aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHannes Frederic Sowa <hannes@stressinduktion.org>2016-04-18 15:19:48 -0400
committerDavid S. Miller <davem@davemloft.net>2016-04-21 15:35:44 -0400
commit681e683ff30ada19f73c17c38a528528dd8824f1 (patch)
treedfb1140e166ecf89f994f667e0cb9e73969845e8
parentb7aade15485a660cbf5161962c284131324a9534 (diff)
geneve: break dependency with netdev drivers
Equivalent to "vxlan: break dependency with netdev drivers", don't autoload geneve module in case the driver is loaded. Instead make the coupling weaker by using netdevice notifiers as proxy. Cc: Jesse Gross <jesse@kernel.org> Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/geneve.c31
-rw-r--r--include/linux/netdevice.h1
-rw-r--r--include/net/geneve.h6
3 files changed, 31 insertions, 7 deletions
diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c
index 512dbe013713..9c40b88fabd5 100644
--- a/drivers/net/geneve.c
+++ b/drivers/net/geneve.c
@@ -1172,7 +1172,7 @@ static struct device_type geneve_type = {
1172 * supply the listening GENEVE udp ports. Callers are expected 1172 * supply the listening GENEVE udp ports. Callers are expected
1173 * to implement the ndo_add_geneve_port. 1173 * to implement the ndo_add_geneve_port.
1174 */ 1174 */
1175void geneve_get_rx_port(struct net_device *dev) 1175static void geneve_push_rx_ports(struct net_device *dev)
1176{ 1176{
1177 struct net *net = dev_net(dev); 1177 struct net *net = dev_net(dev);
1178 struct geneve_net *gn = net_generic(net, geneve_net_id); 1178 struct geneve_net *gn = net_generic(net, geneve_net_id);
@@ -1181,6 +1181,9 @@ void geneve_get_rx_port(struct net_device *dev)
1181 struct sock *sk; 1181 struct sock *sk;
1182 __be16 port; 1182 __be16 port;
1183 1183
1184 if (!dev->netdev_ops->ndo_add_geneve_port)
1185 return;
1186
1184 rcu_read_lock(); 1187 rcu_read_lock();
1185 list_for_each_entry_rcu(gs, &gn->sock_list, list) { 1188 list_for_each_entry_rcu(gs, &gn->sock_list, list) {
1186 sk = gs->sock->sk; 1189 sk = gs->sock->sk;
@@ -1190,7 +1193,6 @@ void geneve_get_rx_port(struct net_device *dev)
1190 } 1193 }
1191 rcu_read_unlock(); 1194 rcu_read_unlock();
1192} 1195}
1193EXPORT_SYMBOL_GPL(geneve_get_rx_port);
1194 1196
1195/* Initialize the device structure. */ 1197/* Initialize the device structure. */
1196static void geneve_setup(struct net_device *dev) 1198static void geneve_setup(struct net_device *dev)
@@ -1538,6 +1540,21 @@ struct net_device *geneve_dev_create_fb(struct net *net, const char *name,
1538} 1540}
1539EXPORT_SYMBOL_GPL(geneve_dev_create_fb); 1541EXPORT_SYMBOL_GPL(geneve_dev_create_fb);
1540 1542
1543static int geneve_netdevice_event(struct notifier_block *unused,
1544 unsigned long event, void *ptr)
1545{
1546 struct net_device *dev = netdev_notifier_info_to_dev(ptr);
1547
1548 if (event == NETDEV_OFFLOAD_PUSH_GENEVE)
1549 geneve_push_rx_ports(dev);
1550
1551 return NOTIFY_DONE;
1552}
1553
1554static struct notifier_block geneve_notifier_block __read_mostly = {
1555 .notifier_call = geneve_netdevice_event,
1556};
1557
1541static __net_init int geneve_init_net(struct net *net) 1558static __net_init int geneve_init_net(struct net *net)
1542{ 1559{
1543 struct geneve_net *gn = net_generic(net, geneve_net_id); 1560 struct geneve_net *gn = net_generic(net, geneve_net_id);
@@ -1590,11 +1607,18 @@ static int __init geneve_init_module(void)
1590 if (rc) 1607 if (rc)
1591 goto out1; 1608 goto out1;
1592 1609
1593 rc = rtnl_link_register(&geneve_link_ops); 1610 rc = register_netdevice_notifier(&geneve_notifier_block);
1594 if (rc) 1611 if (rc)
1595 goto out2; 1612 goto out2;
1596 1613
1614 rc = rtnl_link_register(&geneve_link_ops);
1615 if (rc)
1616 goto out3;
1617
1597 return 0; 1618 return 0;
1619
1620out3:
1621 unregister_netdevice_notifier(&geneve_notifier_block);
1598out2: 1622out2:
1599 unregister_pernet_subsys(&geneve_net_ops); 1623 unregister_pernet_subsys(&geneve_net_ops);
1600out1: 1624out1:
@@ -1605,6 +1629,7 @@ late_initcall(geneve_init_module);
1605static void __exit geneve_cleanup_module(void) 1629static void __exit geneve_cleanup_module(void)
1606{ 1630{
1607 rtnl_link_unregister(&geneve_link_ops); 1631 rtnl_link_unregister(&geneve_link_ops);
1632 unregister_netdevice_notifier(&geneve_notifier_block);
1608 unregister_pernet_subsys(&geneve_net_ops); 1633 unregister_pernet_subsys(&geneve_net_ops);
1609} 1634}
1610module_exit(geneve_cleanup_module); 1635module_exit(geneve_cleanup_module);
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index d4c8cd424f8d..1f6d5db471a2 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2245,6 +2245,7 @@ struct netdev_lag_lower_state_info {
2245#define NETDEV_PRECHANGEUPPER 0x001A 2245#define NETDEV_PRECHANGEUPPER 0x001A
2246#define NETDEV_CHANGELOWERSTATE 0x001B 2246#define NETDEV_CHANGELOWERSTATE 0x001B
2247#define NETDEV_OFFLOAD_PUSH_VXLAN 0x001C 2247#define NETDEV_OFFLOAD_PUSH_VXLAN 0x001C
2248#define NETDEV_OFFLOAD_PUSH_GENEVE 0x001D
2248 2249
2249int register_netdevice_notifier(struct notifier_block *nb); 2250int register_netdevice_notifier(struct notifier_block *nb);
2250int unregister_netdevice_notifier(struct notifier_block *nb); 2251int unregister_netdevice_notifier(struct notifier_block *nb);
diff --git a/include/net/geneve.h b/include/net/geneve.h
index e6c23dc765f7..cb544a530146 100644
--- a/include/net/geneve.h
+++ b/include/net/geneve.h
@@ -62,13 +62,11 @@ struct genevehdr {
62 struct geneve_opt options[]; 62 struct geneve_opt options[];
63}; 63};
64 64
65#if IS_ENABLED(CONFIG_GENEVE)
66void geneve_get_rx_port(struct net_device *netdev);
67#else
68static inline void geneve_get_rx_port(struct net_device *netdev) 65static inline void geneve_get_rx_port(struct net_device *netdev)
69{ 66{
67 ASSERT_RTNL();
68 call_netdevice_notifiers(NETDEV_OFFLOAD_PUSH_GENEVE, netdev);
70} 69}
71#endif
72 70
73#ifdef CONFIG_INET 71#ifdef CONFIG_INET
74struct net_device *geneve_dev_create_fb(struct net *net, const char *name, 72struct net_device *geneve_dev_create_fb(struct net *net, const char *name,