diff options
author | Scott Feldman <sfeldma@gmail.com> | 2015-03-06 00:21:16 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-03-06 00:24:58 -0500 |
commit | 104616e74e0b464d449fdd2ee2f547d2fad71610 (patch) | |
tree | d4b32f6edd854bf4188abcea58ec84616a466df4 | |
parent | 5e8d90497d65f528c54015644095ace6e330fd8e (diff) |
switchdev: don't support custom ip rules, for now
Keep switchdev FIB offload model simple for now and don't allow custom ip
rules.
Signed-off-by: Scott Feldman <sfeldma@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/net/ip_fib.h | 2 | ||||
-rw-r--r-- | net/ipv4/fib_frontend.c | 13 | ||||
-rw-r--r-- | net/ipv4/fib_rules.c | 3 | ||||
-rw-r--r-- | net/ipv4/fib_trie.c | 61 | ||||
-rw-r--r-- | net/switchdev/switchdev.c | 4 |
5 files changed, 83 insertions, 0 deletions
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h index 825cb2800908..1657604c5dd3 100644 --- a/include/net/ip_fib.h +++ b/include/net/ip_fib.h | |||
@@ -196,6 +196,7 @@ int fib_table_delete(struct fib_table *, struct fib_config *); | |||
196 | int fib_table_dump(struct fib_table *table, struct sk_buff *skb, | 196 | int fib_table_dump(struct fib_table *table, struct sk_buff *skb, |
197 | struct netlink_callback *cb); | 197 | struct netlink_callback *cb); |
198 | int fib_table_flush(struct fib_table *table); | 198 | int fib_table_flush(struct fib_table *table); |
199 | void fib_table_flush_external(struct fib_table *table); | ||
199 | void fib_free_table(struct fib_table *tb); | 200 | void fib_free_table(struct fib_table *tb); |
200 | 201 | ||
201 | 202 | ||
@@ -308,6 +309,7 @@ static inline int fib_num_tclassid_users(struct net *net) | |||
308 | return 0; | 309 | return 0; |
309 | } | 310 | } |
310 | #endif | 311 | #endif |
312 | void fib_flush_external(struct net *net); | ||
311 | 313 | ||
312 | /* Exported by fib_semantics.c */ | 314 | /* Exported by fib_semantics.c */ |
313 | int ip_fib_check_default(__be32 gw, struct net_device *dev); | 315 | int ip_fib_check_default(__be32 gw, struct net_device *dev); |
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 220c4b4af4cf..e067770235bf 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c | |||
@@ -144,6 +144,19 @@ static void fib_flush(struct net *net) | |||
144 | rt_cache_flush(net); | 144 | rt_cache_flush(net); |
145 | } | 145 | } |
146 | 146 | ||
147 | void fib_flush_external(struct net *net) | ||
148 | { | ||
149 | struct fib_table *tb; | ||
150 | struct hlist_head *head; | ||
151 | unsigned int h; | ||
152 | |||
153 | for (h = 0; h < FIB_TABLE_HASHSZ; h++) { | ||
154 | head = &net->ipv4.fib_table_hash[h]; | ||
155 | hlist_for_each_entry(tb, head, tb_hlist) | ||
156 | fib_table_flush_external(tb); | ||
157 | } | ||
158 | } | ||
159 | |||
147 | /* | 160 | /* |
148 | * Find address type as if only "dev" was present in the system. If | 161 | * Find address type as if only "dev" was present in the system. If |
149 | * on_dev is NULL then all interfaces are taken into consideration. | 162 | * on_dev is NULL then all interfaces are taken into consideration. |
diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c index d3db718be51d..190d0d00d744 100644 --- a/net/ipv4/fib_rules.c +++ b/net/ipv4/fib_rules.c | |||
@@ -209,6 +209,8 @@ static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb, | |||
209 | rule4->tos = frh->tos; | 209 | rule4->tos = frh->tos; |
210 | 210 | ||
211 | net->ipv4.fib_has_custom_rules = true; | 211 | net->ipv4.fib_has_custom_rules = true; |
212 | fib_flush_external(rule->fr_net); | ||
213 | |||
212 | err = 0; | 214 | err = 0; |
213 | errout: | 215 | errout: |
214 | return err; | 216 | return err; |
@@ -224,6 +226,7 @@ static void fib4_rule_delete(struct fib_rule *rule) | |||
224 | net->ipv4.fib_num_tclassid_users--; | 226 | net->ipv4.fib_num_tclassid_users--; |
225 | #endif | 227 | #endif |
226 | net->ipv4.fib_has_custom_rules = true; | 228 | net->ipv4.fib_has_custom_rules = true; |
229 | fib_flush_external(rule->fr_net); | ||
227 | } | 230 | } |
228 | 231 | ||
229 | static int fib4_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh, | 232 | static int fib4_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh, |
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index fae34ad4bb1a..2de43956c9d0 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c | |||
@@ -1536,6 +1536,67 @@ found: | |||
1536 | return n; | 1536 | return n; |
1537 | } | 1537 | } |
1538 | 1538 | ||
1539 | /* Caller must hold RTNL */ | ||
1540 | void fib_table_flush_external(struct fib_table *tb) | ||
1541 | { | ||
1542 | struct trie *t = (struct trie *)tb->tb_data; | ||
1543 | struct fib_alias *fa; | ||
1544 | struct tnode *n, *pn; | ||
1545 | unsigned long cindex; | ||
1546 | unsigned char slen; | ||
1547 | int found = 0; | ||
1548 | |||
1549 | n = rcu_dereference(t->trie); | ||
1550 | if (!n) | ||
1551 | return; | ||
1552 | |||
1553 | pn = NULL; | ||
1554 | cindex = 0; | ||
1555 | |||
1556 | while (IS_TNODE(n)) { | ||
1557 | /* record pn and cindex for leaf walking */ | ||
1558 | pn = n; | ||
1559 | cindex = 1ul << n->bits; | ||
1560 | backtrace: | ||
1561 | /* walk trie in reverse order */ | ||
1562 | do { | ||
1563 | while (!(cindex--)) { | ||
1564 | t_key pkey = pn->key; | ||
1565 | |||
1566 | n = pn; | ||
1567 | pn = node_parent(n); | ||
1568 | |||
1569 | /* resize completed node */ | ||
1570 | resize(t, n); | ||
1571 | |||
1572 | /* if we got the root we are done */ | ||
1573 | if (!pn) | ||
1574 | return; | ||
1575 | |||
1576 | cindex = get_index(pkey, pn); | ||
1577 | } | ||
1578 | |||
1579 | /* grab the next available node */ | ||
1580 | n = tnode_get_child(pn, cindex); | ||
1581 | } while (!n); | ||
1582 | } | ||
1583 | |||
1584 | hlist_for_each_entry(fa, &n->leaf, fa_list) { | ||
1585 | struct fib_info *fi = fa->fa_info; | ||
1586 | |||
1587 | if (fi && (fi->fib_flags & RTNH_F_EXTERNAL)) { | ||
1588 | netdev_switch_fib_ipv4_del(n->key, | ||
1589 | KEYLENGTH - fa->fa_slen, | ||
1590 | fi, fa->fa_tos, | ||
1591 | fa->fa_type, tb->tb_id); | ||
1592 | } | ||
1593 | } | ||
1594 | |||
1595 | /* if trie is leaf only loop is completed */ | ||
1596 | if (pn) | ||
1597 | goto backtrace; | ||
1598 | } | ||
1599 | |||
1539 | /* Caller must hold RTNL. */ | 1600 | /* Caller must hold RTNL. */ |
1540 | int fib_table_flush(struct fib_table *tb) | 1601 | int fib_table_flush(struct fib_table *tb) |
1541 | { | 1602 | { |
diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c index 3c090f8d071b..81c4c0274b9b 100644 --- a/net/switchdev/switchdev.c +++ b/net/switchdev/switchdev.c | |||
@@ -242,6 +242,10 @@ EXPORT_SYMBOL(ndo_dflt_netdev_switch_port_bridge_dellink); | |||
242 | int netdev_switch_fib_ipv4_add(u32 dst, int dst_len, struct fib_info *fi, | 242 | int netdev_switch_fib_ipv4_add(u32 dst, int dst_len, struct fib_info *fi, |
243 | u8 tos, u8 type, u32 tb_id) | 243 | u8 tos, u8 type, u32 tb_id) |
244 | { | 244 | { |
245 | /* Don't offload route if using custom ip rules */ | ||
246 | if (fi->fib_net->ipv4.fib_has_custom_rules) | ||
247 | return 0; | ||
248 | |||
245 | return 0; | 249 | return 0; |
246 | } | 250 | } |
247 | EXPORT_SYMBOL(netdev_switch_fib_ipv4_add); | 251 | EXPORT_SYMBOL(netdev_switch_fib_ipv4_add); |