Merge branch 'tipc'
Jon Maloy says: ==================== tipc: cleanups in media and bearer layer This commit series performs a number cleanups in order to make the bearer and media part of the code more comprehensible and manageable. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
fcfa1a1722
9 changed files with 311 additions and 747 deletions
|
@ -1282,6 +1282,9 @@ struct net_device {
|
|||
#endif
|
||||
#if IS_ENABLED(CONFIG_NET_DSA)
|
||||
struct dsa_switch_tree *dsa_ptr; /* dsa specific data */
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_TIPC)
|
||||
struct tipc_bearer __rcu *tipc_ptr; /* TIPC specific data */
|
||||
#endif
|
||||
void *atalk_ptr; /* AppleTalk link */
|
||||
struct in_device __rcu *ip_ptr; /* IPv4 specific data */
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* net/tipc/bearer.c: TIPC bearer code
|
||||
*
|
||||
* Copyright (c) 1996-2006, Ericsson AB
|
||||
* Copyright (c) 2004-2006, 2010-2011, Wind River Systems
|
||||
* Copyright (c) 1996-2006, 2013, Ericsson AB
|
||||
* Copyright (c) 2004-2006, 2010-2013, Wind River Systems
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -41,8 +41,13 @@
|
|||
|
||||
#define MAX_ADDR_STR 60
|
||||
|
||||
static struct tipc_media *media_list[MAX_MEDIA];
|
||||
static u32 media_count;
|
||||
static struct tipc_media * const media_info_array[] = {
|
||||
ð_media_info,
|
||||
#ifdef CONFIG_TIPC_MEDIA_IB
|
||||
&ib_media_info,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
||||
struct tipc_bearer tipc_bearers[MAX_BEARERS];
|
||||
|
||||
|
@ -55,11 +60,11 @@ struct tipc_media *tipc_media_find(const char *name)
|
|||
{
|
||||
u32 i;
|
||||
|
||||
for (i = 0; i < media_count; i++) {
|
||||
if (!strcmp(media_list[i]->name, name))
|
||||
return media_list[i];
|
||||
for (i = 0; media_info_array[i] != NULL; i++) {
|
||||
if (!strcmp(media_info_array[i]->name, name))
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
return media_info_array[i];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -69,44 +74,11 @@ static struct tipc_media *media_find_id(u8 type)
|
|||
{
|
||||
u32 i;
|
||||
|
||||
for (i = 0; i < media_count; i++) {
|
||||
if (media_list[i]->type_id == type)
|
||||
return media_list[i];
|
||||
for (i = 0; media_info_array[i] != NULL; i++) {
|
||||
if (media_info_array[i]->type_id == type)
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* tipc_register_media - register a media type
|
||||
*
|
||||
* Bearers for this media type must be activated separately at a later stage.
|
||||
*/
|
||||
int tipc_register_media(struct tipc_media *m_ptr)
|
||||
{
|
||||
int res = -EINVAL;
|
||||
|
||||
write_lock_bh(&tipc_net_lock);
|
||||
|
||||
if ((strlen(m_ptr->name) + 1) > TIPC_MAX_MEDIA_NAME)
|
||||
goto exit;
|
||||
if (m_ptr->priority > TIPC_MAX_LINK_PRI)
|
||||
goto exit;
|
||||
if ((m_ptr->tolerance < TIPC_MIN_LINK_TOL) ||
|
||||
(m_ptr->tolerance > TIPC_MAX_LINK_TOL))
|
||||
goto exit;
|
||||
if (media_count >= MAX_MEDIA)
|
||||
goto exit;
|
||||
if (tipc_media_find(m_ptr->name) || media_find_id(m_ptr->type_id))
|
||||
goto exit;
|
||||
|
||||
media_list[media_count] = m_ptr;
|
||||
media_count++;
|
||||
res = 0;
|
||||
exit:
|
||||
write_unlock_bh(&tipc_net_lock);
|
||||
if (res)
|
||||
pr_warn("Media <%s> registration error\n", m_ptr->name);
|
||||
return res;
|
||||
return media_info_array[i];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -144,13 +116,11 @@ struct sk_buff *tipc_media_get_names(void)
|
|||
if (!buf)
|
||||
return NULL;
|
||||
|
||||
read_lock_bh(&tipc_net_lock);
|
||||
for (i = 0; i < media_count; i++) {
|
||||
for (i = 0; media_info_array[i] != NULL; i++) {
|
||||
tipc_cfg_append_tlv(buf, TIPC_TLV_MEDIA_NAME,
|
||||
media_list[i]->name,
|
||||
strlen(media_list[i]->name) + 1);
|
||||
media_info_array[i]->name,
|
||||
strlen(media_info_array[i]->name) + 1);
|
||||
}
|
||||
read_unlock_bh(&tipc_net_lock);
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
@ -239,7 +209,7 @@ struct tipc_bearer *tipc_bearer_find_interface(const char *if_name)
|
|||
struct sk_buff *tipc_bearer_get_names(void)
|
||||
{
|
||||
struct sk_buff *buf;
|
||||
struct tipc_bearer *b_ptr;
|
||||
struct tipc_bearer *b;
|
||||
int i, j;
|
||||
|
||||
buf = tipc_cfg_reply_alloc(MAX_BEARERS * TLV_SPACE(TIPC_MAX_BEARER_NAME));
|
||||
|
@ -247,13 +217,13 @@ struct sk_buff *tipc_bearer_get_names(void)
|
|||
return NULL;
|
||||
|
||||
read_lock_bh(&tipc_net_lock);
|
||||
for (i = 0; i < media_count; i++) {
|
||||
for (i = 0; media_info_array[i] != NULL; i++) {
|
||||
for (j = 0; j < MAX_BEARERS; j++) {
|
||||
b_ptr = &tipc_bearers[j];
|
||||
if (b_ptr->active && (b_ptr->media == media_list[i])) {
|
||||
b = &tipc_bearers[j];
|
||||
if (b->active && (b->media == media_info_array[i])) {
|
||||
tipc_cfg_append_tlv(buf, TIPC_TLV_BEARER_NAME,
|
||||
b_ptr->name,
|
||||
strlen(b_ptr->name) + 1);
|
||||
b->name,
|
||||
strlen(b->name) + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -362,6 +332,7 @@ int tipc_enable_bearer(const char *name, u32 disc_domain, u32 priority)
|
|||
|
||||
b_ptr = &tipc_bearers[bearer_id];
|
||||
strcpy(b_ptr->name, name);
|
||||
b_ptr->media = m_ptr;
|
||||
res = m_ptr->enable_media(b_ptr);
|
||||
if (res) {
|
||||
pr_warn("Bearer <%s> rejected, enable failure (%d)\n",
|
||||
|
@ -370,7 +341,6 @@ int tipc_enable_bearer(const char *name, u32 disc_domain, u32 priority)
|
|||
}
|
||||
|
||||
b_ptr->identity = bearer_id;
|
||||
b_ptr->media = m_ptr;
|
||||
b_ptr->tolerance = m_ptr->tolerance;
|
||||
b_ptr->window = m_ptr->window;
|
||||
b_ptr->net_plane = bearer_id + 'A';
|
||||
|
@ -397,7 +367,7 @@ int tipc_enable_bearer(const char *name, u32 disc_domain, u32 priority)
|
|||
/**
|
||||
* tipc_reset_bearer - Reset all links established over this bearer
|
||||
*/
|
||||
int tipc_reset_bearer(struct tipc_bearer *b_ptr)
|
||||
static int tipc_reset_bearer(struct tipc_bearer *b_ptr)
|
||||
{
|
||||
struct tipc_link *l_ptr;
|
||||
struct tipc_link *temp_l_ptr;
|
||||
|
@ -463,6 +433,211 @@ int tipc_disable_bearer(const char *name)
|
|||
}
|
||||
|
||||
|
||||
/* tipc_l2_media_addr_set - initialize Ethernet media address structure
|
||||
*
|
||||
* Media-dependent "value" field stores MAC address in first 6 bytes
|
||||
* and zeroes out the remaining bytes.
|
||||
*/
|
||||
void tipc_l2_media_addr_set(const struct tipc_bearer *b,
|
||||
struct tipc_media_addr *a, char *mac)
|
||||
{
|
||||
int len = b->media->hwaddr_len;
|
||||
|
||||
if (unlikely(sizeof(a->value) < len)) {
|
||||
WARN_ONCE(1, "Media length invalid\n");
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(a->value, mac, len);
|
||||
memset(a->value + len, 0, sizeof(a->value) - len);
|
||||
a->media_id = b->media->type_id;
|
||||
a->broadcast = !memcmp(mac, b->bcast_addr.value, len);
|
||||
}
|
||||
|
||||
int tipc_enable_l2_media(struct tipc_bearer *b)
|
||||
{
|
||||
struct net_device *dev;
|
||||
char *driver_name = strchr((const char *)b->name, ':') + 1;
|
||||
|
||||
/* Find device with specified name */
|
||||
dev = dev_get_by_name(&init_net, driver_name);
|
||||
if (!dev)
|
||||
return -ENODEV;
|
||||
|
||||
/* Associate TIPC bearer with Ethernet bearer */
|
||||
b->media_ptr = dev;
|
||||
memset(b->bcast_addr.value, 0, sizeof(b->bcast_addr.value));
|
||||
memcpy(b->bcast_addr.value, dev->broadcast, b->media->hwaddr_len);
|
||||
b->bcast_addr.media_id = b->media->type_id;
|
||||
b->bcast_addr.broadcast = 1;
|
||||
b->mtu = dev->mtu;
|
||||
tipc_l2_media_addr_set(b, &b->addr, (char *)dev->dev_addr);
|
||||
rcu_assign_pointer(dev->tipc_ptr, b);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* tipc_disable_l2_media - detach TIPC bearer from an Ethernet interface
|
||||
*
|
||||
* Mark Ethernet bearer as inactive so that incoming buffers are thrown away,
|
||||
* then get worker thread to complete bearer cleanup. (Can't do cleanup
|
||||
* here because cleanup code needs to sleep and caller holds spinlocks.)
|
||||
*/
|
||||
void tipc_disable_l2_media(struct tipc_bearer *b)
|
||||
{
|
||||
struct net_device *dev = (struct net_device *)b->media_ptr;
|
||||
RCU_INIT_POINTER(dev->tipc_ptr, NULL);
|
||||
dev_put(dev);
|
||||
}
|
||||
|
||||
/**
|
||||
* tipc_l2_send_msg - send a TIPC packet out over an Ethernet interface
|
||||
* @buf: the packet to be sent
|
||||
* @b_ptr: the bearer throught which the packet is to be sent
|
||||
* @dest: peer destination address
|
||||
*/
|
||||
int tipc_l2_send_msg(struct sk_buff *buf, struct tipc_bearer *b,
|
||||
struct tipc_media_addr *dest)
|
||||
{
|
||||
struct sk_buff *clone;
|
||||
int delta;
|
||||
struct net_device *dev = (struct net_device *)b->media_ptr;
|
||||
|
||||
clone = skb_clone(buf, GFP_ATOMIC);
|
||||
if (!clone)
|
||||
return 0;
|
||||
|
||||
delta = dev->hard_header_len - skb_headroom(buf);
|
||||
if ((delta > 0) &&
|
||||
pskb_expand_head(clone, SKB_DATA_ALIGN(delta), 0, GFP_ATOMIC)) {
|
||||
kfree_skb(clone);
|
||||
return 0;
|
||||
}
|
||||
|
||||
skb_reset_network_header(clone);
|
||||
clone->dev = dev;
|
||||
clone->protocol = htons(ETH_P_TIPC);
|
||||
dev_hard_header(clone, dev, ETH_P_TIPC, dest->value,
|
||||
dev->dev_addr, clone->len);
|
||||
dev_queue_xmit(clone);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* tipc_bearer_send- sends buffer to destination over bearer
|
||||
*
|
||||
* IMPORTANT:
|
||||
* The media send routine must not alter the buffer being passed in
|
||||
* as it may be needed for later retransmission!
|
||||
*/
|
||||
void tipc_bearer_send(struct tipc_bearer *b, struct sk_buff *buf,
|
||||
struct tipc_media_addr *dest)
|
||||
{
|
||||
b->media->send_msg(buf, b, dest);
|
||||
}
|
||||
|
||||
/**
|
||||
* tipc_l2_rcv_msg - handle incoming TIPC message from an interface
|
||||
* @buf: the received packet
|
||||
* @dev: the net device that the packet was received on
|
||||
* @pt: the packet_type structure which was used to register this handler
|
||||
* @orig_dev: the original receive net device in case the device is a bond
|
||||
*
|
||||
* Accept only packets explicitly sent to this node, or broadcast packets;
|
||||
* ignores packets sent using interface multicast, and traffic sent to other
|
||||
* nodes (which can happen if interface is running in promiscuous mode).
|
||||
*/
|
||||
static int tipc_l2_rcv_msg(struct sk_buff *buf, struct net_device *dev,
|
||||
struct packet_type *pt, struct net_device *orig_dev)
|
||||
{
|
||||
struct tipc_bearer *b_ptr;
|
||||
|
||||
if (!net_eq(dev_net(dev), &init_net)) {
|
||||
kfree_skb(buf);
|
||||
return NET_RX_DROP;
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
b_ptr = rcu_dereference(dev->tipc_ptr);
|
||||
if (likely(b_ptr)) {
|
||||
if (likely(buf->pkt_type <= PACKET_BROADCAST)) {
|
||||
buf->next = NULL;
|
||||
tipc_recv_msg(buf, b_ptr);
|
||||
rcu_read_unlock();
|
||||
return NET_RX_SUCCESS;
|
||||
}
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
kfree_skb(buf);
|
||||
return NET_RX_DROP;
|
||||
}
|
||||
|
||||
/**
|
||||
* tipc_l2_device_event - handle device events from network device
|
||||
* @nb: the context of the notification
|
||||
* @evt: the type of event
|
||||
* @ptr: the net device that the event was on
|
||||
*
|
||||
* This function is called by the Ethernet driver in case of link
|
||||
* change event.
|
||||
*/
|
||||
static int tipc_l2_device_event(struct notifier_block *nb, unsigned long evt,
|
||||
void *ptr)
|
||||
{
|
||||
struct tipc_bearer *b_ptr;
|
||||
struct net_device *dev = netdev_notifier_info_to_dev(ptr);
|
||||
|
||||
if (!net_eq(dev_net(dev), &init_net))
|
||||
return NOTIFY_DONE;
|
||||
|
||||
rcu_read_lock();
|
||||
b_ptr = rcu_dereference(dev->tipc_ptr);
|
||||
if (!b_ptr) {
|
||||
rcu_read_unlock();
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
b_ptr->mtu = dev->mtu;
|
||||
|
||||
switch (evt) {
|
||||
case NETDEV_CHANGE:
|
||||
if (netif_carrier_ok(dev))
|
||||
break;
|
||||
case NETDEV_DOWN:
|
||||
case NETDEV_CHANGEMTU:
|
||||
case NETDEV_CHANGEADDR:
|
||||
tipc_reset_bearer(b_ptr);
|
||||
break;
|
||||
case NETDEV_UNREGISTER:
|
||||
case NETDEV_CHANGENAME:
|
||||
tipc_disable_bearer(b_ptr->name);
|
||||
break;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
static struct packet_type tipc_packet_type __read_mostly = {
|
||||
.type = __constant_htons(ETH_P_TIPC),
|
||||
.func = tipc_l2_rcv_msg,
|
||||
};
|
||||
|
||||
static struct notifier_block notifier = {
|
||||
.notifier_call = tipc_l2_device_event,
|
||||
.priority = 0,
|
||||
};
|
||||
|
||||
int tipc_bearer_setup(void)
|
||||
{
|
||||
dev_add_pack(&tipc_packet_type);
|
||||
return register_netdevice_notifier(¬ifier);
|
||||
}
|
||||
|
||||
void tipc_bearer_cleanup(void)
|
||||
{
|
||||
unregister_netdevice_notifier(¬ifier);
|
||||
dev_remove_pack(&tipc_packet_type);
|
||||
}
|
||||
|
||||
void tipc_bearer_stop(void)
|
||||
{
|
||||
|
@ -472,5 +647,4 @@ void tipc_bearer_stop(void)
|
|||
if (tipc_bearers[i].active)
|
||||
bearer_disable(&tipc_bearers[i]);
|
||||
}
|
||||
media_count = 0;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* net/tipc/bearer.h: Include file for TIPC bearer code
|
||||
*
|
||||
* Copyright (c) 1996-2006, Ericsson AB
|
||||
* Copyright (c) 1996-2006, 2013, Ericsson AB
|
||||
* Copyright (c) 2005, 2010-2011, Wind River Systems
|
||||
* All rights reserved.
|
||||
*
|
||||
|
@ -73,18 +73,18 @@ struct tipc_media_addr {
|
|||
struct tipc_bearer;
|
||||
|
||||
/**
|
||||
* struct tipc_media - TIPC media information available to internal users
|
||||
* struct tipc_media - Media specific info exposed to generic bearer layer
|
||||
* @send_msg: routine which handles buffer transmission
|
||||
* @enable_media: routine which enables a media
|
||||
* @disable_media: routine which disables a media
|
||||
* @addr2str: routine which converts media address to string
|
||||
* @addr2msg: routine which converts media address to protocol message area
|
||||
* @msg2addr: routine which converts media address from protocol message area
|
||||
* @bcast_addr: media address used in broadcasting
|
||||
* @priority: default link (and bearer) priority
|
||||
* @tolerance: default time (in ms) before declaring link failure
|
||||
* @window: default window (in packets) before declaring link congestion
|
||||
* @type_id: TIPC media identifier
|
||||
* @hwaddr_len: TIPC media address len
|
||||
* @name: media name
|
||||
*/
|
||||
struct tipc_media {
|
||||
|
@ -101,17 +101,20 @@ struct tipc_media {
|
|||
u32 tolerance;
|
||||
u32 window;
|
||||
u32 type_id;
|
||||
u32 hwaddr_len;
|
||||
char name[TIPC_MAX_MEDIA_NAME];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct tipc_bearer - TIPC bearer structure
|
||||
* struct tipc_bearer - Generic TIPC bearer structure
|
||||
* @dev: ptr to associated network device
|
||||
* @usr_handle: pointer to additional media-specific information about bearer
|
||||
* @mtu: max packet size bearer can support
|
||||
* @lock: spinlock for controlling access to bearer
|
||||
* @addr: media-specific address associated with bearer
|
||||
* @name: bearer name (format = media:interface)
|
||||
* @media: ptr to media structure associated with bearer
|
||||
* @bcast_addr: media address used in broadcasting
|
||||
* @priority: default link priority for bearer
|
||||
* @window: default window size for bearer
|
||||
* @tolerance: default link tolerance for bearer
|
||||
|
@ -127,7 +130,7 @@ struct tipc_media {
|
|||
* care of initializing all other fields.
|
||||
*/
|
||||
struct tipc_bearer {
|
||||
void *usr_handle; /* initalized by media */
|
||||
void *media_ptr; /* initalized by media */
|
||||
u32 mtu; /* initalized by media */
|
||||
struct tipc_media_addr addr; /* initalized by media */
|
||||
char name[TIPC_MAX_BEARER_NAME];
|
||||
|
@ -157,33 +160,31 @@ extern struct tipc_bearer tipc_bearers[];
|
|||
/*
|
||||
* TIPC routines available to supported media types
|
||||
*/
|
||||
int tipc_register_media(struct tipc_media *m_ptr);
|
||||
|
||||
void tipc_recv_msg(struct sk_buff *buf, struct tipc_bearer *tb_ptr);
|
||||
|
||||
int tipc_reset_bearer(struct tipc_bearer *b_ptr);
|
||||
|
||||
int tipc_enable_bearer(const char *bearer_name, u32 disc_domain, u32 priority);
|
||||
int tipc_disable_bearer(const char *name);
|
||||
|
||||
/*
|
||||
* Routines made available to TIPC by supported media types
|
||||
*/
|
||||
int tipc_eth_media_start(void);
|
||||
void tipc_eth_media_stop(void);
|
||||
extern struct tipc_media eth_media_info;
|
||||
|
||||
#ifdef CONFIG_TIPC_MEDIA_IB
|
||||
int tipc_ib_media_start(void);
|
||||
void tipc_ib_media_stop(void);
|
||||
#else
|
||||
static inline int tipc_ib_media_start(void) { return 0; }
|
||||
static inline void tipc_ib_media_stop(void) { return; }
|
||||
extern struct tipc_media ib_media_info;
|
||||
#endif
|
||||
|
||||
int tipc_media_set_priority(const char *name, u32 new_value);
|
||||
int tipc_media_set_window(const char *name, u32 new_value);
|
||||
void tipc_media_addr_printf(char *buf, int len, struct tipc_media_addr *a);
|
||||
struct sk_buff *tipc_media_get_names(void);
|
||||
void tipc_l2_media_addr_set(const struct tipc_bearer *b,
|
||||
struct tipc_media_addr *a, char *mac);
|
||||
int tipc_enable_l2_media(struct tipc_bearer *b);
|
||||
void tipc_disable_l2_media(struct tipc_bearer *b);
|
||||
int tipc_l2_send_msg(struct sk_buff *buf, struct tipc_bearer *b,
|
||||
struct tipc_media_addr *dest);
|
||||
|
||||
struct sk_buff *tipc_bearer_get_names(void);
|
||||
void tipc_bearer_add_dest(struct tipc_bearer *b_ptr, u32 dest);
|
||||
|
@ -191,19 +192,10 @@ void tipc_bearer_remove_dest(struct tipc_bearer *b_ptr, u32 dest);
|
|||
struct tipc_bearer *tipc_bearer_find(const char *name);
|
||||
struct tipc_bearer *tipc_bearer_find_interface(const char *if_name);
|
||||
struct tipc_media *tipc_media_find(const char *name);
|
||||
int tipc_bearer_setup(void);
|
||||
void tipc_bearer_cleanup(void);
|
||||
void tipc_bearer_stop(void);
|
||||
|
||||
/**
|
||||
* tipc_bearer_send- sends buffer to destination over bearer
|
||||
*
|
||||
* IMPORTANT:
|
||||
* The media send routine must not alter the buffer being passed in
|
||||
* as it may be needed for later retransmission!
|
||||
*/
|
||||
static inline void tipc_bearer_send(struct tipc_bearer *b, struct sk_buff *buf,
|
||||
struct tipc_media_addr *dest)
|
||||
{
|
||||
b->media->send_msg(buf, b, dest);
|
||||
}
|
||||
void tipc_bearer_send(struct tipc_bearer *b, struct sk_buff *buf,
|
||||
struct tipc_media_addr *dest);
|
||||
|
||||
#endif /* _TIPC_BEARER_H */
|
||||
|
|
|
@ -82,8 +82,7 @@ struct sk_buff *tipc_buf_acquire(u32 size)
|
|||
static void tipc_core_stop_net(void)
|
||||
{
|
||||
tipc_net_stop();
|
||||
tipc_eth_media_stop();
|
||||
tipc_ib_media_stop();
|
||||
tipc_bearer_cleanup();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -94,10 +93,7 @@ int tipc_core_start_net(unsigned long addr)
|
|||
int res;
|
||||
|
||||
tipc_net_start(addr);
|
||||
res = tipc_eth_media_start();
|
||||
if (res < 0)
|
||||
goto err;
|
||||
res = tipc_ib_media_start();
|
||||
res = tipc_bearer_setup();
|
||||
if (res < 0)
|
||||
goto err;
|
||||
return res;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* net/tipc/eth_media.c: Ethernet bearer support for TIPC
|
||||
*
|
||||
* Copyright (c) 2001-2007, Ericsson AB
|
||||
* Copyright (c) 2001-2007, 2013, Ericsson AB
|
||||
* Copyright (c) 2005-2008, 2011-2013, Wind River Systems
|
||||
* All rights reserved.
|
||||
*
|
||||
|
@ -37,249 +37,11 @@
|
|||
#include "core.h"
|
||||
#include "bearer.h"
|
||||
|
||||
#define MAX_ETH_MEDIA MAX_BEARERS
|
||||
|
||||
#define ETH_ADDR_OFFSET 4 /* message header offset of MAC address */
|
||||
|
||||
/**
|
||||
* struct eth_media - Ethernet bearer data structure
|
||||
* @bearer: ptr to associated "generic" bearer structure
|
||||
* @dev: ptr to associated Ethernet network device
|
||||
* @tipc_packet_type: used in binding TIPC to Ethernet driver
|
||||
* @setup: work item used when enabling bearer
|
||||
* @cleanup: work item used when disabling bearer
|
||||
*/
|
||||
struct eth_media {
|
||||
struct tipc_bearer *bearer;
|
||||
struct net_device *dev;
|
||||
struct packet_type tipc_packet_type;
|
||||
struct work_struct setup;
|
||||
struct work_struct cleanup;
|
||||
};
|
||||
|
||||
static struct tipc_media eth_media_info;
|
||||
static struct eth_media eth_media_array[MAX_ETH_MEDIA];
|
||||
static int eth_started;
|
||||
|
||||
static int recv_notification(struct notifier_block *nb, unsigned long evt,
|
||||
void *dv);
|
||||
/*
|
||||
* Network device notifier info
|
||||
*/
|
||||
static struct notifier_block notifier = {
|
||||
.notifier_call = recv_notification,
|
||||
.priority = 0
|
||||
};
|
||||
|
||||
/**
|
||||
* eth_media_addr_set - initialize Ethernet media address structure
|
||||
*
|
||||
* Media-dependent "value" field stores MAC address in first 6 bytes
|
||||
* and zeroes out the remaining bytes.
|
||||
*/
|
||||
static void eth_media_addr_set(const struct tipc_bearer *tb_ptr,
|
||||
struct tipc_media_addr *a, char *mac)
|
||||
{
|
||||
memcpy(a->value, mac, ETH_ALEN);
|
||||
memset(a->value + ETH_ALEN, 0, sizeof(a->value) - ETH_ALEN);
|
||||
a->media_id = TIPC_MEDIA_TYPE_ETH;
|
||||
a->broadcast = !memcmp(mac, tb_ptr->bcast_addr.value, ETH_ALEN);
|
||||
}
|
||||
|
||||
/**
|
||||
* send_msg - send a TIPC message out over an Ethernet interface
|
||||
*/
|
||||
static int send_msg(struct sk_buff *buf, struct tipc_bearer *tb_ptr,
|
||||
struct tipc_media_addr *dest)
|
||||
{
|
||||
struct sk_buff *clone;
|
||||
struct net_device *dev;
|
||||
int delta;
|
||||
|
||||
clone = skb_clone(buf, GFP_ATOMIC);
|
||||
if (!clone)
|
||||
return 0;
|
||||
|
||||
dev = ((struct eth_media *)(tb_ptr->usr_handle))->dev;
|
||||
delta = dev->hard_header_len - skb_headroom(buf);
|
||||
|
||||
if ((delta > 0) &&
|
||||
pskb_expand_head(clone, SKB_DATA_ALIGN(delta), 0, GFP_ATOMIC)) {
|
||||
kfree_skb(clone);
|
||||
return 0;
|
||||
}
|
||||
|
||||
skb_reset_network_header(clone);
|
||||
clone->dev = dev;
|
||||
clone->protocol = htons(ETH_P_TIPC);
|
||||
dev_hard_header(clone, dev, ETH_P_TIPC, dest->value,
|
||||
dev->dev_addr, clone->len);
|
||||
dev_queue_xmit(clone);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* recv_msg - handle incoming TIPC message from an Ethernet interface
|
||||
*
|
||||
* Accept only packets explicitly sent to this node, or broadcast packets;
|
||||
* ignores packets sent using Ethernet multicast, and traffic sent to other
|
||||
* nodes (which can happen if interface is running in promiscuous mode).
|
||||
*/
|
||||
static int recv_msg(struct sk_buff *buf, struct net_device *dev,
|
||||
struct packet_type *pt, struct net_device *orig_dev)
|
||||
{
|
||||
struct eth_media *eb_ptr = (struct eth_media *)pt->af_packet_priv;
|
||||
|
||||
if (!net_eq(dev_net(dev), &init_net)) {
|
||||
kfree_skb(buf);
|
||||
return NET_RX_DROP;
|
||||
}
|
||||
|
||||
if (likely(eb_ptr->bearer)) {
|
||||
if (likely(buf->pkt_type <= PACKET_BROADCAST)) {
|
||||
buf->next = NULL;
|
||||
tipc_recv_msg(buf, eb_ptr->bearer);
|
||||
return NET_RX_SUCCESS;
|
||||
}
|
||||
}
|
||||
kfree_skb(buf);
|
||||
return NET_RX_DROP;
|
||||
}
|
||||
|
||||
/**
|
||||
* setup_media - setup association between Ethernet bearer and interface
|
||||
*/
|
||||
static void setup_media(struct work_struct *work)
|
||||
{
|
||||
struct eth_media *eb_ptr =
|
||||
container_of(work, struct eth_media, setup);
|
||||
|
||||
dev_add_pack(&eb_ptr->tipc_packet_type);
|
||||
}
|
||||
|
||||
/**
|
||||
* enable_media - attach TIPC bearer to an Ethernet interface
|
||||
*/
|
||||
static int enable_media(struct tipc_bearer *tb_ptr)
|
||||
{
|
||||
struct net_device *dev;
|
||||
struct eth_media *eb_ptr = ð_media_array[0];
|
||||
struct eth_media *stop = ð_media_array[MAX_ETH_MEDIA];
|
||||
char *driver_name = strchr((const char *)tb_ptr->name, ':') + 1;
|
||||
int pending_dev = 0;
|
||||
|
||||
/* Find unused Ethernet bearer structure */
|
||||
while (eb_ptr->dev) {
|
||||
if (!eb_ptr->bearer)
|
||||
pending_dev++;
|
||||
if (++eb_ptr == stop)
|
||||
return pending_dev ? -EAGAIN : -EDQUOT;
|
||||
}
|
||||
|
||||
/* Find device with specified name */
|
||||
dev = dev_get_by_name(&init_net, driver_name);
|
||||
if (!dev)
|
||||
return -ENODEV;
|
||||
|
||||
/* Create Ethernet bearer for device */
|
||||
eb_ptr->dev = dev;
|
||||
eb_ptr->tipc_packet_type.type = htons(ETH_P_TIPC);
|
||||
eb_ptr->tipc_packet_type.dev = dev;
|
||||
eb_ptr->tipc_packet_type.func = recv_msg;
|
||||
eb_ptr->tipc_packet_type.af_packet_priv = eb_ptr;
|
||||
INIT_LIST_HEAD(&(eb_ptr->tipc_packet_type.list));
|
||||
INIT_WORK(&eb_ptr->setup, setup_media);
|
||||
schedule_work(&eb_ptr->setup);
|
||||
|
||||
/* Associate TIPC bearer with Ethernet bearer */
|
||||
eb_ptr->bearer = tb_ptr;
|
||||
tb_ptr->usr_handle = (void *)eb_ptr;
|
||||
memset(tb_ptr->bcast_addr.value, 0, sizeof(tb_ptr->bcast_addr.value));
|
||||
memcpy(tb_ptr->bcast_addr.value, dev->broadcast, ETH_ALEN);
|
||||
tb_ptr->bcast_addr.media_id = TIPC_MEDIA_TYPE_ETH;
|
||||
tb_ptr->bcast_addr.broadcast = 1;
|
||||
tb_ptr->mtu = dev->mtu;
|
||||
eth_media_addr_set(tb_ptr, &tb_ptr->addr, (char *)dev->dev_addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* cleanup_media - break association between Ethernet bearer and interface
|
||||
*
|
||||
* This routine must be invoked from a work queue because it can sleep.
|
||||
*/
|
||||
static void cleanup_media(struct work_struct *work)
|
||||
{
|
||||
struct eth_media *eb_ptr =
|
||||
container_of(work, struct eth_media, cleanup);
|
||||
|
||||
dev_remove_pack(&eb_ptr->tipc_packet_type);
|
||||
dev_put(eb_ptr->dev);
|
||||
eb_ptr->dev = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* disable_media - detach TIPC bearer from an Ethernet interface
|
||||
*
|
||||
* Mark Ethernet bearer as inactive so that incoming buffers are thrown away,
|
||||
* then get worker thread to complete bearer cleanup. (Can't do cleanup
|
||||
* here because cleanup code needs to sleep and caller holds spinlocks.)
|
||||
*/
|
||||
static void disable_media(struct tipc_bearer *tb_ptr)
|
||||
{
|
||||
struct eth_media *eb_ptr = (struct eth_media *)tb_ptr->usr_handle;
|
||||
|
||||
eb_ptr->bearer = NULL;
|
||||
INIT_WORK(&eb_ptr->cleanup, cleanup_media);
|
||||
schedule_work(&eb_ptr->cleanup);
|
||||
}
|
||||
|
||||
/**
|
||||
* recv_notification - handle device updates from OS
|
||||
*
|
||||
* Change the state of the Ethernet bearer (if any) associated with the
|
||||
* specified device.
|
||||
*/
|
||||
static int recv_notification(struct notifier_block *nb, unsigned long evt,
|
||||
void *ptr)
|
||||
{
|
||||
struct net_device *dev = netdev_notifier_info_to_dev(ptr);
|
||||
struct eth_media *eb_ptr = ð_media_array[0];
|
||||
struct eth_media *stop = ð_media_array[MAX_ETH_MEDIA];
|
||||
|
||||
if (!net_eq(dev_net(dev), &init_net))
|
||||
return NOTIFY_DONE;
|
||||
|
||||
while ((eb_ptr->dev != dev)) {
|
||||
if (++eb_ptr == stop)
|
||||
return NOTIFY_DONE; /* couldn't find device */
|
||||
}
|
||||
if (!eb_ptr->bearer)
|
||||
return NOTIFY_DONE; /* bearer had been disabled */
|
||||
|
||||
eb_ptr->bearer->mtu = dev->mtu;
|
||||
|
||||
switch (evt) {
|
||||
case NETDEV_CHANGE:
|
||||
if (netif_carrier_ok(dev))
|
||||
break;
|
||||
case NETDEV_DOWN:
|
||||
case NETDEV_CHANGEMTU:
|
||||
case NETDEV_CHANGEADDR:
|
||||
tipc_reset_bearer(eb_ptr->bearer);
|
||||
break;
|
||||
case NETDEV_UNREGISTER:
|
||||
case NETDEV_CHANGENAME:
|
||||
tipc_disable_bearer(eb_ptr->bearer->name);
|
||||
break;
|
||||
}
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* eth_addr2str - convert Ethernet address to string
|
||||
*/
|
||||
static int eth_addr2str(struct tipc_media_addr *a, char *str_buf, int str_size)
|
||||
/* convert Ethernet address to string */
|
||||
static int tipc_eth_addr2str(struct tipc_media_addr *a, char *str_buf,
|
||||
int str_size)
|
||||
{
|
||||
if (str_size < 18) /* 18 = strlen("aa:bb:cc:dd:ee:ff\0") */
|
||||
return 1;
|
||||
|
@ -288,10 +50,8 @@ static int eth_addr2str(struct tipc_media_addr *a, char *str_buf, int str_size)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* eth_str2addr - convert Ethernet address format to message header format
|
||||
*/
|
||||
static int eth_addr2msg(struct tipc_media_addr *a, char *msg_area)
|
||||
/* convert Ethernet address format to message header format */
|
||||
static int tipc_eth_addr2msg(struct tipc_media_addr *a, char *msg_area)
|
||||
{
|
||||
memset(msg_area, 0, TIPC_MEDIA_ADDR_SIZE);
|
||||
msg_area[TIPC_MEDIA_TYPE_OFFSET] = TIPC_MEDIA_TYPE_ETH;
|
||||
|
@ -299,68 +59,30 @@ static int eth_addr2msg(struct tipc_media_addr *a, char *msg_area)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* eth_str2addr - convert message header address format to Ethernet format
|
||||
*/
|
||||
static int eth_msg2addr(const struct tipc_bearer *tb_ptr,
|
||||
struct tipc_media_addr *a, char *msg_area)
|
||||
/* convert message header address format to Ethernet format */
|
||||
static int tipc_eth_msg2addr(const struct tipc_bearer *tb_ptr,
|
||||
struct tipc_media_addr *a, char *msg_area)
|
||||
{
|
||||
if (msg_area[TIPC_MEDIA_TYPE_OFFSET] != TIPC_MEDIA_TYPE_ETH)
|
||||
return 1;
|
||||
|
||||
eth_media_addr_set(tb_ptr, a, msg_area + ETH_ADDR_OFFSET);
|
||||
tipc_l2_media_addr_set(tb_ptr, a, msg_area + ETH_ADDR_OFFSET);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ethernet media registration info
|
||||
*/
|
||||
static struct tipc_media eth_media_info = {
|
||||
.send_msg = send_msg,
|
||||
.enable_media = enable_media,
|
||||
.disable_media = disable_media,
|
||||
.addr2str = eth_addr2str,
|
||||
.addr2msg = eth_addr2msg,
|
||||
.msg2addr = eth_msg2addr,
|
||||
/* Ethernet media registration info */
|
||||
struct tipc_media eth_media_info = {
|
||||
.send_msg = tipc_l2_send_msg,
|
||||
.enable_media = tipc_enable_l2_media,
|
||||
.disable_media = tipc_disable_l2_media,
|
||||
.addr2str = tipc_eth_addr2str,
|
||||
.addr2msg = tipc_eth_addr2msg,
|
||||
.msg2addr = tipc_eth_msg2addr,
|
||||
.priority = TIPC_DEF_LINK_PRI,
|
||||
.tolerance = TIPC_DEF_LINK_TOL,
|
||||
.window = TIPC_DEF_LINK_WIN,
|
||||
.type_id = TIPC_MEDIA_TYPE_ETH,
|
||||
.hwaddr_len = ETH_ALEN,
|
||||
.name = "eth"
|
||||
};
|
||||
|
||||
/**
|
||||
* tipc_eth_media_start - activate Ethernet bearer support
|
||||
*
|
||||
* Register Ethernet media type with TIPC bearer code. Also register
|
||||
* with OS for notifications about device state changes.
|
||||
*/
|
||||
int tipc_eth_media_start(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
if (eth_started)
|
||||
return -EINVAL;
|
||||
|
||||
res = tipc_register_media(ð_media_info);
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
res = register_netdevice_notifier(¬ifier);
|
||||
if (!res)
|
||||
eth_started = 1;
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* tipc_eth_media_stop - deactivate Ethernet bearer support
|
||||
*/
|
||||
void tipc_eth_media_stop(void)
|
||||
{
|
||||
if (!eth_started)
|
||||
return;
|
||||
|
||||
flush_scheduled_work();
|
||||
unregister_netdevice_notifier(¬ifier);
|
||||
eth_started = 0;
|
||||
}
|
||||
|
|
|
@ -42,242 +42,9 @@
|
|||
#include "core.h"
|
||||
#include "bearer.h"
|
||||
|
||||
#define MAX_IB_MEDIA MAX_BEARERS
|
||||
|
||||
/**
|
||||
* struct ib_media - Infiniband media data structure
|
||||
* @bearer: ptr to associated "generic" bearer structure
|
||||
* @dev: ptr to associated Infiniband network device
|
||||
* @tipc_packet_type: used in binding TIPC to Infiniband driver
|
||||
* @cleanup: work item used when disabling bearer
|
||||
*/
|
||||
|
||||
struct ib_media {
|
||||
struct tipc_bearer *bearer;
|
||||
struct net_device *dev;
|
||||
struct packet_type tipc_packet_type;
|
||||
struct work_struct setup;
|
||||
struct work_struct cleanup;
|
||||
};
|
||||
|
||||
static struct tipc_media ib_media_info;
|
||||
static struct ib_media ib_media_array[MAX_IB_MEDIA];
|
||||
static int ib_started;
|
||||
|
||||
/**
|
||||
* ib_media_addr_set - initialize Infiniband media address structure
|
||||
*
|
||||
* Media-dependent "value" field stores MAC address in first 6 bytes
|
||||
* and zeroes out the remaining bytes.
|
||||
*/
|
||||
static void ib_media_addr_set(const struct tipc_bearer *tb_ptr,
|
||||
struct tipc_media_addr *a, char *mac)
|
||||
{
|
||||
BUILD_BUG_ON(sizeof(a->value) < INFINIBAND_ALEN);
|
||||
memcpy(a->value, mac, INFINIBAND_ALEN);
|
||||
a->media_id = TIPC_MEDIA_TYPE_IB;
|
||||
a->broadcast = !memcmp(mac, tb_ptr->bcast_addr.value, INFINIBAND_ALEN);
|
||||
}
|
||||
|
||||
/**
|
||||
* send_msg - send a TIPC message out over an InfiniBand interface
|
||||
*/
|
||||
static int send_msg(struct sk_buff *buf, struct tipc_bearer *tb_ptr,
|
||||
struct tipc_media_addr *dest)
|
||||
{
|
||||
struct sk_buff *clone;
|
||||
struct net_device *dev;
|
||||
int delta;
|
||||
|
||||
clone = skb_clone(buf, GFP_ATOMIC);
|
||||
if (!clone)
|
||||
return 0;
|
||||
|
||||
dev = ((struct ib_media *)(tb_ptr->usr_handle))->dev;
|
||||
delta = dev->hard_header_len - skb_headroom(buf);
|
||||
|
||||
if ((delta > 0) &&
|
||||
pskb_expand_head(clone, SKB_DATA_ALIGN(delta), 0, GFP_ATOMIC)) {
|
||||
kfree_skb(clone);
|
||||
return 0;
|
||||
}
|
||||
|
||||
skb_reset_network_header(clone);
|
||||
clone->dev = dev;
|
||||
clone->protocol = htons(ETH_P_TIPC);
|
||||
dev_hard_header(clone, dev, ETH_P_TIPC, dest->value,
|
||||
dev->dev_addr, clone->len);
|
||||
dev_queue_xmit(clone);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* recv_msg - handle incoming TIPC message from an InfiniBand interface
|
||||
*
|
||||
* Accept only packets explicitly sent to this node, or broadcast packets;
|
||||
* ignores packets sent using InfiniBand multicast, and traffic sent to other
|
||||
* nodes (which can happen if interface is running in promiscuous mode).
|
||||
*/
|
||||
static int recv_msg(struct sk_buff *buf, struct net_device *dev,
|
||||
struct packet_type *pt, struct net_device *orig_dev)
|
||||
{
|
||||
struct ib_media *ib_ptr = (struct ib_media *)pt->af_packet_priv;
|
||||
|
||||
if (!net_eq(dev_net(dev), &init_net)) {
|
||||
kfree_skb(buf);
|
||||
return NET_RX_DROP;
|
||||
}
|
||||
|
||||
if (likely(ib_ptr->bearer)) {
|
||||
if (likely(buf->pkt_type <= PACKET_BROADCAST)) {
|
||||
buf->next = NULL;
|
||||
tipc_recv_msg(buf, ib_ptr->bearer);
|
||||
return NET_RX_SUCCESS;
|
||||
}
|
||||
}
|
||||
kfree_skb(buf);
|
||||
return NET_RX_DROP;
|
||||
}
|
||||
|
||||
/**
|
||||
* setup_bearer - setup association between InfiniBand bearer and interface
|
||||
*/
|
||||
static void setup_media(struct work_struct *work)
|
||||
{
|
||||
struct ib_media *ib_ptr =
|
||||
container_of(work, struct ib_media, setup);
|
||||
|
||||
dev_add_pack(&ib_ptr->tipc_packet_type);
|
||||
}
|
||||
|
||||
/**
|
||||
* enable_media - attach TIPC bearer to an InfiniBand interface
|
||||
*/
|
||||
static int enable_media(struct tipc_bearer *tb_ptr)
|
||||
{
|
||||
struct net_device *dev;
|
||||
struct ib_media *ib_ptr = &ib_media_array[0];
|
||||
struct ib_media *stop = &ib_media_array[MAX_IB_MEDIA];
|
||||
char *driver_name = strchr((const char *)tb_ptr->name, ':') + 1;
|
||||
int pending_dev = 0;
|
||||
|
||||
/* Find unused InfiniBand bearer structure */
|
||||
while (ib_ptr->dev) {
|
||||
if (!ib_ptr->bearer)
|
||||
pending_dev++;
|
||||
if (++ib_ptr == stop)
|
||||
return pending_dev ? -EAGAIN : -EDQUOT;
|
||||
}
|
||||
|
||||
/* Find device with specified name */
|
||||
dev = dev_get_by_name(&init_net, driver_name);
|
||||
if (!dev)
|
||||
return -ENODEV;
|
||||
|
||||
/* Create InfiniBand bearer for device */
|
||||
ib_ptr->dev = dev;
|
||||
ib_ptr->tipc_packet_type.type = htons(ETH_P_TIPC);
|
||||
ib_ptr->tipc_packet_type.dev = dev;
|
||||
ib_ptr->tipc_packet_type.func = recv_msg;
|
||||
ib_ptr->tipc_packet_type.af_packet_priv = ib_ptr;
|
||||
INIT_LIST_HEAD(&(ib_ptr->tipc_packet_type.list));
|
||||
INIT_WORK(&ib_ptr->setup, setup_media);
|
||||
schedule_work(&ib_ptr->setup);
|
||||
|
||||
/* Associate TIPC bearer with InfiniBand bearer */
|
||||
ib_ptr->bearer = tb_ptr;
|
||||
tb_ptr->usr_handle = (void *)ib_ptr;
|
||||
memset(tb_ptr->bcast_addr.value, 0, sizeof(tb_ptr->bcast_addr.value));
|
||||
memcpy(tb_ptr->bcast_addr.value, dev->broadcast, INFINIBAND_ALEN);
|
||||
tb_ptr->bcast_addr.media_id = TIPC_MEDIA_TYPE_IB;
|
||||
tb_ptr->bcast_addr.broadcast = 1;
|
||||
tb_ptr->mtu = dev->mtu;
|
||||
ib_media_addr_set(tb_ptr, &tb_ptr->addr, (char *)dev->dev_addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* cleanup_bearer - break association between InfiniBand bearer and interface
|
||||
*
|
||||
* This routine must be invoked from a work queue because it can sleep.
|
||||
*/
|
||||
static void cleanup_bearer(struct work_struct *work)
|
||||
{
|
||||
struct ib_media *ib_ptr =
|
||||
container_of(work, struct ib_media, cleanup);
|
||||
|
||||
dev_remove_pack(&ib_ptr->tipc_packet_type);
|
||||
dev_put(ib_ptr->dev);
|
||||
ib_ptr->dev = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* disable_media - detach TIPC bearer from an InfiniBand interface
|
||||
*
|
||||
* Mark InfiniBand bearer as inactive so that incoming buffers are thrown away,
|
||||
* then get worker thread to complete bearer cleanup. (Can't do cleanup
|
||||
* here because cleanup code needs to sleep and caller holds spinlocks.)
|
||||
*/
|
||||
static void disable_media(struct tipc_bearer *tb_ptr)
|
||||
{
|
||||
struct ib_media *ib_ptr = (struct ib_media *)tb_ptr->usr_handle;
|
||||
|
||||
ib_ptr->bearer = NULL;
|
||||
INIT_WORK(&ib_ptr->cleanup, cleanup_bearer);
|
||||
schedule_work(&ib_ptr->cleanup);
|
||||
}
|
||||
|
||||
/**
|
||||
* recv_notification - handle device updates from OS
|
||||
*
|
||||
* Change the state of the InfiniBand bearer (if any) associated with the
|
||||
* specified device.
|
||||
*/
|
||||
static int recv_notification(struct notifier_block *nb, unsigned long evt,
|
||||
void *ptr)
|
||||
{
|
||||
struct net_device *dev = netdev_notifier_info_to_dev(ptr);
|
||||
struct ib_media *ib_ptr = &ib_media_array[0];
|
||||
struct ib_media *stop = &ib_media_array[MAX_IB_MEDIA];
|
||||
|
||||
if (!net_eq(dev_net(dev), &init_net))
|
||||
return NOTIFY_DONE;
|
||||
|
||||
while ((ib_ptr->dev != dev)) {
|
||||
if (++ib_ptr == stop)
|
||||
return NOTIFY_DONE; /* couldn't find device */
|
||||
}
|
||||
if (!ib_ptr->bearer)
|
||||
return NOTIFY_DONE; /* bearer had been disabled */
|
||||
|
||||
ib_ptr->bearer->mtu = dev->mtu;
|
||||
|
||||
switch (evt) {
|
||||
case NETDEV_CHANGE:
|
||||
if (netif_carrier_ok(dev))
|
||||
break;
|
||||
case NETDEV_DOWN:
|
||||
case NETDEV_CHANGEMTU:
|
||||
case NETDEV_CHANGEADDR:
|
||||
tipc_reset_bearer(ib_ptr->bearer);
|
||||
break;
|
||||
case NETDEV_UNREGISTER:
|
||||
case NETDEV_CHANGENAME:
|
||||
tipc_disable_bearer(ib_ptr->bearer->name);
|
||||
break;
|
||||
}
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
static struct notifier_block notifier = {
|
||||
.notifier_call = recv_notification,
|
||||
.priority = 0,
|
||||
};
|
||||
|
||||
/**
|
||||
* ib_addr2str - convert InfiniBand address to string
|
||||
*/
|
||||
static int ib_addr2str(struct tipc_media_addr *a, char *str_buf, int str_size)
|
||||
/* convert InfiniBand address to string */
|
||||
static int tipc_ib_addr2str(struct tipc_media_addr *a, char *str_buf,
|
||||
int str_size)
|
||||
{
|
||||
if (str_size < 60) /* 60 = 19 * strlen("xx:") + strlen("xx\0") */
|
||||
return 1;
|
||||
|
@ -287,10 +54,8 @@ static int ib_addr2str(struct tipc_media_addr *a, char *str_buf, int str_size)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ib_addr2msg - convert InfiniBand address format to message header format
|
||||
*/
|
||||
static int ib_addr2msg(struct tipc_media_addr *a, char *msg_area)
|
||||
/* convert InfiniBand address format to message header format */
|
||||
static int tipc_ib_addr2msg(struct tipc_media_addr *a, char *msg_area)
|
||||
{
|
||||
memset(msg_area, 0, TIPC_MEDIA_ADDR_SIZE);
|
||||
msg_area[TIPC_MEDIA_TYPE_OFFSET] = TIPC_MEDIA_TYPE_IB;
|
||||
|
@ -298,65 +63,27 @@ static int ib_addr2msg(struct tipc_media_addr *a, char *msg_area)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ib_msg2addr - convert message header address format to InfiniBand format
|
||||
*/
|
||||
static int ib_msg2addr(const struct tipc_bearer *tb_ptr,
|
||||
struct tipc_media_addr *a, char *msg_area)
|
||||
/* convert message header address format to InfiniBand format */
|
||||
static int tipc_ib_msg2addr(const struct tipc_bearer *tb_ptr,
|
||||
struct tipc_media_addr *a, char *msg_area)
|
||||
{
|
||||
ib_media_addr_set(tb_ptr, a, msg_area);
|
||||
tipc_l2_media_addr_set(tb_ptr, a, msg_area);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* InfiniBand media registration info
|
||||
*/
|
||||
static struct tipc_media ib_media_info = {
|
||||
.send_msg = send_msg,
|
||||
.enable_media = enable_media,
|
||||
.disable_media = disable_media,
|
||||
.addr2str = ib_addr2str,
|
||||
.addr2msg = ib_addr2msg,
|
||||
.msg2addr = ib_msg2addr,
|
||||
/* InfiniBand media registration info */
|
||||
struct tipc_media ib_media_info = {
|
||||
.send_msg = tipc_l2_send_msg,
|
||||
.enable_media = tipc_enable_l2_media,
|
||||
.disable_media = tipc_disable_l2_media,
|
||||
.addr2str = tipc_ib_addr2str,
|
||||
.addr2msg = tipc_ib_addr2msg,
|
||||
.msg2addr = tipc_ib_msg2addr,
|
||||
.priority = TIPC_DEF_LINK_PRI,
|
||||
.tolerance = TIPC_DEF_LINK_TOL,
|
||||
.window = TIPC_DEF_LINK_WIN,
|
||||
.type_id = TIPC_MEDIA_TYPE_IB,
|
||||
.hwaddr_len = INFINIBAND_ALEN,
|
||||
.name = "ib"
|
||||
};
|
||||
|
||||
/**
|
||||
* tipc_ib_media_start - activate InfiniBand bearer support
|
||||
*
|
||||
* Register InfiniBand media type with TIPC bearer code. Also register
|
||||
* with OS for notifications about device state changes.
|
||||
*/
|
||||
int tipc_ib_media_start(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
if (ib_started)
|
||||
return -EINVAL;
|
||||
|
||||
res = tipc_register_media(&ib_media_info);
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
res = register_netdevice_notifier(¬ifier);
|
||||
if (!res)
|
||||
ib_started = 1;
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* tipc_ib_media_stop - deactivate InfiniBand bearer support
|
||||
*/
|
||||
void tipc_ib_media_stop(void)
|
||||
{
|
||||
if (!ib_started)
|
||||
return;
|
||||
|
||||
flush_scheduled_work();
|
||||
unregister_netdevice_notifier(¬ifier);
|
||||
ib_started = 0;
|
||||
}
|
||||
|
|
|
@ -386,14 +386,7 @@ void tipc_link_wakeup_ports(struct tipc_link *l_ptr, int all)
|
|||
*/
|
||||
static void link_release_outqueue(struct tipc_link *l_ptr)
|
||||
{
|
||||
struct sk_buff *buf = l_ptr->first_out;
|
||||
struct sk_buff *next;
|
||||
|
||||
while (buf) {
|
||||
next = buf->next;
|
||||
kfree_skb(buf);
|
||||
buf = next;
|
||||
}
|
||||
kfree_skb_list(l_ptr->first_out);
|
||||
l_ptr->first_out = NULL;
|
||||
l_ptr->out_queue_size = 0;
|
||||
}
|
||||
|
@ -415,32 +408,15 @@ void tipc_link_reset_fragments(struct tipc_link *l_ptr)
|
|||
*/
|
||||
void tipc_link_stop(struct tipc_link *l_ptr)
|
||||
{
|
||||
struct sk_buff *buf;
|
||||
struct sk_buff *next;
|
||||
|
||||
buf = l_ptr->oldest_deferred_in;
|
||||
while (buf) {
|
||||
next = buf->next;
|
||||
kfree_skb(buf);
|
||||
buf = next;
|
||||
}
|
||||
|
||||
buf = l_ptr->first_out;
|
||||
while (buf) {
|
||||
next = buf->next;
|
||||
kfree_skb(buf);
|
||||
buf = next;
|
||||
}
|
||||
|
||||
kfree_skb_list(l_ptr->oldest_deferred_in);
|
||||
kfree_skb_list(l_ptr->first_out);
|
||||
tipc_link_reset_fragments(l_ptr);
|
||||
|
||||
kfree_skb(l_ptr->proto_msg_queue);
|
||||
l_ptr->proto_msg_queue = NULL;
|
||||
}
|
||||
|
||||
void tipc_link_reset(struct tipc_link *l_ptr)
|
||||
{
|
||||
struct sk_buff *buf;
|
||||
u32 prev_state = l_ptr->state;
|
||||
u32 checkpoint = l_ptr->next_in_no;
|
||||
int was_active_link = tipc_link_is_active(l_ptr);
|
||||
|
@ -471,12 +447,7 @@ void tipc_link_reset(struct tipc_link *l_ptr)
|
|||
link_release_outqueue(l_ptr);
|
||||
kfree_skb(l_ptr->proto_msg_queue);
|
||||
l_ptr->proto_msg_queue = NULL;
|
||||
buf = l_ptr->oldest_deferred_in;
|
||||
while (buf) {
|
||||
struct sk_buff *next = buf->next;
|
||||
kfree_skb(buf);
|
||||
buf = next;
|
||||
}
|
||||
kfree_skb_list(l_ptr->oldest_deferred_in);
|
||||
if (!list_empty(&l_ptr->waiting_ports))
|
||||
tipc_link_wakeup_ports(l_ptr, 1);
|
||||
|
||||
|
@ -517,10 +488,11 @@ static void link_state_event(struct tipc_link *l_ptr, unsigned int event)
|
|||
if (!l_ptr->started && (event != STARTING_EVT))
|
||||
return; /* Not yet. */
|
||||
|
||||
if (link_blocked(l_ptr)) {
|
||||
/* Check whether changeover is going on */
|
||||
if (l_ptr->exp_msg_count) {
|
||||
if (event == TIMEOUT_EVT)
|
||||
link_set_timer(l_ptr, cont_intv);
|
||||
return; /* Changeover going on */
|
||||
return;
|
||||
}
|
||||
|
||||
switch (l_ptr->state) {
|
||||
|
@ -1124,10 +1096,7 @@ static int link_send_sections_long(struct tipc_port *sender,
|
|||
if (copy_from_user(buf->data + fragm_crs, sect_crs, sz)) {
|
||||
res = -EFAULT;
|
||||
error:
|
||||
for (; buf_chain; buf_chain = buf) {
|
||||
buf = buf_chain->next;
|
||||
kfree_skb(buf_chain);
|
||||
}
|
||||
kfree_skb_list(buf_chain);
|
||||
return res;
|
||||
}
|
||||
sect_crs += sz;
|
||||
|
@ -1177,18 +1146,12 @@ static int link_send_sections_long(struct tipc_port *sender,
|
|||
if (l_ptr->max_pkt < max_pkt) {
|
||||
sender->max_pkt = l_ptr->max_pkt;
|
||||
tipc_node_unlock(node);
|
||||
for (; buf_chain; buf_chain = buf) {
|
||||
buf = buf_chain->next;
|
||||
kfree_skb(buf_chain);
|
||||
}
|
||||
kfree_skb_list(buf_chain);
|
||||
goto again;
|
||||
}
|
||||
} else {
|
||||
reject:
|
||||
for (; buf_chain; buf_chain = buf) {
|
||||
buf = buf_chain->next;
|
||||
kfree_skb(buf_chain);
|
||||
}
|
||||
kfree_skb_list(buf_chain);
|
||||
return tipc_port_reject_sections(sender, hdr, msg_sect,
|
||||
len, TIPC_ERR_NO_NODE);
|
||||
}
|
||||
|
@ -1769,7 +1732,8 @@ void tipc_link_send_proto_msg(struct tipc_link *l_ptr, u32 msg_typ,
|
|||
l_ptr->proto_msg_queue = NULL;
|
||||
}
|
||||
|
||||
if (link_blocked(l_ptr))
|
||||
/* Don't send protocol message during link changeover */
|
||||
if (l_ptr->exp_msg_count)
|
||||
return;
|
||||
|
||||
/* Abort non-RESET send if communication with node is prohibited */
|
||||
|
@ -1862,7 +1826,8 @@ static void link_recv_proto_msg(struct tipc_link *l_ptr, struct sk_buff *buf)
|
|||
u32 msg_tol;
|
||||
struct tipc_msg *msg = buf_msg(buf);
|
||||
|
||||
if (link_blocked(l_ptr))
|
||||
/* Discard protocol message during link changeover */
|
||||
if (l_ptr->exp_msg_count)
|
||||
goto exit;
|
||||
|
||||
/* record unnumbered packet arrival (force mismatch on next timeout) */
|
||||
|
@ -2283,11 +2248,7 @@ static int link_send_long_buf(struct tipc_link *l_ptr, struct sk_buff *buf)
|
|||
fragm = tipc_buf_acquire(fragm_sz + INT_H_SIZE);
|
||||
if (fragm == NULL) {
|
||||
kfree_skb(buf);
|
||||
while (buf_chain) {
|
||||
buf = buf_chain;
|
||||
buf_chain = buf_chain->next;
|
||||
kfree_skb(buf);
|
||||
}
|
||||
kfree_skb_list(buf_chain);
|
||||
return -ENOMEM;
|
||||
}
|
||||
msg_set_size(&fragm_hdr, fragm_sz + INT_H_SIZE);
|
||||
|
|
|
@ -112,7 +112,6 @@ struct tipc_stats {
|
|||
* @continuity_interval: link continuity testing interval [in ms]
|
||||
* @abort_limit: # of unacknowledged continuity probes needed to reset link
|
||||
* @state: current state of link FSM
|
||||
* @blocked: indicates if link has been administratively blocked
|
||||
* @fsm_msg_cnt: # of protocol messages link FSM has sent in current state
|
||||
* @proto_msg: template for control messages generated by link
|
||||
* @pmsg: convenience pointer to "proto_msg" field
|
||||
|
@ -162,7 +161,6 @@ struct tipc_link {
|
|||
u32 continuity_interval;
|
||||
u32 abort_limit;
|
||||
int state;
|
||||
int blocked;
|
||||
u32 fsm_msg_cnt;
|
||||
struct {
|
||||
unchar hdr[INT_H_SIZE];
|
||||
|
@ -312,11 +310,6 @@ static inline int link_reset_reset(struct tipc_link *l_ptr)
|
|||
return l_ptr->state == RESET_RESET;
|
||||
}
|
||||
|
||||
static inline int link_blocked(struct tipc_link *l_ptr)
|
||||
{
|
||||
return l_ptr->exp_msg_count || l_ptr->blocked;
|
||||
}
|
||||
|
||||
static inline int link_congested(struct tipc_link *l_ptr)
|
||||
{
|
||||
return l_ptr->out_queue_size >= l_ptr->queue_limit[0];
|
||||
|
|
|
@ -291,11 +291,7 @@ static void node_lost_contact(struct tipc_node *n_ptr)
|
|||
|
||||
/* Flush broadcast link info associated with lost node */
|
||||
if (n_ptr->bclink.recv_permitted) {
|
||||
while (n_ptr->bclink.deferred_head) {
|
||||
struct sk_buff *buf = n_ptr->bclink.deferred_head;
|
||||
n_ptr->bclink.deferred_head = buf->next;
|
||||
kfree_skb(buf);
|
||||
}
|
||||
kfree_skb_list(n_ptr->bclink.deferred_head);
|
||||
n_ptr->bclink.deferred_size = 0;
|
||||
|
||||
if (n_ptr->bclink.reasm_head) {
|
||||
|
|
Loading…
Reference in a new issue