|
71 | 71 | #include <net/tcp.h> |
72 | 72 | #include <net/flow_dissector.h> |
73 | 73 |
|
| 74 | +#if IS_ENABLED(CONFIG_NF_CONNTRACK) |
| 75 | +#include <net/netfilter/nf_conntrack_core.h> |
| 76 | +#endif |
| 77 | + |
74 | 78 | #define CAKE_SET_WAYS (8) |
75 | 79 | #define CAKE_MAX_TINS (8) |
76 | 80 | #define CAKE_QUEUES (1024) |
@@ -516,6 +520,29 @@ static bool cobalt_should_drop(struct cobalt_vars *vars, |
516 | 520 | return drop; |
517 | 521 | } |
518 | 522 |
|
| 523 | +static void cake_update_flowkeys(struct flow_keys *keys, |
| 524 | + const struct sk_buff *skb) |
| 525 | +{ |
| 526 | +#if IS_ENABLED(CONFIG_NF_CONNTRACK) |
| 527 | + struct nf_conntrack_tuple tuple = {}; |
| 528 | + bool rev = !skb->_nfct; |
| 529 | + |
| 530 | + if (tc_skb_protocol(skb) != htons(ETH_P_IP)) |
| 531 | + return; |
| 532 | + |
| 533 | + if (!nf_ct_get_tuple_skb(&tuple, skb)) |
| 534 | + return; |
| 535 | + |
| 536 | + keys->addrs.v4addrs.src = rev ? tuple.dst.u3.ip : tuple.src.u3.ip; |
| 537 | + keys->addrs.v4addrs.dst = rev ? tuple.src.u3.ip : tuple.dst.u3.ip; |
| 538 | + |
| 539 | + if (keys->ports.ports) { |
| 540 | + keys->ports.src = rev ? tuple.dst.u.all : tuple.src.u.all; |
| 541 | + keys->ports.dst = rev ? tuple.src.u.all : tuple.dst.u.all; |
| 542 | + } |
| 543 | +#endif |
| 544 | +} |
| 545 | + |
519 | 546 | /* Cake has several subtle multiple bit settings. In these cases you |
520 | 547 | * would be matching triple isolate mode as well. |
521 | 548 | */ |
@@ -543,6 +570,9 @@ static u32 cake_hash(struct cake_tin_data *q, const struct sk_buff *skb, |
543 | 570 | skb_flow_dissect_flow_keys(skb, &keys, |
544 | 571 | FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL); |
545 | 572 |
|
| 573 | + if (flow_mode & CAKE_FLOW_NAT_FLAG) |
| 574 | + cake_update_flowkeys(&keys, skb); |
| 575 | + |
546 | 576 | /* flow_hash_from_keys() sorts the addresses by value, so we have |
547 | 577 | * to preserve their order in a separate data structure to treat |
548 | 578 | * src and dst host addresses as independently selectable. |
@@ -1939,12 +1969,25 @@ static int cake_change(struct Qdisc *sch, struct nlattr *opt, |
1939 | 1969 | if (err < 0) |
1940 | 1970 | return err; |
1941 | 1971 |
|
| 1972 | + if (tb[TCA_CAKE_NAT]) { |
| 1973 | +#if IS_ENABLED(CONFIG_NF_CONNTRACK) |
| 1974 | + q->flow_mode &= ~CAKE_FLOW_NAT_FLAG; |
| 1975 | + q->flow_mode |= CAKE_FLOW_NAT_FLAG * |
| 1976 | + !!nla_get_u32(tb[TCA_CAKE_NAT]); |
| 1977 | +#else |
| 1978 | + NL_SET_ERR_MSG_ATTR(extack, tb[TCA_CAKE_NAT], |
| 1979 | + "No conntrack support in kernel"); |
| 1980 | + return -EOPNOTSUPP; |
| 1981 | +#endif |
| 1982 | + } |
| 1983 | + |
1942 | 1984 | if (tb[TCA_CAKE_BASE_RATE64]) |
1943 | 1985 | q->rate_bps = nla_get_u64(tb[TCA_CAKE_BASE_RATE64]); |
1944 | 1986 |
|
1945 | 1987 | if (tb[TCA_CAKE_FLOW_MODE]) |
1946 | | - q->flow_mode = (nla_get_u32(tb[TCA_CAKE_FLOW_MODE]) & |
1947 | | - CAKE_FLOW_MASK); |
| 1988 | + q->flow_mode = ((q->flow_mode & CAKE_FLOW_NAT_FLAG) | |
| 1989 | + (nla_get_u32(tb[TCA_CAKE_FLOW_MODE]) & |
| 1990 | + CAKE_FLOW_MASK)); |
1948 | 1991 |
|
1949 | 1992 | if (tb[TCA_CAKE_RTT]) { |
1950 | 1993 | q->interval = nla_get_u32(tb[TCA_CAKE_RTT]); |
@@ -2111,6 +2154,10 @@ static int cake_dump(struct Qdisc *sch, struct sk_buff *skb) |
2111 | 2154 | if (nla_put_u32(skb, TCA_CAKE_ACK_FILTER, q->ack_filter)) |
2112 | 2155 | goto nla_put_failure; |
2113 | 2156 |
|
| 2157 | + if (nla_put_u32(skb, TCA_CAKE_NAT, |
| 2158 | + !!(q->flow_mode & CAKE_FLOW_NAT_FLAG))) |
| 2159 | + goto nla_put_failure; |
| 2160 | + |
2114 | 2161 | return nla_nest_end(skb, opts); |
2115 | 2162 |
|
2116 | 2163 | nla_put_failure: |
|
0 commit comments