X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=datapath%2Fvport-netdev.c;h=4bc16175c92256cf2935fdc29e640574922d63cd;hb=b0fb94a346e52f36aeef238dd5f9bef9a10c14ef;hp=55592f988e55e1e22f51821c6dce04efc8c750cb;hpb=be7cd27e44258bdb3c4e7dd8fd7389b5db56d55a;p=sliver-openvswitch.git diff --git a/datapath/vport-netdev.c b/datapath/vport-netdev.c index 55592f988..4bc16175c 100644 --- a/datapath/vport-netdev.c +++ b/datapath/vport-netdev.c @@ -25,6 +25,7 @@ #include #include #include +#include #include @@ -45,12 +46,6 @@ MODULE_PARM_DESC(vlan_tso, "Enable TSO for VLAN packets"); #define vlan_tso true #endif -#ifdef HAVE_RHEL_OVS_HOOK -static atomic_t nr_bridges = ATOMIC_INIT(0); - -extern struct sk_buff *(*openvswitch_handle_frame_hook)(struct sk_buff *skb); -#endif - static void netdev_port_receive(struct vport *vport, struct sk_buff *skb); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39) @@ -117,21 +112,40 @@ static int netdev_frame_hook(struct net_bridge_port *p, struct sk_buff **pskb) static int netdev_init(void) { return 0; } static void netdev_exit(void) { } #else -static int netdev_init(void) +static int port_count; + +static void netdev_init(void) { + port_count++; + if (port_count > 1) + return; + /* Hook into callback used by the bridge to intercept packets. * Parasites we are. */ br_handle_frame_hook = netdev_frame_hook; - return 0; + return; } static void netdev_exit(void) { + port_count--; + if (port_count > 0) + return; + br_handle_frame_hook = NULL; } #endif +static struct net_device *get_dpdev(struct datapath *dp) +{ + struct vport *local; + + local = ovs_vport_ovsl(dp, OVSP_LOCAL); + BUG_ON(!local); + return netdev_vport_priv(local)->dev; +} + static struct vport *netdev_create(const struct vport_parms *parms) { struct vport *vport; @@ -161,16 +175,15 @@ static struct vport *netdev_create(const struct vport_parms *parms) } rtnl_lock(); -#ifdef HAVE_RHEL_OVS_HOOK - rcu_assign_pointer(netdev_vport->dev->ax25_ptr, vport); - atomic_inc(&nr_bridges); - rcu_assign_pointer(openvswitch_handle_frame_hook, netdev_frame_hook); -#else + err = netdev_master_upper_dev_link(netdev_vport->dev, + get_dpdev(vport->dp)); + if (err) + goto error_unlock; + err = netdev_rx_handler_register(netdev_vport->dev, netdev_frame_hook, vport); if (err) - goto error_unlock; -#endif + goto error_master_upper_dev_unlink; dev_set_promiscuity(netdev_vport->dev, 1); #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) @@ -179,11 +192,12 @@ static struct vport *netdev_create(const struct vport_parms *parms) netdev_vport->dev->priv_flags |= IFF_OVS_DATAPATH; rtnl_unlock(); + netdev_init(); return vport; -#ifndef HAVE_RHEL_OVS_HOOK +error_master_upper_dev_unlink: + netdev_upper_dev_unlink(netdev_vport->dev, get_dpdev(vport->dp)); error_unlock: -#endif rtnl_unlock(); error_put: dev_put(netdev_vport->dev); @@ -198,12 +212,6 @@ static void free_port_rcu(struct rcu_head *rcu) struct netdev_vport *netdev_vport = container_of(rcu, struct netdev_vport, rcu); -#ifdef HAVE_RHEL_OVS_HOOK - rcu_assign_pointer(netdev_vport->dev->ax25_ptr, NULL); - - if (atomic_dec_and_test(&nr_bridges)) - rcu_assign_pointer(openvswitch_handle_frame_hook, NULL); -#endif dev_put(netdev_vport->dev); ovs_vport_free(vport_from_priv(netdev_vport)); } @@ -212,9 +220,11 @@ static void netdev_destroy(struct vport *vport) { struct netdev_vport *netdev_vport = netdev_vport_priv(vport); + netdev_exit(); rtnl_lock(); netdev_vport->dev->priv_flags &= ~IFF_OVS_DATAPATH; netdev_rx_handler_unregister(netdev_vport->dev); + netdev_upper_dev_unlink(netdev_vport->dev, get_dpdev(vport->dp)); dev_set_promiscuity(netdev_vport->dev, -1); rtnl_unlock(); @@ -244,14 +254,15 @@ static void netdev_port_receive(struct vport *vport, struct sk_buff *skb) if (unlikely(!skb)) return; - skb_push(skb, ETH_HLEN); - if (unlikely(compute_ip_summed(skb, false))) goto error; + skb_push(skb, ETH_HLEN); + ovs_skb_postpush_rcsum(skb, skb->data, ETH_HLEN); + vlan_copy_skb_tci(skb); - ovs_vport_receive(vport, skb); + ovs_vport_receive(vport, skb, NULL); return; error: @@ -383,9 +394,6 @@ struct vport *ovs_netdev_get_vport(struct net_device *dev) const struct vport_ops ovs_netdev_vport_ops = { .type = OVS_VPORT_TYPE_NETDEV, - .flags = VPORT_F_REQUIRED, - .init = netdev_init, - .exit = netdev_exit, .create = netdev_create, .destroy = netdev_destroy, .get_name = ovs_netdev_get_name,