]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - net/ipv4/udp_tunnel.c
net: Combine GENEVE and VXLAN port notifiers into single functions
[mirror_ubuntu-artful-kernel.git] / net / ipv4 / udp_tunnel.c
index 47f12c73d9598bcef8442527f13a434abd6169eb..8174753e64941f720a58cfea43a05b59ca6d1ec2 100644 (file)
@@ -76,6 +76,108 @@ void setup_udp_tunnel_sock(struct net *net, struct socket *sock,
 }
 EXPORT_SYMBOL_GPL(setup_udp_tunnel_sock);
 
+static void __udp_tunnel_push_rx_port(struct net_device *dev,
+                                     struct udp_tunnel_info *ti)
+{
+       switch (ti->type) {
+       case UDP_TUNNEL_TYPE_VXLAN:
+               if (!dev->netdev_ops->ndo_add_vxlan_port)
+                       break;
+
+               dev->netdev_ops->ndo_add_vxlan_port(dev,
+                                                   ti->sa_family,
+                                                   ti->port);
+               break;
+       case UDP_TUNNEL_TYPE_GENEVE:
+               if (!dev->netdev_ops->ndo_add_geneve_port)
+                       break;
+
+               dev->netdev_ops->ndo_add_geneve_port(dev,
+                                                    ti->sa_family,
+                                                    ti->port);
+               break;
+       default:
+               break;
+       }
+}
+
+void udp_tunnel_push_rx_port(struct net_device *dev, struct socket *sock,
+                            unsigned short type)
+{
+       struct sock *sk = sock->sk;
+       struct udp_tunnel_info ti;
+
+       ti.type = type;
+       ti.sa_family = sk->sk_family;
+       ti.port = inet_sk(sk)->inet_sport;
+
+       __udp_tunnel_push_rx_port(dev, &ti);
+}
+EXPORT_SYMBOL_GPL(udp_tunnel_push_rx_port);
+
+/* Notify netdevs that UDP port started listening */
+void udp_tunnel_notify_add_rx_port(struct socket *sock, unsigned short type)
+{
+       struct sock *sk = sock->sk;
+       struct net *net = sock_net(sk);
+       struct udp_tunnel_info ti;
+       struct net_device *dev;
+
+       ti.type = type;
+       ti.sa_family = sk->sk_family;
+       ti.port = inet_sk(sk)->inet_sport;
+
+       rcu_read_lock();
+       for_each_netdev_rcu(net, dev)
+               __udp_tunnel_push_rx_port(dev, &ti);
+       rcu_read_unlock();
+}
+EXPORT_SYMBOL_GPL(udp_tunnel_notify_add_rx_port);
+
+static void __udp_tunnel_pull_rx_port(struct net_device *dev,
+                                     struct udp_tunnel_info *ti)
+{
+       switch (ti->type) {
+       case UDP_TUNNEL_TYPE_VXLAN:
+               if (!dev->netdev_ops->ndo_del_vxlan_port)
+                       break;
+
+               dev->netdev_ops->ndo_del_vxlan_port(dev,
+                                                   ti->sa_family,
+                                                   ti->port);
+               break;
+       case UDP_TUNNEL_TYPE_GENEVE:
+               if (!dev->netdev_ops->ndo_del_geneve_port)
+                       break;
+
+               dev->netdev_ops->ndo_del_geneve_port(dev,
+                                                    ti->sa_family,
+                                                    ti->port);
+               break;
+       default:
+               break;
+       }
+}
+
+/* Notify netdevs that UDP port is no more listening */
+void udp_tunnel_notify_del_rx_port(struct socket *sock, unsigned short type)
+{
+       struct sock *sk = sock->sk;
+       struct net *net = sock_net(sk);
+       struct udp_tunnel_info ti;
+       struct net_device *dev;
+
+       ti.type = type;
+       ti.sa_family = sk->sk_family;
+       ti.port = inet_sk(sk)->inet_sport;
+
+       rcu_read_lock();
+       for_each_netdev_rcu(net, dev)
+               __udp_tunnel_pull_rx_port(dev, &ti);
+       rcu_read_unlock();
+}
+EXPORT_SYMBOL_GPL(udp_tunnel_notify_del_rx_port);
+
 void udp_tunnel_xmit_skb(struct rtable *rt, struct sock *sk, struct sk_buff *skb,
                         __be32 src, __be32 dst, __u8 tos, __u8 ttl,
                         __be16 df, __be16 src_port, __be16 dst_port,