diff options
author | Jiri Pirko <jiri@mellanox.com> | 2016-09-26 06:52:33 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-09-28 04:48:00 -0400 |
commit | 347e3b28c1ba24c1ae2f30290d8247480ab9ce14 (patch) | |
tree | b84cd9ae18da57455f7e3ede13c2ef6522eecff8 | |
parent | 936bd486564aa3edb52313aa7c2e7381e0bcaba3 (diff) |
switchdev: remove FIB offload infrastructure
Since this is now taken care of by FIB notifier, remove the code, with
all unused dependencies.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/net/ip_fib.h | 2 | ||||
-rw-r--r-- | include/net/switchdev.h | 40 | ||||
-rw-r--r-- | net/ipv4/fib_frontend.c | 13 | ||||
-rw-r--r-- | net/ipv4/fib_rules.c | 2 | ||||
-rw-r--r-- | net/ipv4/fib_trie.c | 104 | ||||
-rw-r--r-- | net/switchdev/switchdev.c | 181 |
6 files changed, 1 insertions, 341 deletions
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h index ffccf1787914..b9314b48e39f 100644 --- a/include/net/ip_fib.h +++ b/include/net/ip_fib.h | |||
@@ -243,7 +243,6 @@ int fib_table_dump(struct fib_table *table, struct sk_buff *skb, | |||
243 | struct netlink_callback *cb); | 243 | struct netlink_callback *cb); |
244 | int fib_table_flush(struct net *net, struct fib_table *table); | 244 | int fib_table_flush(struct net *net, struct fib_table *table); |
245 | struct fib_table *fib_trie_unmerge(struct fib_table *main_tb); | 245 | struct fib_table *fib_trie_unmerge(struct fib_table *main_tb); |
246 | void fib_table_flush_external(struct fib_table *table); | ||
247 | void fib_free_table(struct fib_table *tb); | 246 | void fib_free_table(struct fib_table *tb); |
248 | 247 | ||
249 | #ifndef CONFIG_IP_MULTIPLE_TABLES | 248 | #ifndef CONFIG_IP_MULTIPLE_TABLES |
@@ -356,7 +355,6 @@ static inline int fib_num_tclassid_users(struct net *net) | |||
356 | } | 355 | } |
357 | #endif | 356 | #endif |
358 | int fib_unmerge(struct net *net); | 357 | int fib_unmerge(struct net *net); |
359 | void fib_flush_external(struct net *net); | ||
360 | 358 | ||
361 | /* Exported by fib_semantics.c */ | 359 | /* Exported by fib_semantics.c */ |
362 | int ip_fib_check_default(__be32 gw, struct net_device *dev); | 360 | int ip_fib_check_default(__be32 gw, struct net_device *dev); |
diff --git a/include/net/switchdev.h b/include/net/switchdev.h index 729fe1534160..eba80c4fc56f 100644 --- a/include/net/switchdev.h +++ b/include/net/switchdev.h | |||
@@ -68,7 +68,6 @@ struct switchdev_attr { | |||
68 | enum switchdev_obj_id { | 68 | enum switchdev_obj_id { |
69 | SWITCHDEV_OBJ_ID_UNDEFINED, | 69 | SWITCHDEV_OBJ_ID_UNDEFINED, |
70 | SWITCHDEV_OBJ_ID_PORT_VLAN, | 70 | SWITCHDEV_OBJ_ID_PORT_VLAN, |
71 | SWITCHDEV_OBJ_ID_IPV4_FIB, | ||
72 | SWITCHDEV_OBJ_ID_PORT_FDB, | 71 | SWITCHDEV_OBJ_ID_PORT_FDB, |
73 | SWITCHDEV_OBJ_ID_PORT_MDB, | 72 | SWITCHDEV_OBJ_ID_PORT_MDB, |
74 | }; | 73 | }; |
@@ -92,21 +91,6 @@ struct switchdev_obj_port_vlan { | |||
92 | #define SWITCHDEV_OBJ_PORT_VLAN(obj) \ | 91 | #define SWITCHDEV_OBJ_PORT_VLAN(obj) \ |
93 | container_of(obj, struct switchdev_obj_port_vlan, obj) | 92 | container_of(obj, struct switchdev_obj_port_vlan, obj) |
94 | 93 | ||
95 | /* SWITCHDEV_OBJ_ID_IPV4_FIB */ | ||
96 | struct switchdev_obj_ipv4_fib { | ||
97 | struct switchdev_obj obj; | ||
98 | u32 dst; | ||
99 | int dst_len; | ||
100 | struct fib_info *fi; | ||
101 | u8 tos; | ||
102 | u8 type; | ||
103 | u32 nlflags; | ||
104 | u32 tb_id; | ||
105 | }; | ||
106 | |||
107 | #define SWITCHDEV_OBJ_IPV4_FIB(obj) \ | ||
108 | container_of(obj, struct switchdev_obj_ipv4_fib, obj) | ||
109 | |||
110 | /* SWITCHDEV_OBJ_ID_PORT_FDB */ | 94 | /* SWITCHDEV_OBJ_ID_PORT_FDB */ |
111 | struct switchdev_obj_port_fdb { | 95 | struct switchdev_obj_port_fdb { |
112 | struct switchdev_obj obj; | 96 | struct switchdev_obj obj; |
@@ -209,11 +193,6 @@ int switchdev_port_bridge_setlink(struct net_device *dev, | |||
209 | struct nlmsghdr *nlh, u16 flags); | 193 | struct nlmsghdr *nlh, u16 flags); |
210 | int switchdev_port_bridge_dellink(struct net_device *dev, | 194 | int switchdev_port_bridge_dellink(struct net_device *dev, |
211 | struct nlmsghdr *nlh, u16 flags); | 195 | struct nlmsghdr *nlh, u16 flags); |
212 | int switchdev_fib_ipv4_add(u32 dst, int dst_len, struct fib_info *fi, | ||
213 | u8 tos, u8 type, u32 nlflags, u32 tb_id); | ||
214 | int switchdev_fib_ipv4_del(u32 dst, int dst_len, struct fib_info *fi, | ||
215 | u8 tos, u8 type, u32 tb_id); | ||
216 | void switchdev_fib_ipv4_abort(struct fib_info *fi); | ||
217 | int switchdev_port_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], | 196 | int switchdev_port_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], |
218 | struct net_device *dev, const unsigned char *addr, | 197 | struct net_device *dev, const unsigned char *addr, |
219 | u16 vid, u16 nlm_flags); | 198 | u16 vid, u16 nlm_flags); |
@@ -304,25 +283,6 @@ static inline int switchdev_port_bridge_dellink(struct net_device *dev, | |||
304 | return -EOPNOTSUPP; | 283 | return -EOPNOTSUPP; |
305 | } | 284 | } |
306 | 285 | ||
307 | static inline int switchdev_fib_ipv4_add(u32 dst, int dst_len, | ||
308 | struct fib_info *fi, | ||
309 | u8 tos, u8 type, | ||
310 | u32 nlflags, u32 tb_id) | ||
311 | { | ||
312 | return 0; | ||
313 | } | ||
314 | |||
315 | static inline int switchdev_fib_ipv4_del(u32 dst, int dst_len, | ||
316 | struct fib_info *fi, | ||
317 | u8 tos, u8 type, u32 tb_id) | ||
318 | { | ||
319 | return 0; | ||
320 | } | ||
321 | |||
322 | static inline void switchdev_fib_ipv4_abort(struct fib_info *fi) | ||
323 | { | ||
324 | } | ||
325 | |||
326 | static inline int switchdev_port_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], | 286 | static inline int switchdev_port_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], |
327 | struct net_device *dev, | 287 | struct net_device *dev, |
328 | const unsigned char *addr, | 288 | const unsigned char *addr, |
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 86c43dc9a60e..c3b80478226e 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c | |||
@@ -189,19 +189,6 @@ static void fib_flush(struct net *net) | |||
189 | rt_cache_flush(net); | 189 | rt_cache_flush(net); |
190 | } | 190 | } |
191 | 191 | ||
192 | void fib_flush_external(struct net *net) | ||
193 | { | ||
194 | struct fib_table *tb; | ||
195 | struct hlist_head *head; | ||
196 | unsigned int h; | ||
197 | |||
198 | for (h = 0; h < FIB_TABLE_HASHSZ; h++) { | ||
199 | head = &net->ipv4.fib_table_hash[h]; | ||
200 | hlist_for_each_entry(tb, head, tb_hlist) | ||
201 | fib_table_flush_external(tb); | ||
202 | } | ||
203 | } | ||
204 | |||
205 | /* | 192 | /* |
206 | * Find address type as if only "dev" was present in the system. If | 193 | * Find address type as if only "dev" was present in the system. If |
207 | * on_dev is NULL then all interfaces are taken into consideration. | 194 | * 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 ebadf6b99499..2e50062f642d 100644 --- a/net/ipv4/fib_rules.c +++ b/net/ipv4/fib_rules.c | |||
@@ -228,7 +228,6 @@ static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb, | |||
228 | rule4->tos = frh->tos; | 228 | rule4->tos = frh->tos; |
229 | 229 | ||
230 | net->ipv4.fib_has_custom_rules = true; | 230 | net->ipv4.fib_has_custom_rules = true; |
231 | fib_flush_external(rule->fr_net); | ||
232 | call_fib_rule_notifiers(net, FIB_EVENT_RULE_ADD); | 231 | call_fib_rule_notifiers(net, FIB_EVENT_RULE_ADD); |
233 | 232 | ||
234 | err = 0; | 233 | err = 0; |
@@ -251,7 +250,6 @@ static int fib4_rule_delete(struct fib_rule *rule) | |||
251 | net->ipv4.fib_num_tclassid_users--; | 250 | net->ipv4.fib_num_tclassid_users--; |
252 | #endif | 251 | #endif |
253 | net->ipv4.fib_has_custom_rules = true; | 252 | net->ipv4.fib_has_custom_rules = true; |
254 | fib_flush_external(rule->fr_net); | ||
255 | call_fib_rule_notifiers(net, FIB_EVENT_RULE_DEL); | 253 | call_fib_rule_notifiers(net, FIB_EVENT_RULE_DEL); |
256 | errout: | 254 | errout: |
257 | return err; | 255 | return err; |
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index 51a4537eb145..31cef3602585 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c | |||
@@ -81,7 +81,6 @@ | |||
81 | #include <net/tcp.h> | 81 | #include <net/tcp.h> |
82 | #include <net/sock.h> | 82 | #include <net/sock.h> |
83 | #include <net/ip_fib.h> | 83 | #include <net/ip_fib.h> |
84 | #include <net/switchdev.h> | ||
85 | #include <trace/events/fib.h> | 84 | #include <trace/events/fib.h> |
86 | #include "fib_lookup.h" | 85 | #include "fib_lookup.h" |
87 | 86 | ||
@@ -1215,17 +1214,6 @@ int fib_table_insert(struct net *net, struct fib_table *tb, | |||
1215 | new_fa->tb_id = tb->tb_id; | 1214 | new_fa->tb_id = tb->tb_id; |
1216 | new_fa->fa_default = -1; | 1215 | new_fa->fa_default = -1; |
1217 | 1216 | ||
1218 | err = switchdev_fib_ipv4_add(key, plen, fi, | ||
1219 | new_fa->fa_tos, | ||
1220 | cfg->fc_type, | ||
1221 | cfg->fc_nlflags, | ||
1222 | tb->tb_id); | ||
1223 | if (err) { | ||
1224 | switchdev_fib_ipv4_abort(fi); | ||
1225 | kmem_cache_free(fn_alias_kmem, new_fa); | ||
1226 | goto out; | ||
1227 | } | ||
1228 | |||
1229 | hlist_replace_rcu(&fa->fa_list, &new_fa->fa_list); | 1217 | hlist_replace_rcu(&fa->fa_list, &new_fa->fa_list); |
1230 | 1218 | ||
1231 | alias_free_mem_rcu(fa); | 1219 | alias_free_mem_rcu(fa); |
@@ -1273,18 +1261,10 @@ int fib_table_insert(struct net *net, struct fib_table *tb, | |||
1273 | new_fa->tb_id = tb->tb_id; | 1261 | new_fa->tb_id = tb->tb_id; |
1274 | new_fa->fa_default = -1; | 1262 | new_fa->fa_default = -1; |
1275 | 1263 | ||
1276 | /* (Optionally) offload fib entry to switch hardware. */ | ||
1277 | err = switchdev_fib_ipv4_add(key, plen, fi, tos, cfg->fc_type, | ||
1278 | cfg->fc_nlflags, tb->tb_id); | ||
1279 | if (err) { | ||
1280 | switchdev_fib_ipv4_abort(fi); | ||
1281 | goto out_free_new_fa; | ||
1282 | } | ||
1283 | |||
1284 | /* Insert new entry to the list. */ | 1264 | /* Insert new entry to the list. */ |
1285 | err = fib_insert_alias(t, tp, l, new_fa, fa, key); | 1265 | err = fib_insert_alias(t, tp, l, new_fa, fa, key); |
1286 | if (err) | 1266 | if (err) |
1287 | goto out_sw_fib_del; | 1267 | goto out_free_new_fa; |
1288 | 1268 | ||
1289 | if (!plen) | 1269 | if (!plen) |
1290 | tb->tb_num_default++; | 1270 | tb->tb_num_default++; |
@@ -1297,8 +1277,6 @@ int fib_table_insert(struct net *net, struct fib_table *tb, | |||
1297 | succeeded: | 1277 | succeeded: |
1298 | return 0; | 1278 | return 0; |
1299 | 1279 | ||
1300 | out_sw_fib_del: | ||
1301 | switchdev_fib_ipv4_del(key, plen, fi, tos, cfg->fc_type, tb->tb_id); | ||
1302 | out_free_new_fa: | 1280 | out_free_new_fa: |
1303 | kmem_cache_free(fn_alias_kmem, new_fa); | 1281 | kmem_cache_free(fn_alias_kmem, new_fa); |
1304 | out: | 1282 | out: |
@@ -1591,9 +1569,6 @@ int fib_table_delete(struct net *net, struct fib_table *tb, | |||
1591 | if (!fa_to_delete) | 1569 | if (!fa_to_delete) |
1592 | return -ESRCH; | 1570 | return -ESRCH; |
1593 | 1571 | ||
1594 | switchdev_fib_ipv4_del(key, plen, fa_to_delete->fa_info, tos, | ||
1595 | cfg->fc_type, tb->tb_id); | ||
1596 | |||
1597 | call_fib_entry_notifiers(net, FIB_EVENT_ENTRY_DEL, key, plen, | 1572 | call_fib_entry_notifiers(net, FIB_EVENT_ENTRY_DEL, key, plen, |
1598 | fa_to_delete->fa_info, tos, cfg->fc_type, | 1573 | fa_to_delete->fa_info, tos, cfg->fc_type, |
1599 | tb->tb_id, 0); | 1574 | tb->tb_id, 0); |
@@ -1785,80 +1760,6 @@ out: | |||
1785 | return NULL; | 1760 | return NULL; |
1786 | } | 1761 | } |
1787 | 1762 | ||
1788 | /* Caller must hold RTNL */ | ||
1789 | void fib_table_flush_external(struct fib_table *tb) | ||
1790 | { | ||
1791 | struct trie *t = (struct trie *)tb->tb_data; | ||
1792 | struct key_vector *pn = t->kv; | ||
1793 | unsigned long cindex = 1; | ||
1794 | struct hlist_node *tmp; | ||
1795 | struct fib_alias *fa; | ||
1796 | |||
1797 | /* walk trie in reverse order */ | ||
1798 | for (;;) { | ||
1799 | unsigned char slen = 0; | ||
1800 | struct key_vector *n; | ||
1801 | |||
1802 | if (!(cindex--)) { | ||
1803 | t_key pkey = pn->key; | ||
1804 | |||
1805 | /* cannot resize the trie vector */ | ||
1806 | if (IS_TRIE(pn)) | ||
1807 | break; | ||
1808 | |||
1809 | /* resize completed node */ | ||
1810 | pn = resize(t, pn); | ||
1811 | cindex = get_index(pkey, pn); | ||
1812 | |||
1813 | continue; | ||
1814 | } | ||
1815 | |||
1816 | /* grab the next available node */ | ||
1817 | n = get_child(pn, cindex); | ||
1818 | if (!n) | ||
1819 | continue; | ||
1820 | |||
1821 | if (IS_TNODE(n)) { | ||
1822 | /* record pn and cindex for leaf walking */ | ||
1823 | pn = n; | ||
1824 | cindex = 1ul << n->bits; | ||
1825 | |||
1826 | continue; | ||
1827 | } | ||
1828 | |||
1829 | hlist_for_each_entry_safe(fa, tmp, &n->leaf, fa_list) { | ||
1830 | struct fib_info *fi = fa->fa_info; | ||
1831 | |||
1832 | /* if alias was cloned to local then we just | ||
1833 | * need to remove the local copy from main | ||
1834 | */ | ||
1835 | if (tb->tb_id != fa->tb_id) { | ||
1836 | hlist_del_rcu(&fa->fa_list); | ||
1837 | alias_free_mem_rcu(fa); | ||
1838 | continue; | ||
1839 | } | ||
1840 | |||
1841 | /* record local slen */ | ||
1842 | slen = fa->fa_slen; | ||
1843 | |||
1844 | if (!fi || !(fi->fib_flags & RTNH_F_OFFLOAD)) | ||
1845 | continue; | ||
1846 | |||
1847 | switchdev_fib_ipv4_del(n->key, KEYLENGTH - fa->fa_slen, | ||
1848 | fi, fa->fa_tos, fa->fa_type, | ||
1849 | tb->tb_id); | ||
1850 | } | ||
1851 | |||
1852 | /* update leaf slen */ | ||
1853 | n->slen = slen; | ||
1854 | |||
1855 | if (hlist_empty(&n->leaf)) { | ||
1856 | put_child_root(pn, n->key, NULL); | ||
1857 | node_free(n); | ||
1858 | } | ||
1859 | } | ||
1860 | } | ||
1861 | |||
1862 | /* Caller must hold RTNL. */ | 1763 | /* Caller must hold RTNL. */ |
1863 | int fib_table_flush(struct net *net, struct fib_table *tb) | 1764 | int fib_table_flush(struct net *net, struct fib_table *tb) |
1864 | { | 1765 | { |
@@ -1909,9 +1810,6 @@ int fib_table_flush(struct net *net, struct fib_table *tb) | |||
1909 | continue; | 1810 | continue; |
1910 | } | 1811 | } |
1911 | 1812 | ||
1912 | switchdev_fib_ipv4_del(n->key, KEYLENGTH - fa->fa_slen, | ||
1913 | fi, fa->fa_tos, fa->fa_type, | ||
1914 | tb->tb_id); | ||
1915 | call_fib_entry_notifiers(net, FIB_EVENT_ENTRY_DEL, | 1813 | call_fib_entry_notifiers(net, FIB_EVENT_ENTRY_DEL, |
1916 | n->key, | 1814 | n->key, |
1917 | KEYLENGTH - fa->fa_slen, | 1815 | KEYLENGTH - fa->fa_slen, |
diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c index abd8d2a38a7d..02beb35f577f 100644 --- a/net/switchdev/switchdev.c +++ b/net/switchdev/switchdev.c | |||
@@ -21,7 +21,6 @@ | |||
21 | #include <linux/workqueue.h> | 21 | #include <linux/workqueue.h> |
22 | #include <linux/if_vlan.h> | 22 | #include <linux/if_vlan.h> |
23 | #include <linux/rtnetlink.h> | 23 | #include <linux/rtnetlink.h> |
24 | #include <net/ip_fib.h> | ||
25 | #include <net/switchdev.h> | 24 | #include <net/switchdev.h> |
26 | 25 | ||
27 | /** | 26 | /** |
@@ -344,8 +343,6 @@ static size_t switchdev_obj_size(const struct switchdev_obj *obj) | |||
344 | switch (obj->id) { | 343 | switch (obj->id) { |
345 | case SWITCHDEV_OBJ_ID_PORT_VLAN: | 344 | case SWITCHDEV_OBJ_ID_PORT_VLAN: |
346 | return sizeof(struct switchdev_obj_port_vlan); | 345 | return sizeof(struct switchdev_obj_port_vlan); |
347 | case SWITCHDEV_OBJ_ID_IPV4_FIB: | ||
348 | return sizeof(struct switchdev_obj_ipv4_fib); | ||
349 | case SWITCHDEV_OBJ_ID_PORT_FDB: | 346 | case SWITCHDEV_OBJ_ID_PORT_FDB: |
350 | return sizeof(struct switchdev_obj_port_fdb); | 347 | return sizeof(struct switchdev_obj_port_fdb); |
351 | case SWITCHDEV_OBJ_ID_PORT_MDB: | 348 | case SWITCHDEV_OBJ_ID_PORT_MDB: |
@@ -1108,184 +1105,6 @@ int switchdev_port_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb, | |||
1108 | } | 1105 | } |
1109 | EXPORT_SYMBOL_GPL(switchdev_port_fdb_dump); | 1106 | EXPORT_SYMBOL_GPL(switchdev_port_fdb_dump); |
1110 | 1107 | ||
1111 | static struct net_device *switchdev_get_lowest_dev(struct net_device *dev) | ||
1112 | { | ||
1113 | const struct switchdev_ops *ops = dev->switchdev_ops; | ||
1114 | struct net_device *lower_dev; | ||
1115 | struct net_device *port_dev; | ||
1116 | struct list_head *iter; | ||
1117 | |||
1118 | /* Recusively search down until we find a sw port dev. | ||
1119 | * (A sw port dev supports switchdev_port_attr_get). | ||
1120 | */ | ||
1121 | |||
1122 | if (ops && ops->switchdev_port_attr_get) | ||
1123 | return dev; | ||
1124 | |||
1125 | netdev_for_each_lower_dev(dev, lower_dev, iter) { | ||
1126 | port_dev = switchdev_get_lowest_dev(lower_dev); | ||
1127 | if (port_dev) | ||
1128 | return port_dev; | ||
1129 | } | ||
1130 | |||
1131 | return NULL; | ||
1132 | } | ||
1133 | |||
1134 | static struct net_device *switchdev_get_dev_by_nhs(struct fib_info *fi) | ||
1135 | { | ||
1136 | struct switchdev_attr attr = { | ||
1137 | .id = SWITCHDEV_ATTR_ID_PORT_PARENT_ID, | ||
1138 | }; | ||
1139 | struct switchdev_attr prev_attr; | ||
1140 | struct net_device *dev = NULL; | ||
1141 | int nhsel; | ||
1142 | |||
1143 | ASSERT_RTNL(); | ||
1144 | |||
1145 | /* For this route, all nexthop devs must be on the same switch. */ | ||
1146 | |||
1147 | for (nhsel = 0; nhsel < fi->fib_nhs; nhsel++) { | ||
1148 | const struct fib_nh *nh = &fi->fib_nh[nhsel]; | ||
1149 | |||
1150 | if (!nh->nh_dev) | ||
1151 | return NULL; | ||
1152 | |||
1153 | dev = switchdev_get_lowest_dev(nh->nh_dev); | ||
1154 | if (!dev) | ||
1155 | return NULL; | ||
1156 | |||
1157 | attr.orig_dev = dev; | ||
1158 | if (switchdev_port_attr_get(dev, &attr)) | ||
1159 | return NULL; | ||
1160 | |||
1161 | if (nhsel > 0 && | ||
1162 | !netdev_phys_item_id_same(&prev_attr.u.ppid, &attr.u.ppid)) | ||
1163 | return NULL; | ||
1164 | |||
1165 | prev_attr = attr; | ||
1166 | } | ||
1167 | |||
1168 | return dev; | ||
1169 | } | ||
1170 | |||
1171 | /** | ||
1172 | * switchdev_fib_ipv4_add - Add/modify switch IPv4 route entry | ||
1173 | * | ||
1174 | * @dst: route's IPv4 destination address | ||
1175 | * @dst_len: destination address length (prefix length) | ||
1176 | * @fi: route FIB info structure | ||
1177 | * @tos: route TOS | ||
1178 | * @type: route type | ||
1179 | * @nlflags: netlink flags passed in (NLM_F_*) | ||
1180 | * @tb_id: route table ID | ||
1181 | * | ||
1182 | * Add/modify switch IPv4 route entry. | ||
1183 | */ | ||
1184 | int switchdev_fib_ipv4_add(u32 dst, int dst_len, struct fib_info *fi, | ||
1185 | u8 tos, u8 type, u32 nlflags, u32 tb_id) | ||
1186 | { | ||
1187 | struct switchdev_obj_ipv4_fib ipv4_fib = { | ||
1188 | .obj.id = SWITCHDEV_OBJ_ID_IPV4_FIB, | ||
1189 | .dst = dst, | ||
1190 | .dst_len = dst_len, | ||
1191 | .fi = fi, | ||
1192 | .tos = tos, | ||
1193 | .type = type, | ||
1194 | .nlflags = nlflags, | ||
1195 | .tb_id = tb_id, | ||
1196 | }; | ||
1197 | struct net_device *dev; | ||
1198 | int err = 0; | ||
1199 | |||
1200 | /* Don't offload route if using custom ip rules or if | ||
1201 | * IPv4 FIB offloading has been disabled completely. | ||
1202 | */ | ||
1203 | |||
1204 | #ifdef CONFIG_IP_MULTIPLE_TABLES | ||
1205 | if (fi->fib_net->ipv4.fib_has_custom_rules) | ||
1206 | return 0; | ||
1207 | #endif | ||
1208 | |||
1209 | if (fi->fib_net->ipv4.fib_offload_disabled) | ||
1210 | return 0; | ||
1211 | |||
1212 | dev = switchdev_get_dev_by_nhs(fi); | ||
1213 | if (!dev) | ||
1214 | return 0; | ||
1215 | |||
1216 | ipv4_fib.obj.orig_dev = dev; | ||
1217 | err = switchdev_port_obj_add(dev, &ipv4_fib.obj); | ||
1218 | if (!err) | ||
1219 | fib_info_offload_inc(fi); | ||
1220 | |||
1221 | return err == -EOPNOTSUPP ? 0 : err; | ||
1222 | } | ||
1223 | EXPORT_SYMBOL_GPL(switchdev_fib_ipv4_add); | ||
1224 | |||
1225 | /** | ||
1226 | * switchdev_fib_ipv4_del - Delete IPv4 route entry from switch | ||
1227 | * | ||
1228 | * @dst: route's IPv4 destination address | ||
1229 | * @dst_len: destination address length (prefix length) | ||
1230 | * @fi: route FIB info structure | ||
1231 | * @tos: route TOS | ||
1232 | * @type: route type | ||
1233 | * @tb_id: route table ID | ||
1234 | * | ||
1235 | * Delete IPv4 route entry from switch device. | ||
1236 | */ | ||
1237 | int switchdev_fib_ipv4_del(u32 dst, int dst_len, struct fib_info *fi, | ||
1238 | u8 tos, u8 type, u32 tb_id) | ||
1239 | { | ||
1240 | struct switchdev_obj_ipv4_fib ipv4_fib = { | ||
1241 | .obj.id = SWITCHDEV_OBJ_ID_IPV4_FIB, | ||
1242 | .dst = dst, | ||
1243 | .dst_len = dst_len, | ||
1244 | .fi = fi, | ||
1245 | .tos = tos, | ||
1246 | .type = type, | ||
1247 | .nlflags = 0, | ||
1248 | .tb_id = tb_id, | ||
1249 | }; | ||
1250 | struct net_device *dev; | ||
1251 | int err = 0; | ||
1252 | |||
1253 | if (!(fi->fib_flags & RTNH_F_OFFLOAD)) | ||
1254 | return 0; | ||
1255 | |||
1256 | dev = switchdev_get_dev_by_nhs(fi); | ||
1257 | if (!dev) | ||
1258 | return 0; | ||
1259 | |||
1260 | ipv4_fib.obj.orig_dev = dev; | ||
1261 | err = switchdev_port_obj_del(dev, &ipv4_fib.obj); | ||
1262 | if (!err) | ||
1263 | fib_info_offload_dec(fi); | ||
1264 | |||
1265 | return err == -EOPNOTSUPP ? 0 : err; | ||
1266 | } | ||
1267 | EXPORT_SYMBOL_GPL(switchdev_fib_ipv4_del); | ||
1268 | |||
1269 | /** | ||
1270 | * switchdev_fib_ipv4_abort - Abort an IPv4 FIB operation | ||
1271 | * | ||
1272 | * @fi: route FIB info structure | ||
1273 | */ | ||
1274 | void switchdev_fib_ipv4_abort(struct fib_info *fi) | ||
1275 | { | ||
1276 | /* There was a problem installing this route to the offload | ||
1277 | * device. For now, until we come up with more refined | ||
1278 | * policy handling, abruptly end IPv4 fib offloading for | ||
1279 | * for entire net by flushing offload device(s) of all | ||
1280 | * IPv4 routes, and mark IPv4 fib offloading broken from | ||
1281 | * this point forward. | ||
1282 | */ | ||
1283 | |||
1284 | fib_flush_external(fi->fib_net); | ||
1285 | fi->fib_net->ipv4.fib_offload_disabled = true; | ||
1286 | } | ||
1287 | EXPORT_SYMBOL_GPL(switchdev_fib_ipv4_abort); | ||
1288 | |||
1289 | bool switchdev_port_same_parent_id(struct net_device *a, | 1108 | bool switchdev_port_same_parent_id(struct net_device *a, |
1290 | struct net_device *b) | 1109 | struct net_device *b) |
1291 | { | 1110 | { |