aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorScott Feldman <sfeldma@gmail.com>2015-03-06 00:21:16 -0500
committerDavid S. Miller <davem@davemloft.net>2015-03-06 00:24:58 -0500
commit104616e74e0b464d449fdd2ee2f547d2fad71610 (patch)
treed4b32f6edd854bf4188abcea58ec84616a466df4
parent5e8d90497d65f528c54015644095ace6e330fd8e (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.h2
-rw-r--r--net/ipv4/fib_frontend.c13
-rw-r--r--net/ipv4/fib_rules.c3
-rw-r--r--net/ipv4/fib_trie.c61
-rw-r--r--net/switchdev/switchdev.c4
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 *);
196int fib_table_dump(struct fib_table *table, struct sk_buff *skb, 196int fib_table_dump(struct fib_table *table, struct sk_buff *skb,
197 struct netlink_callback *cb); 197 struct netlink_callback *cb);
198int fib_table_flush(struct fib_table *table); 198int fib_table_flush(struct fib_table *table);
199void fib_table_flush_external(struct fib_table *table);
199void fib_free_table(struct fib_table *tb); 200void 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
312void fib_flush_external(struct net *net);
311 313
312/* Exported by fib_semantics.c */ 314/* Exported by fib_semantics.c */
313int ip_fib_check_default(__be32 gw, struct net_device *dev); 315int 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
147void 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;
213errout: 215errout:
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
229static int fib4_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh, 232static 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 */
1540void 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;
1560backtrace:
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. */
1540int fib_table_flush(struct fib_table *tb) 1601int 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);
242int netdev_switch_fib_ipv4_add(u32 dst, int dst_len, struct fib_info *fi, 242int 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}
247EXPORT_SYMBOL(netdev_switch_fib_ipv4_add); 251EXPORT_SYMBOL(netdev_switch_fib_ipv4_add);