tipc: permit bond slave as bearer
authorParthasarathy Bhuvaragan <parthasarathy.bhuvaragan@ericsson.com>
Mon, 28 Aug 2017 15:57:02 +0000 (17:57 +0200)
committerDavid S. Miller <davem@davemloft.net>
Tue, 29 Aug 2017 22:07:33 +0000 (15:07 -0700)
For a bond slave device as a tipc bearer, the dev represents the bond
interface and orig_dev represents the slave in tipc_l2_rcv_msg().
Since we decode the tipc_ptr from bonding device (dev), we fail to
find the bearer and thus tipc links are not established.

In this commit, we register the tipc protocol callback per device and
look for tipc bearer from both the devices.

Signed-off-by: Parthasarathy Bhuvaragan <parthasarathy.bhuvaragan@ericsson.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/tipc/bearer.c
net/tipc/bearer.h

index 767e0537dde5a8d0cfac97f6b11ee1d568ef87ed..89cd061c4468247cf761541ff1a2ca27f0836d6f 100644 (file)
@@ -65,6 +65,8 @@ static struct tipc_bearer *bearer_get(struct net *net, int bearer_id)
 }
 
 static void bearer_disable(struct net *net, struct tipc_bearer *b);
+static int tipc_l2_rcv_msg(struct sk_buff *skb, struct net_device *dev,
+                          struct packet_type *pt, struct net_device *orig_dev);
 
 /**
  * tipc_media_find - locates specified media object by name
@@ -428,6 +430,10 @@ int tipc_enable_l2_media(struct net *net, struct tipc_bearer *b,
 
        /* Associate TIPC bearer with L2 bearer */
        rcu_assign_pointer(b->media_ptr, dev);
+       b->pt.dev = dev;
+       b->pt.type = htons(ETH_P_TIPC);
+       b->pt.func = tipc_l2_rcv_msg;
+       dev_add_pack(&b->pt);
        memset(&b->bcast_addr, 0, sizeof(b->bcast_addr));
        memcpy(b->bcast_addr.value, dev->broadcast, b->media->hwaddr_len);
        b->bcast_addr.media_id = b->media->type_id;
@@ -447,6 +453,7 @@ void tipc_disable_l2_media(struct tipc_bearer *b)
        struct net_device *dev;
 
        dev = (struct net_device *)rtnl_dereference(b->media_ptr);
+       dev_remove_pack(&b->pt);
        RCU_INIT_POINTER(dev->tipc_ptr, NULL);
        synchronize_net();
        dev_put(dev);
@@ -594,11 +601,12 @@ static int tipc_l2_rcv_msg(struct sk_buff *skb, struct net_device *dev,
        struct tipc_bearer *b;
 
        rcu_read_lock();
-       b = rcu_dereference_rtnl(dev->tipc_ptr);
+       b = rcu_dereference_rtnl(dev->tipc_ptr) ?:
+               rcu_dereference_rtnl(orig_dev->tipc_ptr);
        if (likely(b && test_bit(0, &b->up) &&
                   (skb->pkt_type <= PACKET_MULTICAST))) {
                skb->next = NULL;
-               tipc_rcv(dev_net(dev), skb, b);
+               tipc_rcv(dev_net(b->pt.dev), skb, b);
                rcu_read_unlock();
                return NET_RX_SUCCESS;
        }
@@ -659,11 +667,6 @@ static int tipc_l2_device_event(struct notifier_block *nb, unsigned long evt,
        return NOTIFY_OK;
 }
 
-static struct packet_type tipc_packet_type __read_mostly = {
-       .type = htons(ETH_P_TIPC),
-       .func = tipc_l2_rcv_msg,
-};
-
 static struct notifier_block notifier = {
        .notifier_call  = tipc_l2_device_event,
        .priority       = 0,
@@ -671,19 +674,12 @@ static struct notifier_block notifier = {
 
 int tipc_bearer_setup(void)
 {
-       int err;
-
-       err = register_netdevice_notifier(&notifier);
-       if (err)
-               return err;
-       dev_add_pack(&tipc_packet_type);
-       return 0;
+       return register_netdevice_notifier(&notifier);
 }
 
 void tipc_bearer_cleanup(void)
 {
        unregister_netdevice_notifier(&notifier);
-       dev_remove_pack(&tipc_packet_type);
 }
 
 void tipc_bearer_stop(struct net *net)
index 635c9086e19af86b81b4dc572a7c2ee0374b02fc..e07a55a80c18ba0f3c4f1187b7544faeca395a4e 100644 (file)
@@ -131,6 +131,7 @@ struct tipc_media {
  * @name: bearer name (format = media:interface)
  * @media: ptr to media structure associated with bearer
  * @bcast_addr: media address used in broadcasting
+ * @pt: packet type for bearer
  * @rcu: rcu struct for tipc_bearer
  * @priority: default link priority for bearer
  * @window: default window size for bearer
@@ -151,6 +152,7 @@ struct tipc_bearer {
        char name[TIPC_MAX_BEARER_NAME];
        struct tipc_media *media;
        struct tipc_media_addr bcast_addr;
+       struct packet_type pt;
        struct rcu_head rcu;
        u32 priority;
        u32 window;