tipc: permit bond slave as bearer

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>
This commit is contained in:
Parthasarathy Bhuvaragan 2017-08-28 17:57:02 +02:00 коммит произвёл David S. Miller
Родитель e8d411d298
Коммит d55c60eba0
2 изменённых файлов: 13 добавлений и 15 удалений

Просмотреть файл

@ -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 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 * 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 */ /* Associate TIPC bearer with L2 bearer */
rcu_assign_pointer(b->media_ptr, dev); 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)); memset(&b->bcast_addr, 0, sizeof(b->bcast_addr));
memcpy(b->bcast_addr.value, dev->broadcast, b->media->hwaddr_len); memcpy(b->bcast_addr.value, dev->broadcast, b->media->hwaddr_len);
b->bcast_addr.media_id = b->media->type_id; 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; struct net_device *dev;
dev = (struct net_device *)rtnl_dereference(b->media_ptr); dev = (struct net_device *)rtnl_dereference(b->media_ptr);
dev_remove_pack(&b->pt);
RCU_INIT_POINTER(dev->tipc_ptr, NULL); RCU_INIT_POINTER(dev->tipc_ptr, NULL);
synchronize_net(); synchronize_net();
dev_put(dev); 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; struct tipc_bearer *b;
rcu_read_lock(); 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) && if (likely(b && test_bit(0, &b->up) &&
(skb->pkt_type <= PACKET_MULTICAST))) { (skb->pkt_type <= PACKET_MULTICAST))) {
skb->next = NULL; skb->next = NULL;
tipc_rcv(dev_net(dev), skb, b); tipc_rcv(dev_net(b->pt.dev), skb, b);
rcu_read_unlock(); rcu_read_unlock();
return NET_RX_SUCCESS; return NET_RX_SUCCESS;
} }
@ -659,11 +667,6 @@ static int tipc_l2_device_event(struct notifier_block *nb, unsigned long evt,
return NOTIFY_OK; 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 = { static struct notifier_block notifier = {
.notifier_call = tipc_l2_device_event, .notifier_call = tipc_l2_device_event,
.priority = 0, .priority = 0,
@ -671,19 +674,12 @@ static struct notifier_block notifier = {
int tipc_bearer_setup(void) int tipc_bearer_setup(void)
{ {
int err; return register_netdevice_notifier(&notifier);
err = register_netdevice_notifier(&notifier);
if (err)
return err;
dev_add_pack(&tipc_packet_type);
return 0;
} }
void tipc_bearer_cleanup(void) void tipc_bearer_cleanup(void)
{ {
unregister_netdevice_notifier(&notifier); unregister_netdevice_notifier(&notifier);
dev_remove_pack(&tipc_packet_type);
} }
void tipc_bearer_stop(struct net *net) void tipc_bearer_stop(struct net *net)

Просмотреть файл

@ -131,6 +131,7 @@ struct tipc_media {
* @name: bearer name (format = media:interface) * @name: bearer name (format = media:interface)
* @media: ptr to media structure associated with bearer * @media: ptr to media structure associated with bearer
* @bcast_addr: media address used in broadcasting * @bcast_addr: media address used in broadcasting
* @pt: packet type for bearer
* @rcu: rcu struct for tipc_bearer * @rcu: rcu struct for tipc_bearer
* @priority: default link priority for bearer * @priority: default link priority for bearer
* @window: default window size for bearer * @window: default window size for bearer
@ -151,6 +152,7 @@ struct tipc_bearer {
char name[TIPC_MAX_BEARER_NAME]; char name[TIPC_MAX_BEARER_NAME];
struct tipc_media *media; struct tipc_media *media;
struct tipc_media_addr bcast_addr; struct tipc_media_addr bcast_addr;
struct packet_type pt;
struct rcu_head rcu; struct rcu_head rcu;
u32 priority; u32 priority;
u32 window; u32 window;