Netdev List
 help / color / mirror / Atom feed
* [PATCH net-next 19/23] tipc: Handle broadcast attempt when no neighboring nodes exist
From: Paul Gortmaker @ 2011-12-27 17:39 UTC (permalink / raw)
  To: davem; +Cc: netdev, allan.stephens, ying.xue, Paul Gortmaker
In-Reply-To: <1325007582-31610-1-git-send-email-paul.gortmaker@windriver.com>

From: Allan Stephens <allan.stephens@windriver.com>

Adds a check to detect when an attempt is made to send a message
via the broadcast link and no neighboring nodes are currently available
to receive it. Rather than wasting effort passing the message to the
broadcast link and broadcast bearer, who will only throw it away,
TIPC now frees the message immediately and reports success (i.e. the
message has been delivered to all available destinations).

Signed-off-by: Allan Stephens <allan.stephens@windriver.com>
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
---
 net/tipc/bcast.c |    8 +++++++-
 1 files changed, 7 insertions(+), 1 deletions(-)

diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c
index 5ca8fdd..8f58df2 100644
--- a/net/tipc/bcast.c
+++ b/net/tipc/bcast.c
@@ -417,13 +417,19 @@ int tipc_bclink_send_msg(struct sk_buff *buf)
 
 	spin_lock_bh(&bc_lock);
 
+	if (!bclink->bcast_nodes.count) {
+		res = msg_data_sz(buf_msg(buf));
+		buf_discard(buf);
+		goto exit;
+	}
+
 	res = tipc_link_send_buf(bcl, buf);
 	if (likely(res > 0))
 		bclink_set_last_sent();
 
 	bcl->stats.queue_sz_counts++;
 	bcl->stats.accu_queue_sz += bcl->out_queue_size;
-
+exit:
 	spin_unlock_bh(&bc_lock);
 	return res;
 }
-- 
1.7.4.4

^ permalink raw reply related

* [PATCH net-next 17/23] tipc: Eliminate dynamic allocation of broadcast link data structures
From: Paul Gortmaker @ 2011-12-27 17:39 UTC (permalink / raw)
  To: davem; +Cc: netdev, allan.stephens, ying.xue, Paul Gortmaker
In-Reply-To: <1325007582-31610-1-git-send-email-paul.gortmaker@windriver.com>

From: Allan Stephens <allan.stephens@windriver.com>

Creates global variables to hold the broadcast link's pseudo-bearer and
pseudo-link structures, rather than allocating them dynamically. There
is only a single instance of each structure, and changing over to static
allocation allows elimination of code to handle the cases where dynamic
allocation was unsuccessful.

The memset in the teardown code may look like they aren't used, but
the same teardown code is run when there is a non-fatal error at
init-time, so that stale data isn't present when the user fixes the
cause of the soft error.

Signed-off-by: Allan Stephens <allan.stephens@windriver.com>
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
---
 net/tipc/bcast.c |   37 +++++++++++--------------------------
 net/tipc/bcast.h |    2 +-
 net/tipc/net.c   |    5 +----
 3 files changed, 13 insertions(+), 31 deletions(-)

diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c
index 28908f5..738cb64 100644
--- a/net/tipc/bcast.c
+++ b/net/tipc/bcast.c
@@ -98,10 +98,13 @@ struct bclink {
 	struct tipc_node *retransmit_to;
 };
 
+static struct bcbearer bcast_bearer;
+static struct bclink bcast_link;
+
+static struct bcbearer *bcbearer = &bcast_bearer;
+static struct bclink *bclink = &bcast_link;
+static struct link *bcl = &bcast_link.link;
 
-static struct bcbearer *bcbearer;
-static struct bclink *bclink;
-static struct link *bcl;
 static DEFINE_SPINLOCK(bc_lock);
 
 /* broadcast-capable node map */
@@ -752,25 +755,13 @@ int tipc_bclink_set_queue_limits(u32 limit)
 	return 0;
 }
 
-int tipc_bclink_init(void)
+void tipc_bclink_init(void)
 {
-	bcbearer = kzalloc(sizeof(*bcbearer), GFP_ATOMIC);
-	bclink = kzalloc(sizeof(*bclink), GFP_ATOMIC);
-	if (!bcbearer || !bclink) {
-		warn("Broadcast link creation failed, no memory\n");
-		kfree(bcbearer);
-		bcbearer = NULL;
-		kfree(bclink);
-		bclink = NULL;
-		return -ENOMEM;
-	}
-
 	INIT_LIST_HEAD(&bcbearer->bearer.cong_links);
 	bcbearer->bearer.media = &bcbearer->media;
 	bcbearer->media.send_msg = tipc_bcbearer_send;
 	sprintf(bcbearer->media.name, "tipc-broadcast");
 
-	bcl = &bclink->link;
 	INIT_LIST_HEAD(&bcl->waiting_ports);
 	bcl->next_out_no = 1;
 	spin_lock_init(&bclink->node.lock);
@@ -780,22 +771,16 @@ int tipc_bclink_init(void)
 	bcl->b_ptr = &bcbearer->bearer;
 	bcl->state = WORKING_WORKING;
 	strlcpy(bcl->name, tipc_bclink_name, TIPC_MAX_LINK_NAME);
-
-	return 0;
 }
 
 void tipc_bclink_stop(void)
 {
 	spin_lock_bh(&bc_lock);
-	if (bcbearer) {
-		tipc_link_stop(bcl);
-		bcl = NULL;
-		kfree(bclink);
-		bclink = NULL;
-		kfree(bcbearer);
-		bcbearer = NULL;
-	}
+	tipc_link_stop(bcl);
 	spin_unlock_bh(&bc_lock);
+
+	memset(bclink, 0, sizeof(*bclink));
+	memset(bcbearer, 0, sizeof(*bcbearer));
 }
 
 
diff --git a/net/tipc/bcast.h b/net/tipc/bcast.h
index 06740da..0b04443 100644
--- a/net/tipc/bcast.h
+++ b/net/tipc/bcast.h
@@ -88,7 +88,7 @@ static inline int tipc_nmap_equal(struct tipc_node_map *nm_a, struct tipc_node_m
 void tipc_port_list_add(struct port_list *pl_ptr, u32 port);
 void tipc_port_list_free(struct port_list *pl_ptr);
 
-int  tipc_bclink_init(void);
+void tipc_bclink_init(void);
 void tipc_bclink_stop(void);
 struct tipc_node *tipc_bclink_retransmit_to(void);
 void tipc_bclink_acknowledge(struct tipc_node *n_ptr, u32 acked);
diff --git a/net/tipc/net.c b/net/tipc/net.c
index e13162f..61afee7 100644
--- a/net/tipc/net.c
+++ b/net/tipc/net.c
@@ -174,7 +174,6 @@ void tipc_net_route_msg(struct sk_buff *buf)
 int tipc_net_start(u32 addr)
 {
 	char addr_string[16];
-	int res;
 
 	if (tipc_mode != TIPC_NODE_MODE)
 		return -ENOPROTOOPT;
@@ -187,9 +186,7 @@ int tipc_net_start(u32 addr)
 	tipc_named_reinit();
 	tipc_port_reinit();
 
-	res = tipc_bclink_init();
-	if (res)
-		return res;
+	tipc_bclink_init();
 
 	tipc_k_signal((Handler)tipc_subscr_start, 0);
 	tipc_k_signal((Handler)tipc_cfg_init, 0);
-- 
1.7.4.4

^ permalink raw reply related

* [PATCH net-next 18/23] tipc: Ensure broadcast link spinlock is held when updating node map
From: Paul Gortmaker @ 2011-12-27 17:39 UTC (permalink / raw)
  To: davem; +Cc: netdev, allan.stephens, ying.xue, Paul Gortmaker
In-Reply-To: <1325007582-31610-1-git-send-email-paul.gortmaker@windriver.com>

From: Allan Stephens <allan.stephens@windriver.com>

Fixes oversight that allowed broadcast link node map to be updated without
first taking the broadcast link spinlock that protects the map. As part
of this fix the node map has been incorporated into the broadcast link
structure to make the need for such protection more evident.

Signed-off-by: Allan Stephens <allan.stephens@windriver.com>
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
---
 net/tipc/bcast.c |   24 ++++++++++++++++++------
 net/tipc/bcast.h |    4 ++--
 net/tipc/node.c  |    4 ++--
 3 files changed, 22 insertions(+), 10 deletions(-)

diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c
index 738cb64..5ca8fdd 100644
--- a/net/tipc/bcast.c
+++ b/net/tipc/bcast.c
@@ -87,6 +87,7 @@ struct bcbearer {
  * struct bclink - link used for broadcast messages
  * @link: (non-standard) broadcast link structure
  * @node: (non-standard) node structure representing b'cast link's peer node
+ * @bcast_nodes: map of broadcast-capable nodes
  * @retransmit_to: node that most recently requested a retransmit
  *
  * Handles sequence numbering, fragmentation, bundling, etc.
@@ -95,6 +96,7 @@ struct bcbearer {
 struct bclink {
 	struct link link;
 	struct tipc_node node;
+	struct tipc_node_map bcast_nodes;
 	struct tipc_node *retransmit_to;
 };
 
@@ -107,9 +109,6 @@ static struct link *bcl = &bcast_link.link;
 
 static DEFINE_SPINLOCK(bc_lock);
 
-/* broadcast-capable node map */
-struct tipc_node_map tipc_bcast_nmap;
-
 const char tipc_bclink_name[] = "broadcast-link";
 
 static void tipc_nmap_diff(struct tipc_node_map *nm_a,
@@ -136,6 +135,19 @@ static void bcbuf_decr_acks(struct sk_buff *buf)
 	bcbuf_set_acks(buf, bcbuf_acks(buf) - 1);
 }
 
+void tipc_bclink_add_node(u32 addr)
+{
+	spin_lock_bh(&bc_lock);
+	tipc_nmap_add(&bclink->bcast_nodes, addr);
+	spin_unlock_bh(&bc_lock);
+}
+
+void tipc_bclink_remove_node(u32 addr)
+{
+	spin_lock_bh(&bc_lock);
+	tipc_nmap_remove(&bclink->bcast_nodes, addr);
+	spin_unlock_bh(&bc_lock);
+}
 
 static void bclink_set_last_sent(void)
 {
@@ -575,13 +587,13 @@ static int tipc_bcbearer_send(struct sk_buff *buf,
 	if (likely(!msg_non_seq(buf_msg(buf)))) {
 		struct tipc_msg *msg;
 
-		bcbuf_set_acks(buf, tipc_bcast_nmap.count);
+		bcbuf_set_acks(buf, bclink->bcast_nodes.count);
 		msg = buf_msg(buf);
 		msg_set_non_seq(msg, 1);
 		msg_set_mc_netid(msg, tipc_net_id);
 		bcl->stats.sent_info++;
 
-		if (WARN_ON(!tipc_bcast_nmap.count)) {
+		if (WARN_ON(!bclink->bcast_nodes.count)) {
 			dump_stack();
 			return 0;
 		}
@@ -589,7 +601,7 @@ static int tipc_bcbearer_send(struct sk_buff *buf,
 
 	/* Send buffer over bearers until all targets reached */
 
-	bcbearer->remains = tipc_bcast_nmap;
+	bcbearer->remains = bclink->bcast_nodes;
 
 	for (bp_index = 0; bp_index < MAX_BEARERS; bp_index++) {
 		struct tipc_bearer *p = bcbearer->bpairs[bp_index].primary;
diff --git a/net/tipc/bcast.h b/net/tipc/bcast.h
index 0b04443..3c37fdb 100644
--- a/net/tipc/bcast.h
+++ b/net/tipc/bcast.h
@@ -51,8 +51,6 @@ struct tipc_node_map {
 	u32 map[MAX_NODES / WSIZE];
 };
 
-extern struct tipc_node_map tipc_bcast_nmap;
-
 #define PLSIZE 32
 
 /**
@@ -90,6 +88,8 @@ void tipc_port_list_free(struct port_list *pl_ptr);
 
 void tipc_bclink_init(void);
 void tipc_bclink_stop(void);
+void tipc_bclink_add_node(u32 addr);
+void tipc_bclink_remove_node(u32 addr);
 struct tipc_node *tipc_bclink_retransmit_to(void);
 void tipc_bclink_acknowledge(struct tipc_node *n_ptr, u32 acked);
 int  tipc_bclink_send_msg(struct sk_buff *buf);
diff --git a/net/tipc/node.c b/net/tipc/node.c
index 27b4bb0..1861ae9 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -307,7 +307,7 @@ static void node_established_contact(struct tipc_node *n_ptr)
 	n_ptr->bclink.acked = tipc_bclink_get_last_sent();
 
 	if (n_ptr->bclink.supported) {
-		tipc_nmap_add(&tipc_bcast_nmap, n_ptr->addr);
+		tipc_bclink_add_node(n_ptr->addr);
 		if (n_ptr->addr < tipc_own_addr)
 			tipc_own_tag++;
 	}
@@ -350,7 +350,7 @@ static void node_lost_contact(struct tipc_node *n_ptr)
 			n_ptr->bclink.defragm = NULL;
 		}
 
-		tipc_nmap_remove(&tipc_bcast_nmap, n_ptr->addr);
+		tipc_bclink_remove_node(n_ptr->addr);
 		tipc_bclink_acknowledge(n_ptr,
 					mod(n_ptr->bclink.acked + 10000));
 		if (n_ptr->addr < tipc_own_addr)
-- 
1.7.4.4

^ permalink raw reply related

* [PATCH net-next 16/23] tipc: Eliminate useless check when network address is assigned
From: Paul Gortmaker @ 2011-12-27 17:39 UTC (permalink / raw)
  To: davem; +Cc: netdev, allan.stephens, ying.xue, Paul Gortmaker
In-Reply-To: <1325007582-31610-1-git-send-email-paul.gortmaker@windriver.com>

From: Allan Stephens <allan.stephens@windriver.com>

Gets rid of an unnecessary check in the routine that updates the port id
of a node's name publications when the node is assigned a network address,
since the routine is only invoked if the new address is different from
the existing one.

Signed-off-by: Allan Stephens <allan.stephens@windriver.com>
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
---
 net/tipc/name_distr.c |   12 +++++-------
 1 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c
index b7ca1bd..be8306f 100644
--- a/net/tipc/name_distr.c
+++ b/net/tipc/name_distr.c
@@ -322,10 +322,9 @@ void tipc_named_recv(struct sk_buff *buf)
 /**
  * tipc_named_reinit - re-initialize local publication list
  *
- * This routine is called whenever TIPC networking is (re)enabled.
+ * This routine is called whenever TIPC networking is enabled.
  * All existing publications by this node that have "cluster" or "zone" scope
- * are updated to reflect the node's current network address.
- * (If the node's address is unchanged, the update loop terminates immediately.)
+ * are updated to reflect the node's new network address.
  */
 
 void tipc_named_reinit(void)
@@ -333,10 +332,9 @@ void tipc_named_reinit(void)
 	struct publication *publ;
 
 	write_lock_bh(&tipc_nametbl_lock);
-	list_for_each_entry(publ, &publ_root, local_list) {
-		if (publ->node == tipc_own_addr)
-			break;
+
+	list_for_each_entry(publ, &publ_root, local_list)
 		publ->node = tipc_own_addr;
-	}
+
 	write_unlock_bh(&tipc_nametbl_lock);
 }
-- 
1.7.4.4

^ permalink raw reply related

* [PATCH net-next 15/23] tipc: Minor correction to TIPC module unloading
From: Paul Gortmaker @ 2011-12-27 17:39 UTC (permalink / raw)
  To: davem; +Cc: netdev, allan.stephens, ying.xue, Paul Gortmaker
In-Reply-To: <1325007582-31610-1-git-send-email-paul.gortmaker@windriver.com>

From: Allan Stephens <allan.stephens@windriver.com>

Modifies TIPC's module unloading logic to switch itself into "single
node" mode before starting to terminate networking support. This helps
to ensure that no operations that require TIPC to be in "networking"
mode can initiate once unloading starts.

Signed-off-by: Allan Stephens <allan.stephens@windriver.com>
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
---
 net/tipc/net.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/net/tipc/net.c b/net/tipc/net.c
index fafef6c..e13162f 100644
--- a/net/tipc/net.c
+++ b/net/tipc/net.c
@@ -207,8 +207,8 @@ void tipc_net_stop(void)
 	if (tipc_mode != TIPC_NET_MODE)
 		return;
 	write_lock_bh(&tipc_net_lock);
-	tipc_bearer_stop();
 	tipc_mode = TIPC_NODE_MODE;
+	tipc_bearer_stop();
 	tipc_bclink_stop();
 	list_for_each_entry_safe(node, t_node, &tipc_node_list, list)
 		tipc_node_delete(node);
-- 
1.7.4.4

^ permalink raw reply related

* [PATCH net-next 13/23] tipc: Do timely cleanup of disabled Ethernet bearer resources
From: Paul Gortmaker @ 2011-12-27 17:39 UTC (permalink / raw)
  To: davem; +Cc: netdev, allan.stephens, ying.xue, Paul Gortmaker
In-Reply-To: <1325007582-31610-1-git-send-email-paul.gortmaker@windriver.com>

From: Allan Stephens <allan.stephens@windriver.com>

Modifies Ethernet bearer disable logic to break the association between
the bearer and its device driver at the time the bearer is disabled,
rather than when the TIPC module is unloaded. This allows the array
entry used by the disabled bearer to be re-used if the same bearer (or
a different one) is subsequently enabled.

Signed-off-by: Allan Stephens <allan.stephens@windriver.com>
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
---
 net/tipc/eth_media.c |   39 +++++++++++++++++++++++++++------------
 1 files changed, 27 insertions(+), 12 deletions(-)

diff --git a/net/tipc/eth_media.c b/net/tipc/eth_media.c
index 23bf67b..236155c 100644
--- a/net/tipc/eth_media.c
+++ b/net/tipc/eth_media.c
@@ -46,12 +46,14 @@
  * @bearer: ptr to associated "generic" bearer structure
  * @dev: ptr to associated Ethernet network device
  * @tipc_packet_type: used in binding TIPC to Ethernet driver
+ * @cleanup: work item used when disabling bearer
  */
 
 struct eth_bearer {
 	struct tipc_bearer *bearer;
 	struct net_device *dev;
 	struct packet_type tipc_packet_type;
+	struct work_struct cleanup;
 };
 
 static struct media eth_media_info;
@@ -192,16 +194,36 @@ static int enable_bearer(struct tipc_bearer *tb_ptr)
 }
 
 /**
+ * cleanup_bearer - break association between Ethernet 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 eth_bearer *eb_ptr =
+		container_of(work, struct eth_bearer, cleanup);
+
+	dev_remove_pack(&eb_ptr->tipc_packet_type);
+	dev_put(eb_ptr->dev);
+	eb_ptr->dev = NULL;
+}
+
+/**
  * disable_bearer - detach TIPC bearer from an Ethernet interface
  *
- * We really should do dev_remove_pack() here, but this function can not be
- * called at tasklet level. => Use eth_bearer->bearer as a flag to throw away
- * incoming buffers, & postpone dev_remove_pack() to eth_media_stop() on exit.
+ * 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_bearer(struct tipc_bearer *tb_ptr)
 {
-	((struct eth_bearer *)tb_ptr->usr_handle)->bearer = NULL;
+	struct eth_bearer *eb_ptr = (struct eth_bearer *)tb_ptr->usr_handle;
+
+	eb_ptr->bearer = NULL;
+	INIT_WORK(&eb_ptr->cleanup, cleanup_bearer);
+	schedule_work(&eb_ptr->cleanup);
 }
 
 /**
@@ -369,18 +391,11 @@ int tipc_eth_media_start(void)
 
 void tipc_eth_media_stop(void)
 {
-	int i;
-
 	if (!eth_started)
 		return;
 
+	flush_scheduled_work();
 	unregister_netdevice_notifier(&notifier);
-	for (i = 0; i < MAX_ETH_BEARERS ; i++) {
-		if (eth_bearers[i].dev) {
-			dev_remove_pack(&eth_bearers[i].tipc_packet_type);
-			dev_put(eth_bearers[i].dev);
-		}
-	}
 	memset(&eth_bearers, 0, sizeof(eth_bearers));
 	eth_started = 0;
 }
-- 
1.7.4.4

^ permalink raw reply related

* [PATCH net-next 14/23] tipc: Eliminate useless memset operations in Ethernet media support
From: Paul Gortmaker @ 2011-12-27 17:39 UTC (permalink / raw)
  To: davem; +Cc: netdev, allan.stephens, ying.xue, Paul Gortmaker
In-Reply-To: <1325007582-31610-1-git-send-email-paul.gortmaker@windriver.com>

From: Allan Stephens <allan.stephens@windriver.com>

Gets rid of two pointless operations that zero out the array used to
record information about TIPC's Ethernet bearers. There is no need to
initialize the array on start up since it is a global variable that is
already zero'd out, and there is no need to zero it out on exit because
the array is never referenced again.

Signed-off-by: Allan Stephens <allan.stephens@windriver.com>
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
---
 net/tipc/eth_media.c |    3 ---
 1 files changed, 0 insertions(+), 3 deletions(-)

diff --git a/net/tipc/eth_media.c b/net/tipc/eth_media.c
index 236155c..cd0a4b8 100644
--- a/net/tipc/eth_media.c
+++ b/net/tipc/eth_media.c
@@ -371,8 +371,6 @@ int tipc_eth_media_start(void)
 	if (eth_started)
 		return -EINVAL;
 
-	memset(eth_bearers, 0, sizeof(eth_bearers));
-
 	res = tipc_register_media(&eth_media_info);
 	if (res)
 		return res;
@@ -396,6 +394,5 @@ void tipc_eth_media_stop(void)
 
 	flush_scheduled_work();
 	unregister_netdevice_notifier(&notifier);
-	memset(&eth_bearers, 0, sizeof(eth_bearers));
 	eth_started = 0;
 }
-- 
1.7.4.4

^ permalink raw reply related

* [PATCH net-next 12/23] tipc: Minor optimization to deactivation of Ethernet media suppot
From: Paul Gortmaker @ 2011-12-27 17:39 UTC (permalink / raw)
  To: davem; +Cc: netdev, allan.stephens, ying.xue, Paul Gortmaker
In-Reply-To: <1325007582-31610-1-git-send-email-paul.gortmaker@windriver.com>

From: Allan Stephens <allan.stephens@windriver.com>

Change TIPC's shutdown code to deactivate generic networking support
before terminating Ethernet media support. The deactivation of generic
networking support causes all existing bearers to be destroyed, meaning
the Ethernet media termination routine no longer has to bother marking
them as unavailable.

Signed-off-by: Allan Stephens <allan.stephens@windriver.com>
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
---
 net/tipc/core.c      |    2 +-
 net/tipc/eth_media.c |    4 ----
 2 files changed, 1 insertions(+), 5 deletions(-)

diff --git a/net/tipc/core.c b/net/tipc/core.c
index c21331d..2691cd5 100644
--- a/net/tipc/core.c
+++ b/net/tipc/core.c
@@ -99,8 +99,8 @@ struct sk_buff *tipc_buf_acquire(u32 size)
 
 static void tipc_core_stop_net(void)
 {
-	tipc_eth_media_stop();
 	tipc_net_stop();
+	tipc_eth_media_stop();
 }
 
 /**
diff --git a/net/tipc/eth_media.c b/net/tipc/eth_media.c
index 3b75c0d..23bf67b 100644
--- a/net/tipc/eth_media.c
+++ b/net/tipc/eth_media.c
@@ -376,10 +376,6 @@ void tipc_eth_media_stop(void)
 
 	unregister_netdevice_notifier(&notifier);
 	for (i = 0; i < MAX_ETH_BEARERS ; i++) {
-		if (eth_bearers[i].bearer) {
-			eth_bearers[i].bearer->blocked = 1;
-			eth_bearers[i].bearer = NULL;
-		}
 		if (eth_bearers[i].dev) {
 			dev_remove_pack(&eth_bearers[i].tipc_packet_type);
 			dev_put(eth_bearers[i].dev);
-- 
1.7.4.4

^ permalink raw reply related

* [PATCH net-next 11/23] tipc: Revise comment justifying release of configuration spinlock
From: Paul Gortmaker @ 2011-12-27 17:39 UTC (permalink / raw)
  To: davem; +Cc: netdev, allan.stephens, ying.xue, Paul Gortmaker
In-Reply-To: <1325007582-31610-1-git-send-email-paul.gortmaker@windriver.com>

From: Allan Stephens <allan.stephens@windriver.com>

Comment-only change to better explain why TIPC's configuration lock is
temporarily released while activating support for network interfaces,
and why the existing activation code doesn't require rework.

Signed-off-by: Allan Stephens <allan.stephens@windriver.com>
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
---
 net/tipc/config.c |   13 ++++++-------
 1 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/net/tipc/config.c b/net/tipc/config.c
index b25a396..4785bf2 100644
--- a/net/tipc/config.c
+++ b/net/tipc/config.c
@@ -184,13 +184,12 @@ static struct sk_buff *cfg_set_own_addr(void)
 						   " (cannot change node address once assigned)");
 
 	/*
-	 * Must release all spinlocks before calling start_net() because
-	 * Linux version of TIPC calls eth_media_start() which calls
-	 * register_netdevice_notifier() which may block!
-	 *
-	 * Temporarily releasing the lock should be harmless for non-Linux TIPC,
-	 * but Linux version of eth_media_start() should really be reworked
-	 * so that it can be called with spinlocks held.
+	 * Must temporarily release configuration spinlock while switching into
+	 * networking mode as it calls tipc_eth_media_start(), which may sleep.
+	 * Releasing the lock is harmless as other locally-issued configuration
+	 * commands won't occur until this one completes, and remotely-issued
+	 * configuration commands can't be received until a local configuration
+	 * command to enable the first bearer is received and processed.
 	 */
 
 	spin_unlock_bh(&config_lock);
-- 
1.7.4.4

^ permalink raw reply related

* [PATCH net-next 10/23] tipc: Allow run-time alteration of default link settings
From: Paul Gortmaker @ 2011-12-27 17:39 UTC (permalink / raw)
  To: davem; +Cc: netdev, allan.stephens, ying.xue, Paul Gortmaker
In-Reply-To: <1325007582-31610-1-git-send-email-paul.gortmaker@windriver.com>

From: Allan Stephens <allan.stephens@windriver.com>

Permits run-time alteration of default link settings on a per-media
and per-bearer basis, in addition to the existing per-link basis.
The following syntax can now be used:

    tipc-config -lt=<link-name|bearer-name|media-name>/<tolerance>
    tipc-config -lp=<link-name|bearer-name|media-name>/<priority>
    tipc-config -lw=<link-name|bearer-name|media-name>/<window>

Note that changes to the default settings for a given media type has
no effect on the default settings used by existing bearers. Similarly,
changes to default bearer settings has no effect on existing link
endpoints that utilize that interface.

Thanks to Florian Westphal <fw@strlen.de> for his contributions to
the development of this enhancement.

Signed-off-by: Allan Stephens <allan.stephens@windriver.com>
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
---
 net/tipc/bearer.c |   18 ++++---
 net/tipc/bearer.h |    8 +++
 net/tipc/link.c   |  150 ++++++++++++++++++++++++++++++++++++++--------------
 3 files changed, 127 insertions(+), 49 deletions(-)

diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c
index aa37261..b40e98a 100644
--- a/net/tipc/bearer.c
+++ b/net/tipc/bearer.c
@@ -65,10 +65,10 @@ static int media_name_valid(const char *name)
 }
 
 /**
- * media_find - locates specified media object by name
+ * tipc_media_find - locates specified media object by name
  */
 
-static struct media *media_find(const char *name)
+struct media *tipc_media_find(const char *name)
 {
 	u32 i;
 
@@ -118,7 +118,7 @@ int  tipc_register_media(struct media *m_ptr)
 		goto exit;
 	if (media_count >= MAX_MEDIA)
 		goto exit;
-	if (media_find(m_ptr->name) || media_find_id(m_ptr->type_id))
+	if (tipc_media_find(m_ptr->name) || media_find_id(m_ptr->type_id))
 		goto exit;
 
 	media_list[media_count] = m_ptr;
@@ -229,10 +229,10 @@ static int bearer_name_validate(const char *name,
 }
 
 /**
- * bearer_find - locates bearer object with matching bearer name
+ * tipc_bearer_find - locates bearer object with matching bearer name
  */
 
-static struct tipc_bearer *bearer_find(const char *name)
+struct tipc_bearer *tipc_bearer_find(const char *name)
 {
 	struct tipc_bearer *b_ptr;
 	u32 i;
@@ -463,7 +463,7 @@ int tipc_enable_bearer(const char *name, u32 disc_domain, u32 priority)
 
 	write_lock_bh(&tipc_net_lock);
 
-	m_ptr = media_find(b_name.media_name);
+	m_ptr = tipc_media_find(b_name.media_name);
 	if (!m_ptr) {
 		warn("Bearer <%s> rejected, media <%s> not registered\n", name,
 		     b_name.media_name);
@@ -513,6 +513,8 @@ restart:
 
 	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';
 	b_ptr->active = 1;
 	b_ptr->priority = priority;
@@ -546,7 +548,7 @@ int tipc_block_bearer(const char *name)
 	struct link *temp_l_ptr;
 
 	read_lock_bh(&tipc_net_lock);
-	b_ptr = bearer_find(name);
+	b_ptr = tipc_bearer_find(name);
 	if (!b_ptr) {
 		warn("Attempt to block unknown bearer <%s>\n", name);
 		read_unlock_bh(&tipc_net_lock);
@@ -600,7 +602,7 @@ int tipc_disable_bearer(const char *name)
 	int res;
 
 	write_lock_bh(&tipc_net_lock);
-	b_ptr = bearer_find(name);
+	b_ptr = tipc_bearer_find(name);
 	if (b_ptr == NULL) {
 		warn("Attempt to disable unknown bearer <%s>\n", name);
 		res = -EINVAL;
diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h
index 54a5a57..cfe77c4 100644
--- a/net/tipc/bearer.h
+++ b/net/tipc/bearer.h
@@ -118,6 +118,8 @@ struct media {
  * @name: bearer name (format = media:interface)
  * @media: ptr to media structure associated with bearer
  * @priority: default link priority for bearer
+ * @window: default window size for bearer
+ * @tolerance: default link tolerance for bearer
  * @identity: array index of this bearer within TIPC bearer array
  * @link_req: ptr to (optional) structure making periodic link setup requests
  * @links: list of non-congested links associated with bearer
@@ -139,6 +141,8 @@ struct tipc_bearer {
 	spinlock_t lock;
 	struct media *media;
 	u32 priority;
+	u32 window;
+	u32 tolerance;
 	u32 identity;
 	struct link_req *link_req;
 	struct list_head links;
@@ -176,6 +180,8 @@ int tipc_disable_bearer(const char *name);
 int  tipc_eth_media_start(void);
 void tipc_eth_media_stop(void);
 
+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(struct print_buf *pb, struct tipc_media_addr *a);
 struct sk_buff *tipc_media_get_names(void);
 
@@ -183,7 +189,9 @@ struct sk_buff *tipc_bearer_get_names(void);
 void tipc_bearer_add_dest(struct tipc_bearer *b_ptr, u32 dest);
 void tipc_bearer_remove_dest(struct tipc_bearer *b_ptr, u32 dest);
 void tipc_bearer_schedule(struct tipc_bearer *b_ptr, struct link *l_ptr);
+struct tipc_bearer *tipc_bearer_find(const char *name);
 struct tipc_bearer *tipc_bearer_find_interface(const char *if_name);
+struct media *tipc_media_find(const char *name);
 int tipc_bearer_resolve_congestion(struct tipc_bearer *b_ptr, struct link *l_ptr);
 int tipc_bearer_congested(struct tipc_bearer *b_ptr, struct link *l_ptr);
 void tipc_bearer_stop(void);
diff --git a/net/tipc/link.c b/net/tipc/link.c
index ae98a72..332915e 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -343,7 +343,7 @@ struct link *tipc_link_create(struct tipc_node *n_ptr,
 	l_ptr->checkpoint = 1;
 	l_ptr->peer_session = INVALID_SESSION;
 	l_ptr->b_ptr = b_ptr;
-	link_set_supervision_props(l_ptr, b_ptr->media->tolerance);
+	link_set_supervision_props(l_ptr, b_ptr->tolerance);
 	l_ptr->state = RESET_UNKNOWN;
 
 	l_ptr->pmsg = (struct tipc_msg *)&l_ptr->proto_msg;
@@ -355,7 +355,7 @@ struct link *tipc_link_create(struct tipc_node *n_ptr,
 	strcpy((char *)msg_data(msg), if_name);
 
 	l_ptr->priority = b_ptr->priority;
-	tipc_link_set_queue_limits(l_ptr, b_ptr->media->window);
+	tipc_link_set_queue_limits(l_ptr, b_ptr->window);
 
 	link_init_max_pkt(l_ptr);
 
@@ -2754,13 +2754,113 @@ static struct link *link_find_link(const char *name, struct tipc_node **node)
 	return l_ptr;
 }
 
+/**
+ * link_value_is_valid -- validate proposed link tolerance/priority/window
+ *
+ * @cmd - value type (TIPC_CMD_SET_LINK_*)
+ * @new_value - the new value
+ *
+ * Returns 1 if value is within range, 0 if not.
+ */
+
+static int link_value_is_valid(u16 cmd, u32 new_value)
+{
+	switch (cmd) {
+	case TIPC_CMD_SET_LINK_TOL:
+		return (new_value >= TIPC_MIN_LINK_TOL) &&
+			(new_value <= TIPC_MAX_LINK_TOL);
+	case TIPC_CMD_SET_LINK_PRI:
+		return (new_value <= TIPC_MAX_LINK_PRI);
+	case TIPC_CMD_SET_LINK_WINDOW:
+		return (new_value >= TIPC_MIN_LINK_WIN) &&
+			(new_value <= TIPC_MAX_LINK_WIN);
+	}
+	return 0;
+}
+
+
+/**
+ * link_cmd_set_value - change priority/tolerance/window for link/bearer/media
+ * @name - ptr to link, bearer, or media name
+ * @new_value - new value of link, bearer, or media setting
+ * @cmd - which link, bearer, or media attribute to set (TIPC_CMD_SET_LINK_*)
+ *
+ * Caller must hold 'tipc_net_lock' to ensure link/bearer/media is not deleted.
+ *
+ * Returns 0 if value updated and negative value on error.
+ */
+
+static int link_cmd_set_value(const char *name, u32 new_value, u16 cmd)
+{
+	struct tipc_node *node;
+	struct link *l_ptr;
+	struct tipc_bearer *b_ptr;
+	struct media *m_ptr;
+
+	l_ptr = link_find_link(name, &node);
+	if (l_ptr) {
+		/*
+		 * acquire node lock for tipc_link_send_proto_msg().
+		 * see "TIPC locking policy" in net.c.
+		 */
+		tipc_node_lock(node);
+		switch (cmd) {
+		case TIPC_CMD_SET_LINK_TOL:
+			link_set_supervision_props(l_ptr, new_value);
+			tipc_link_send_proto_msg(l_ptr,
+				STATE_MSG, 0, 0, new_value, 0, 0);
+			break;
+		case TIPC_CMD_SET_LINK_PRI:
+			l_ptr->priority = new_value;
+			tipc_link_send_proto_msg(l_ptr,
+				STATE_MSG, 0, 0, 0, new_value, 0);
+			break;
+		case TIPC_CMD_SET_LINK_WINDOW:
+			tipc_link_set_queue_limits(l_ptr, new_value);
+			break;
+		}
+		tipc_node_unlock(node);
+		return 0;
+	}
+
+	b_ptr = tipc_bearer_find(name);
+	if (b_ptr) {
+		switch (cmd) {
+		case TIPC_CMD_SET_LINK_TOL:
+			b_ptr->tolerance = new_value;
+			return 0;
+		case TIPC_CMD_SET_LINK_PRI:
+			b_ptr->priority = new_value;
+			return 0;
+		case TIPC_CMD_SET_LINK_WINDOW:
+			b_ptr->window = new_value;
+			return 0;
+		}
+		return -EINVAL;
+	}
+
+	m_ptr = tipc_media_find(name);
+	if (!m_ptr)
+		return -ENODEV;
+	switch (cmd) {
+	case TIPC_CMD_SET_LINK_TOL:
+		m_ptr->tolerance = new_value;
+		return 0;
+	case TIPC_CMD_SET_LINK_PRI:
+		m_ptr->priority = new_value;
+		return 0;
+	case TIPC_CMD_SET_LINK_WINDOW:
+		m_ptr->window = new_value;
+		return 0;
+	}
+	return -EINVAL;
+}
+
 struct sk_buff *tipc_link_cmd_config(const void *req_tlv_area, int req_tlv_space,
 				     u16 cmd)
 {
 	struct tipc_link_config *args;
 	u32 new_value;
-	struct link *l_ptr;
-	struct tipc_node *node;
 	int res;
 
 	if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_LINK_CONFIG))
@@ -2769,6 +2869,10 @@ struct sk_buff *tipc_link_cmd_config(const void *req_tlv_area, int req_tlv_space
 	args = (struct tipc_link_config *)TLV_DATA(req_tlv_area);
 	new_value = ntohl(args->value);
 
+	if (!link_value_is_valid(cmd, new_value))
+		return tipc_cfg_reply_error_string(
+			"cannot change, value invalid");
+
 	if (!strcmp(args->name, tipc_bclink_name)) {
 		if ((cmd == TIPC_CMD_SET_LINK_WINDOW) &&
 		    (tipc_bclink_set_queue_limits(new_value) == 0))
@@ -2778,43 +2882,7 @@ struct sk_buff *tipc_link_cmd_config(const void *req_tlv_area, int req_tlv_space
 	}
 
 	read_lock_bh(&tipc_net_lock);
-	l_ptr = link_find_link(args->name, &node);
-	if (!l_ptr) {
-		read_unlock_bh(&tipc_net_lock);
-		return tipc_cfg_reply_error_string("link not found");
-	}
-
-	tipc_node_lock(node);
-	res = -EINVAL;
-	switch (cmd) {
-	case TIPC_CMD_SET_LINK_TOL:
-		if ((new_value >= TIPC_MIN_LINK_TOL) &&
-		    (new_value <= TIPC_MAX_LINK_TOL)) {
-			link_set_supervision_props(l_ptr, new_value);
-			tipc_link_send_proto_msg(l_ptr, STATE_MSG,
-						 0, 0, new_value, 0, 0);
-			res = 0;
-		}
-		break;
-	case TIPC_CMD_SET_LINK_PRI:
-		if ((new_value >= TIPC_MIN_LINK_PRI) &&
-		    (new_value <= TIPC_MAX_LINK_PRI)) {
-			l_ptr->priority = new_value;
-			tipc_link_send_proto_msg(l_ptr, STATE_MSG,
-						 0, 0, 0, new_value, 0);
-			res = 0;
-		}
-		break;
-	case TIPC_CMD_SET_LINK_WINDOW:
-		if ((new_value >= TIPC_MIN_LINK_WIN) &&
-		    (new_value <= TIPC_MAX_LINK_WIN)) {
-			tipc_link_set_queue_limits(l_ptr, new_value);
-			res = 0;
-		}
-		break;
-	}
-	tipc_node_unlock(node);
-
+	res = link_cmd_set_value(args->name, new_value, cmd);
 	read_unlock_bh(&tipc_net_lock);
 	if (res)
 		return tipc_cfg_reply_error_string("cannot change link setting");
-- 
1.7.4.4

^ permalink raw reply related

* [PATCH net-next 09/23] tipc: Ignore neighbor discovery messages containing invalid address
From: Paul Gortmaker @ 2011-12-27 17:39 UTC (permalink / raw)
  To: davem; +Cc: netdev, allan.stephens, ying.xue, Paul Gortmaker
In-Reply-To: <1325007582-31610-1-git-send-email-paul.gortmaker@windriver.com>

From: Allan Stephens <allan.stephens@windriver.com>

Adds a check to ensure that TIPC ignores an incoming neighbor discovery
message that specifies an invalid media address as its source. The check
ensures that the source address is a valid, non-broadcast address that
could legally be used by a neighboring link endpoint.

Signed-off-by: Allan Stephens <allan.stephens@windriver.com>
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
---
 net/tipc/discover.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/net/tipc/discover.c b/net/tipc/discover.c
index 1ea2d44..420e032 100644
--- a/net/tipc/discover.c
+++ b/net/tipc/discover.c
@@ -130,12 +130,15 @@ void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr)
 	u32 type = msg_type(msg);
 	int link_fully_up;
 
+	media_addr.broadcast = 1;
 	b_ptr->media->msg2addr(&media_addr, msg_media_addr(msg));
 	buf_discard(buf);
 
 	/* Validate discovery message from requesting node */
 	if (net_id != tipc_net_id)
 		return;
+	if (media_addr.broadcast)
+		return;
 	if (!tipc_addr_domain_valid(dest))
 		return;
 	if (!tipc_addr_node_valid(orig))
-- 
1.7.4.4

^ permalink raw reply related

* [PATCH net-next 08/23] tipc: Hide media-specific addressing details from generic bearer code
From: Paul Gortmaker @ 2011-12-27 17:39 UTC (permalink / raw)
  To: davem; +Cc: netdev, allan.stephens, ying.xue, Paul Gortmaker
In-Reply-To: <1325007582-31610-1-git-send-email-paul.gortmaker@windriver.com>

From: Allan Stephens <allan.stephens@windriver.com>

Reworks TIPC's media address data structure and associated processing
routines to transfer all media-specific details of address conversion
to the associated TIPC media adaptation code. TIPC's generic bearer code
now only needs to know which media type an address is associated with
and whether or not it is a broadcast address, and totally ignores the
"value" field that contains the actual media-specific addressing info.

These changes eliminate the need for a number of endianness conversion
operations and will make it easier for TIPC to support new media types
in the future.

Signed-off-by: Allan Stephens <allan.stephens@windriver.com>
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
---
 net/tipc/bearer.c    |   14 ++++++--------
 net/tipc/bearer.h    |   17 ++++++++---------
 net/tipc/discover.c  |    4 ++--
 net/tipc/eth_media.c |   22 +++++++++++++---------
 net/tipc/msg.c       |    9 ++++++---
 net/tipc/msg.h       |   16 ++++++----------
 6 files changed, 41 insertions(+), 41 deletions(-)

diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c
index 17652f2..aa37261 100644
--- a/net/tipc/bearer.c
+++ b/net/tipc/bearer.c
@@ -108,7 +108,8 @@ int  tipc_register_media(struct media *m_ptr)
 
 	if (!media_name_valid(m_ptr->name))
 		goto exit;
-	if (m_ptr->bcast_addr.type != htonl(m_ptr->type_id))
+	if ((m_ptr->bcast_addr.media_id != m_ptr->type_id) ||
+	    !m_ptr->bcast_addr.broadcast)
 		goto exit;
 	if (m_ptr->priority > TIPC_MAX_LINK_PRI)
 		goto exit;
@@ -138,20 +139,17 @@ void tipc_media_addr_printf(struct print_buf *pb, struct tipc_media_addr *a)
 {
 	char addr_str[MAX_ADDR_STR];
 	struct media *m_ptr;
-	u32 media_type;
 
-	media_type = ntohl(a->type);
-	m_ptr = media_find_id(media_type);
+	m_ptr = media_find_id(a->media_id);
 
 	if (m_ptr && !m_ptr->addr2str(a, addr_str, sizeof(addr_str)))
 		tipc_printf(pb, "%s(%s)", m_ptr->name, addr_str);
 	else {
-		unchar *addr = (unchar *)&a->dev_addr;
 		u32 i;
 
-		tipc_printf(pb, "UNKNOWN(%u)", media_type);
-		for (i = 0; i < (sizeof(*a) - sizeof(a->type)); i++)
-			tipc_printf(pb, "-%02x", addr[i]);
+		tipc_printf(pb, "UNKNOWN(%u)", a->media_id);
+		for (i = 0; i < sizeof(a->value); i++)
+			tipc_printf(pb, "-%02x", a->value[i]);
 	}
 }
 
diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h
index 41a61d2..54a5a57 100644
--- a/net/tipc/bearer.h
+++ b/net/tipc/bearer.h
@@ -59,17 +59,16 @@
 #define TIPC_MEDIA_TYPE_ETH	1
 
 /*
- * Destination address structure used by TIPC bearers when sending messages
- *
- * IMPORTANT: The fields of this structure MUST be stored using the specified
- * byte order indicated below, as the structure is exchanged between nodes
- * as part of a link setup process.
+ * struct tipc_media_addr - destination address used by TIPC bearers
+ * @value: address info (format defined by media)
+ * @media_id: TIPC media type identifier
+ * @broadcast: non-zero if address is a broadcast address
  */
+
 struct tipc_media_addr {
-	__be32  type;			/* bearer type (network byte order) */
-	union {
-		__u8   eth_addr[6];	/* 48 bit Ethernet addr (byte array) */
-	} dev_addr;
+	u8 value[TIPC_MEDIA_ADDR_SIZE];
+	u8 media_id;
+	u8 broadcast;
 };
 
 struct tipc_bearer;
diff --git a/net/tipc/discover.c b/net/tipc/discover.c
index f2fb96e..1ea2d44 100644
--- a/net/tipc/discover.c
+++ b/net/tipc/discover.c
@@ -84,7 +84,7 @@ static struct sk_buff *tipc_disc_init_msg(u32 type,
 		msg_set_non_seq(msg, 1);
 		msg_set_dest_domain(msg, dest_domain);
 		msg_set_bc_netid(msg, tipc_net_id);
-		msg_set_media_addr(msg, &b_ptr->addr);
+		b_ptr->media->addr2msg(&b_ptr->addr, msg_media_addr(msg));
 	}
 	return buf;
 }
@@ -130,7 +130,7 @@ void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr)
 	u32 type = msg_type(msg);
 	int link_fully_up;
 
-	msg_get_media_addr(msg, &media_addr);
+	b_ptr->media->msg2addr(&media_addr, msg_media_addr(msg));
 	buf_discard(buf);
 
 	/* Validate discovery message from requesting node */
diff --git a/net/tipc/eth_media.c b/net/tipc/eth_media.c
index ebba0fc..3b75c0d 100644
--- a/net/tipc/eth_media.c
+++ b/net/tipc/eth_media.c
@@ -54,18 +54,24 @@ struct eth_bearer {
 	struct packet_type tipc_packet_type;
 };
 
+static struct media eth_media_info;
 static struct eth_bearer eth_bearers[MAX_ETH_BEARERS];
 static int eth_started;
 static struct notifier_block notifier;
 
 /**
  * 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(struct tipc_media_addr *a, char *mac)
 {
-	a->type = htonl(TIPC_MEDIA_TYPE_ETH);
-	memcpy(&a->dev_addr.eth_addr, mac, ETH_ALEN);
+	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, eth_media_info.bcast_addr.value, ETH_ALEN);
 }
 
 /**
@@ -94,7 +100,7 @@ static int send_msg(struct sk_buff *buf, struct tipc_bearer *tb_ptr,
 
 	skb_reset_network_header(clone);
 	clone->dev = dev;
-	dev_hard_header(clone, dev, ETH_P_TIPC, &dest->dev_addr.eth_addr,
+	dev_hard_header(clone, dev, ETH_P_TIPC, dest->value,
 			dev->dev_addr, clone->len);
 	dev_queue_xmit(clone);
 	return 0;
@@ -256,12 +262,10 @@ static int recv_notification(struct notifier_block *nb, unsigned long evt,
 
 static int eth_addr2str(struct tipc_media_addr *a, char *str_buf, int str_size)
 {
-	unchar *addr = (unchar *)&a->dev_addr;
-
 	if (str_size < 18)	/* 18 = strlen("aa:bb:cc:dd:ee:ff\0") */
 		return 1;
 
-	sprintf(str_buf, "%pM", addr);
+	sprintf(str_buf, "%pM", a->value);
 	return 0;
 }
 
@@ -293,7 +297,7 @@ static int 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;
-	memcpy(msg_area + ETH_ADDR_OFFSET, a->dev_addr.eth_addr, ETH_ALEN);
+	memcpy(msg_area + ETH_ADDR_OFFSET, a->value, ETH_ALEN);
 	return 0;
 }
 
@@ -322,8 +326,8 @@ static struct media eth_media_info = {
 	.str2addr	= eth_str2addr,
 	.addr2msg	= eth_addr2msg,
 	.msg2addr	= eth_msg2addr,
-	.bcast_addr	= { htonl(TIPC_MEDIA_TYPE_ETH),
-			    { {0xff, 0xff, 0xff, 0xff, 0xff, 0xff} } },
+	.bcast_addr	= { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
+			    TIPC_MEDIA_TYPE_ETH, 1 },
 	.priority	= TIPC_DEF_LINK_PRI,
 	.tolerance	= TIPC_DEF_LINK_TOL,
 	.window		= TIPC_DEF_LINK_WIN,
diff --git a/net/tipc/msg.c b/net/tipc/msg.c
index 83d5096..3e4d3e2 100644
--- a/net/tipc/msg.c
+++ b/net/tipc/msg.c
@@ -333,11 +333,14 @@ void tipc_msg_dbg(struct print_buf *buf, struct tipc_msg *msg, const char *str)
 	}
 
 	if (msg_user(msg) ==  LINK_CONFIG) {
-		u32 *raw = (u32 *)msg;
-		struct tipc_media_addr *orig = (struct tipc_media_addr *)&raw[5];
+		struct tipc_media_addr orig;
+
 		tipc_printf(buf, ":DDOM(%x):", msg_dest_domain(msg));
 		tipc_printf(buf, ":NETID(%u):", msg_bc_netid(msg));
-		tipc_media_addr_printf(buf, orig);
+		memcpy(orig.value, msg_media_addr(msg), sizeof(orig.value));
+		orig.media_id = 0;
+		orig.broadcast = 0;
+		tipc_media_addr_printf(buf, &orig);
 	}
 	if (msg_user(msg) == BCAST_PROTOCOL) {
 		tipc_printf(buf, "BCNACK:AFTER(%u):", msg_bcgap_after(msg));
diff --git a/net/tipc/msg.h b/net/tipc/msg.h
index d93178f..7b0cda1 100644
--- a/net/tipc/msg.h
+++ b/net/tipc/msg.h
@@ -78,6 +78,8 @@
 
 #define MAX_MSG_SIZE (MAX_H_SIZE + TIPC_MAX_USER_MSG_SIZE)
 
+#define TIPC_MEDIA_ADDR_OFFSET	5
+
 
 struct tipc_msg {
 	__be32 hdr[15];
@@ -682,6 +684,10 @@ static inline void msg_set_redundant_link(struct tipc_msg *m, u32 r)
 	msg_set_bits(m, 5, 12, 0x1, r);
 }
 
+static inline char *msg_media_addr(struct tipc_msg *m)
+{
+	return (char *)&m->hdr[TIPC_MEDIA_ADDR_OFFSET];
+}
 
 /*
  * Word 9
@@ -734,14 +740,4 @@ int tipc_msg_build(struct tipc_msg *hdr, struct iovec const *msg_sect,
 		   u32 num_sect, unsigned int total_len,
 			    int max_size, int usrmem, struct sk_buff **buf);
 
-static inline void msg_set_media_addr(struct tipc_msg *m, struct tipc_media_addr *a)
-{
-	memcpy(&((int *)m)[5], a, sizeof(*a));
-}
-
-static inline void msg_get_media_addr(struct tipc_msg *m, struct tipc_media_addr *a)
-{
-	memcpy(a, &((int *)m)[5], sizeof(*a));
-}
-
 #endif
-- 
1.7.4.4

^ permalink raw reply related

* [PATCH net-next 07/23] tipc: Add new address conversion routines for Ethernet media
From: Paul Gortmaker @ 2011-12-27 17:39 UTC (permalink / raw)
  To: davem; +Cc: netdev, allan.stephens, ying.xue, Paul Gortmaker
In-Reply-To: <1325007582-31610-1-git-send-email-paul.gortmaker@windriver.com>

From: Allan Stephens <allan.stephens@windriver.com>

Enhances TIPC's Ethernet media support to provide 3 new address conversion
routines, which allow TIPC to interpret an address that is in string form
and to convert an address to and from the 20 byte format used in TIPC's
neighbor discovery messages.

These routines are pre-requisites to a follow on commit that hides all
media-specific addressing details from TIPC's generic bearer code.

Signed-off-by: Allan Stephens <allan.stephens@windriver.com>
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
---
 net/tipc/bearer.h    |   19 ++++++++++++++-
 net/tipc/eth_media.c |   63 ++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 79 insertions(+), 3 deletions(-)

diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h
index 4e9367f..41a61d2 100644
--- a/net/tipc/bearer.h
+++ b/net/tipc/bearer.h
@@ -43,6 +43,17 @@
 #define MAX_MEDIA	2
 
 /*
+ * Identifiers associated with TIPC message header media address info
+ *
+ * - address info field is 20 bytes long
+ * - media type identifier located at offset 3
+ * - remaining bytes vary according to media type
+ */
+
+#define TIPC_MEDIA_ADDR_SIZE	20
+#define TIPC_MEDIA_TYPE_OFFSET	3
+
+/*
  * Identifiers of supported TIPC media types
  */
 #define TIPC_MEDIA_TYPE_ETH	1
@@ -68,7 +79,10 @@ struct tipc_bearer;
  * @send_msg: routine which handles buffer transmission
  * @enable_bearer: routine which enables a bearer
  * @disable_bearer: routine which disables a bearer
- * @addr2str: routine which converts bearer's address to string form
+ * @addr2str: routine which converts media address to string
+ * @str2addr: routine which converts media address from 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
@@ -84,6 +98,9 @@ struct media {
 	int (*enable_bearer)(struct tipc_bearer *b_ptr);
 	void (*disable_bearer)(struct tipc_bearer *b_ptr);
 	int (*addr2str)(struct tipc_media_addr *a, char *str_buf, int str_size);
+	int (*str2addr)(struct tipc_media_addr *a, char *str_buf);
+	int (*addr2msg)(struct tipc_media_addr *a, char *msg_area);
+	int (*msg2addr)(struct tipc_media_addr *a, char *msg_area);
 	struct tipc_media_addr bcast_addr;
 	u32 priority;
 	u32 tolerance;
diff --git a/net/tipc/eth_media.c b/net/tipc/eth_media.c
index 67f616a..ebba0fc 100644
--- a/net/tipc/eth_media.c
+++ b/net/tipc/eth_media.c
@@ -39,6 +39,8 @@
 
 #define MAX_ETH_BEARERS		MAX_BEARERS
 
+#define ETH_ADDR_OFFSET	4	/* message header offset of MAC address */
+
 /**
  * struct eth_bearer - Ethernet bearer data structure
  * @bearer: ptr to associated "generic" bearer structure
@@ -57,6 +59,16 @@ static int eth_started;
 static struct notifier_block notifier;
 
 /**
+ * eth_media_addr_set - initialize Ethernet media address structure
+ */
+
+static void eth_media_addr_set(struct tipc_media_addr *a, char *mac)
+{
+	a->type = htonl(TIPC_MEDIA_TYPE_ETH);
+	memcpy(&a->dev_addr.eth_addr, mac, ETH_ALEN);
+}
+
+/**
  * send_msg - send a TIPC message out over an Ethernet interface
  */
 
@@ -169,8 +181,7 @@ static int enable_bearer(struct tipc_bearer *tb_ptr)
 	tb_ptr->usr_handle = (void *)eb_ptr;
 	tb_ptr->mtu = dev->mtu;
 	tb_ptr->blocked = 0;
-	tb_ptr->addr.type = htonl(TIPC_MEDIA_TYPE_ETH);
-	memcpy(&tb_ptr->addr.dev_addr, dev->dev_addr, ETH_ALEN);
+	eth_media_addr_set(&tb_ptr->addr, (char *)dev->dev_addr);
 	return 0;
 }
 
@@ -254,6 +265,51 @@ static int eth_addr2str(struct tipc_media_addr *a, char *str_buf, int str_size)
 	return 0;
 }
 
+/**
+ * eth_str2addr - convert string to Ethernet address
+ */
+
+static int eth_str2addr(struct tipc_media_addr *a, char *str_buf)
+{
+	char mac[ETH_ALEN];
+	int r;
+
+	r = sscanf(str_buf, "%02x:%02x:%02x:%02x:%02x:%02x",
+		       (u32 *)&mac[0], (u32 *)&mac[1], (u32 *)&mac[2],
+		       (u32 *)&mac[3], (u32 *)&mac[4], (u32 *)&mac[5]);
+
+	if (r != ETH_ALEN)
+		return 1;
+
+	eth_media_addr_set(a, mac);
+	return 0;
+}
+
+/**
+ * eth_str2addr - convert Ethernet address format to message header format
+ */
+
+static int 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;
+	memcpy(msg_area + ETH_ADDR_OFFSET, a->dev_addr.eth_addr, ETH_ALEN);
+	return 0;
+}
+
+/**
+ * eth_str2addr - convert message header address format to Ethernet format
+ */
+
+static int eth_msg2addr(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(a, msg_area + ETH_ADDR_OFFSET);
+	return 0;
+}
+
 /*
  * Ethernet media registration info
  */
@@ -263,6 +319,9 @@ static struct media eth_media_info = {
 	.enable_bearer	= enable_bearer,
 	.disable_bearer	= disable_bearer,
 	.addr2str	= eth_addr2str,
+	.str2addr	= eth_str2addr,
+	.addr2msg	= eth_addr2msg,
+	.msg2addr	= eth_msg2addr,
 	.bcast_addr	= { htonl(TIPC_MEDIA_TYPE_ETH),
 			    { {0xff, 0xff, 0xff, 0xff, 0xff, 0xff} } },
 	.priority	= TIPC_DEF_LINK_PRI,
-- 
1.7.4.4

^ permalink raw reply related

* [PATCH net-next 06/23] tipc: Improve handling of media address printing errors
From: Paul Gortmaker @ 2011-12-27 17:39 UTC (permalink / raw)
  To: davem; +Cc: netdev, allan.stephens, ying.xue, Paul Gortmaker
In-Reply-To: <1325007582-31610-1-git-send-email-paul.gortmaker@windriver.com>

From: Allan Stephens <allan.stephens@windriver.com>

Enhances conversion of a media address to printable form so that an
unconvertable address will be displayed as a string of hex digits,
rather than not being displayed at all. (Also removes a pointless check
for the existence of the media-specific address conversion routine,
since the routine is not optional.)

Signed-off-by: Allan Stephens <allan.stephens@windriver.com>
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
---
 net/tipc/bearer.c    |   12 +++++-------
 net/tipc/bearer.h    |    3 +--
 net/tipc/eth_media.c |   12 ++++++------
 3 files changed, 12 insertions(+), 15 deletions(-)

diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c
index f908b80..17652f2 100644
--- a/net/tipc/bearer.c
+++ b/net/tipc/bearer.c
@@ -136,20 +136,18 @@ exit:
 
 void tipc_media_addr_printf(struct print_buf *pb, struct tipc_media_addr *a)
 {
+	char addr_str[MAX_ADDR_STR];
 	struct media *m_ptr;
 	u32 media_type;
-	u32 i;
 
 	media_type = ntohl(a->type);
 	m_ptr = media_find_id(media_type);
 
-	if (m_ptr && (m_ptr->addr2str != NULL)) {
-		char addr_str[MAX_ADDR_STR];
-
-		tipc_printf(pb, "%s(%s)", m_ptr->name,
-			    m_ptr->addr2str(a, addr_str, sizeof(addr_str)));
-	} else {
+	if (m_ptr && !m_ptr->addr2str(a, addr_str, sizeof(addr_str)))
+		tipc_printf(pb, "%s(%s)", m_ptr->name, addr_str);
+	else {
 		unchar *addr = (unchar *)&a->dev_addr;
+		u32 i;
 
 		tipc_printf(pb, "UNKNOWN(%u)", media_type);
 		for (i = 0; i < (sizeof(*a) - sizeof(a->type)); i++)
diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h
index 148ed04..4e9367f 100644
--- a/net/tipc/bearer.h
+++ b/net/tipc/bearer.h
@@ -83,8 +83,7 @@ struct media {
 			struct tipc_media_addr *dest);
 	int (*enable_bearer)(struct tipc_bearer *b_ptr);
 	void (*disable_bearer)(struct tipc_bearer *b_ptr);
-	char *(*addr2str)(struct tipc_media_addr *a,
-			  char *str_buf, int str_size);
+	int (*addr2str)(struct tipc_media_addr *a, char *str_buf, int str_size);
 	struct tipc_media_addr bcast_addr;
 	u32 priority;
 	u32 tolerance;
diff --git a/net/tipc/eth_media.c b/net/tipc/eth_media.c
index 15c685b..67f616a 100644
--- a/net/tipc/eth_media.c
+++ b/net/tipc/eth_media.c
@@ -243,15 +243,15 @@ static int recv_notification(struct notifier_block *nb, unsigned long evt,
  * eth_addr2str - convert Ethernet address to string
  */
 
-static char *eth_addr2str(struct tipc_media_addr *a, char *str_buf, int str_size)
+static int eth_addr2str(struct tipc_media_addr *a, char *str_buf, int str_size)
 {
 	unchar *addr = (unchar *)&a->dev_addr;
 
-	if (str_size < 18)
-		*str_buf = '\0';
-	else
-		sprintf(str_buf, "%pM", addr);
-	return str_buf;
+	if (str_size < 18)	/* 18 = strlen("aa:bb:cc:dd:ee:ff\0") */
+		return 1;
+
+	sprintf(str_buf, "%pM", addr);
+	return 0;
 }
 
 /*
-- 
1.7.4.4

^ permalink raw reply related

* [PATCH net-next 05/23] tipc: Streamline media registration error checking
From: Paul Gortmaker @ 2011-12-27 17:39 UTC (permalink / raw)
  To: davem; +Cc: netdev, allan.stephens, ying.xue, Paul Gortmaker
In-Reply-To: <1325007582-31610-1-git-send-email-paul.gortmaker@windriver.com>

From: Allan Stephens <allan.stephens@windriver.com>

Simplifies error handling performed during media registration, since
TIPC no longer supports the dynamic addition of new media types that
are potentially error-prone. These simplifications include the following:

1) No longer check for premature registration of a new media type.
2) No longer check for negative link priority values (which was pointless
   since such values are unsigned, and could cause a compiler warning).
3) No longer generate a warning describing the exact cause of any
   registration failure (just warns that overall registration failed).

Signed-off-by: Allan Stephens <allan.stephens@windriver.com>
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
---
 net/tipc/bearer.c |   37 ++++++++-----------------------------
 1 files changed, 8 insertions(+), 29 deletions(-)

diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c
index 9012a36..f908b80 100644
--- a/net/tipc/bearer.c
+++ b/net/tipc/bearer.c
@@ -106,48 +106,27 @@ int  tipc_register_media(struct media *m_ptr)
 
 	write_lock_bh(&tipc_net_lock);
 
-	if (tipc_mode != TIPC_NET_MODE) {
-		warn("Media <%s> rejected, not in networked mode yet\n",
-		     m_ptr->name);
+	if (!media_name_valid(m_ptr->name))
 		goto exit;
-	}
-	if (!media_name_valid(m_ptr->name)) {
-		warn("Media <%s> rejected, illegal name\n", m_ptr->name);
+	if (m_ptr->bcast_addr.type != htonl(m_ptr->type_id))
 		goto exit;
-	}
-	if (m_ptr->bcast_addr.type != htonl(m_ptr->type_id)) {
-		warn("Media <%s> rejected, illegal broadcast address\n",
-		     m_ptr->name);
-		goto exit;
-	}
-	if ((m_ptr->priority < TIPC_MIN_LINK_PRI) ||
-	    (m_ptr->priority > TIPC_MAX_LINK_PRI)) {
-		warn("Media <%s> rejected, illegal priority (%u)\n",
-		     m_ptr->name, m_ptr->priority);
+	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)) {
-		warn("Media <%s> rejected, illegal tolerance (%u)\n",
-		     m_ptr->name, m_ptr->tolerance);
+	    (m_ptr->tolerance > TIPC_MAX_LINK_TOL))
 		goto exit;
-	}
-
-	if (media_count >= MAX_MEDIA) {
-		warn("Media <%s> rejected, media limit reached (%u)\n",
-		     m_ptr->name, MAX_MEDIA);
+	if (media_count >= MAX_MEDIA)
 		goto exit;
-	}
-	if (media_find(m_ptr->name) || media_find_id(m_ptr->type_id)) {
-		warn("Media <%s> rejected, already registered\n", m_ptr->name);
+	if (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)
+		warn("Media <%s> registration error\n", m_ptr->name);
 	return res;
 }
 
-- 
1.7.4.4

^ permalink raw reply related

* [PATCH net-next 04/23] tipc: Eliminate duplication of media structures
From: Paul Gortmaker @ 2011-12-27 17:39 UTC (permalink / raw)
  To: davem; +Cc: netdev, allan.stephens, ying.xue, Paul Gortmaker
In-Reply-To: <1325007582-31610-1-git-send-email-paul.gortmaker@windriver.com>

From: Allan Stephens <allan.stephens@windriver.com>

Changes TIPC's list of registered media types from an array of media
structures to an array of pointers to media structures. This eliminates
the need to copy of the contents of the structure passed in during media
registration.

Signed-off-by: Allan Stephens <allan.stephens@windriver.com>
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
---
 net/tipc/bearer.c |   35 +++++++++++++++--------------------
 1 files changed, 15 insertions(+), 20 deletions(-)

diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c
index 9ff8920..9012a36 100644
--- a/net/tipc/bearer.c
+++ b/net/tipc/bearer.c
@@ -41,7 +41,7 @@
 
 #define MAX_ADDR_STR 32
 
-static struct media media_list[MAX_MEDIA];
+static struct media *media_list[MAX_MEDIA];
 static u32 media_count;
 
 struct tipc_bearer tipc_bearers[MAX_BEARERS];
@@ -70,12 +70,11 @@ static int media_name_valid(const char *name)
 
 static struct media *media_find(const char *name)
 {
-	struct media *m_ptr;
 	u32 i;
 
-	for (i = 0, m_ptr = media_list; i < media_count; i++, m_ptr++) {
-		if (!strcmp(m_ptr->name, name))
-			return m_ptr;
+	for (i = 0; i < media_count; i++) {
+		if (!strcmp(media_list[i]->name, name))
+			return media_list[i];
 	}
 	return NULL;
 }
@@ -89,8 +88,8 @@ static struct 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];
+		if (media_list[i]->type_id == type)
+			return media_list[i];
 	}
 	return NULL;
 }
@@ -144,7 +143,7 @@ int  tipc_register_media(struct media *m_ptr)
 		goto exit;
 	}
 
-	media_list[media_count] = *m_ptr;
+	media_list[media_count] = m_ptr;
 	media_count++;
 	res = 0;
 exit:
@@ -163,12 +162,9 @@ void tipc_media_addr_printf(struct print_buf *pb, struct tipc_media_addr *a)
 	u32 i;
 
 	media_type = ntohl(a->type);
-	for (i = 0, m_ptr = media_list; i < media_count; i++, m_ptr++) {
-		if (m_ptr->type_id == media_type)
-			break;
-	}
+	m_ptr = media_find_id(media_type);
 
-	if ((i < media_count) && (m_ptr->addr2str != NULL)) {
+	if (m_ptr && (m_ptr->addr2str != NULL)) {
 		char addr_str[MAX_ADDR_STR];
 
 		tipc_printf(pb, "%s(%s)", m_ptr->name,
@@ -189,7 +185,6 @@ void tipc_media_addr_printf(struct print_buf *pb, struct tipc_media_addr *a)
 struct sk_buff *tipc_media_get_names(void)
 {
 	struct sk_buff *buf;
-	struct media *m_ptr;
 	int i;
 
 	buf = tipc_cfg_reply_alloc(MAX_MEDIA * TLV_SPACE(TIPC_MAX_MEDIA_NAME));
@@ -197,9 +192,10 @@ struct sk_buff *tipc_media_get_names(void)
 		return NULL;
 
 	read_lock_bh(&tipc_net_lock);
-	for (i = 0, m_ptr = media_list; i < media_count; i++, m_ptr++) {
-		tipc_cfg_append_tlv(buf, TIPC_TLV_MEDIA_NAME, m_ptr->name,
-				    strlen(m_ptr->name) + 1);
+	for (i = 0; i < media_count; i++) {
+		tipc_cfg_append_tlv(buf, TIPC_TLV_MEDIA_NAME,
+				    media_list[i]->name,
+				    strlen(media_list[i]->name) + 1);
 	}
 	read_unlock_bh(&tipc_net_lock);
 	return buf;
@@ -300,7 +296,6 @@ struct tipc_bearer *tipc_bearer_find_interface(const char *if_name)
 struct sk_buff *tipc_bearer_get_names(void)
 {
 	struct sk_buff *buf;
-	struct media *m_ptr;
 	struct tipc_bearer *b_ptr;
 	int i, j;
 
@@ -309,10 +304,10 @@ struct sk_buff *tipc_bearer_get_names(void)
 		return NULL;
 
 	read_lock_bh(&tipc_net_lock);
-	for (i = 0, m_ptr = media_list; i < media_count; i++, m_ptr++) {
+	for (i = 0; i < media_count; i++) {
 		for (j = 0; j < MAX_BEARERS; j++) {
 			b_ptr = &tipc_bearers[j];
-			if (b_ptr->active && (b_ptr->media == m_ptr)) {
+			if (b_ptr->active && (b_ptr->media == media_list[i])) {
 				tipc_cfg_append_tlv(buf, TIPC_TLV_BEARER_NAME,
 						    b_ptr->name,
 						    strlen(b_ptr->name) + 1);
-- 
1.7.4.4

^ permalink raw reply related

* [PATCH net-next 03/23] tipc: Optimize detection of duplicate media registration
From: Paul Gortmaker @ 2011-12-27 17:39 UTC (permalink / raw)
  To: davem; +Cc: netdev, allan.stephens, ying.xue, Paul Gortmaker
In-Reply-To: <1325007582-31610-1-git-send-email-paul.gortmaker@windriver.com>

From: Allan Stephens <allan.stephens@windriver.com>

Streamlines the detection of an attempt to register a TIPC media structure
using an already registered name or type identifier. The revised logic now
reuses an existing routine to detect an existing name and no longer
unnecessarily manipulates the media type counter during an unsuccessful
registration attempt.

Signed-off-by: Allan Stephens <allan.stephens@windriver.com>
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
---
 net/tipc/bearer.c |   40 +++++++++++++++++++++-------------------
 1 files changed, 21 insertions(+), 19 deletions(-)

diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c
index 75af271..9ff8920 100644
--- a/net/tipc/bearer.c
+++ b/net/tipc/bearer.c
@@ -81,6 +81,21 @@ static struct media *media_find(const char *name)
 }
 
 /**
+ * media_find_id - locates specified media object by type identifier
+ */
+
+static struct 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];
+	}
+	return NULL;
+}
+
+/**
  * tipc_register_media - register a media type
  *
  * Bearers for this media type must be activated separately at a later stage.
@@ -88,8 +103,6 @@ static struct media *media_find(const char *name)
 
 int  tipc_register_media(struct media *m_ptr)
 {
-	u32 media_id;
-	u32 i;
 	int res = -EINVAL;
 
 	write_lock_bh(&tipc_net_lock);
@@ -121,29 +134,18 @@ int  tipc_register_media(struct media *m_ptr)
 		goto exit;
 	}
 
-	media_id = media_count++;
-	if (media_id >= MAX_MEDIA) {
+	if (media_count >= MAX_MEDIA) {
 		warn("Media <%s> rejected, media limit reached (%u)\n",
 		     m_ptr->name, MAX_MEDIA);
-		media_count--;
 		goto exit;
 	}
-	for (i = 0; i < media_id; i++) {
-		if (media_list[i].type_id == m_ptr->type_id) {
-			warn("Media <%s> rejected, duplicate type (%u)\n",
-			     m_ptr->name, m_ptr->type_id);
-			media_count--;
-			goto exit;
-		}
-		if (!strcmp(m_ptr->name, media_list[i].name)) {
-			warn("Media <%s> rejected, duplicate name\n",
-			     m_ptr->name);
-			media_count--;
-			goto exit;
-		}
+	if (media_find(m_ptr->name) || media_find_id(m_ptr->type_id)) {
+		warn("Media <%s> rejected, already registered\n", m_ptr->name);
+		goto exit;
 	}
 
-	media_list[media_id] = *m_ptr;
+	media_list[media_count] = *m_ptr;
+	media_count++;
 	res = 0;
 exit:
 	write_unlock_bh(&tipc_net_lock);
-- 
1.7.4.4

^ permalink raw reply related

* [PATCH net-next 02/23] tipc: Register new media using pre-compiled structure
From: Paul Gortmaker @ 2011-12-27 17:39 UTC (permalink / raw)
  To: davem; +Cc: netdev, allan.stephens, ying.xue, Paul Gortmaker
In-Reply-To: <1325007582-31610-1-git-send-email-paul.gortmaker@windriver.com>

From: Allan Stephens <allan.stephens@windriver.com>

Speeds up the registration of TIPC media types by passing in a structure
containing the required information, rather than by passing in the various
fields describing the media type individually.

Signed-off-by: Allan Stephens <allan.stephens@windriver.com>
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
---
 net/tipc/bearer.c    |   70 ++++++++++++++++++--------------------------------
 net/tipc/bearer.h    |   11 +-------
 net/tipc/eth_media.c |   30 +++++++++++++--------
 3 files changed, 45 insertions(+), 66 deletions(-)

diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c
index e2202de..75af271 100644
--- a/net/tipc/bearer.c
+++ b/net/tipc/bearer.c
@@ -86,21 +86,8 @@ static struct media *media_find(const char *name)
  * Bearers for this media type must be activated separately at a later stage.
  */
 
-int  tipc_register_media(u32 media_type,
-			 char *name,
-			 int (*enable)(struct tipc_bearer *),
-			 void (*disable)(struct tipc_bearer *),
-			 int (*send_msg)(struct sk_buff *,
-					 struct tipc_bearer *,
-					 struct tipc_media_addr *),
-			 char *(*addr2str)(struct tipc_media_addr *a,
-					   char *str_buf, int str_size),
-			 struct tipc_media_addr *bcast_addr,
-			 const u32 bearer_priority,
-			 const u32 link_tolerance,  /* [ms] */
-			 const u32 send_window_limit)
+int  tipc_register_media(struct media *m_ptr)
 {
-	struct media *m_ptr;
 	u32 media_id;
 	u32 i;
 	int res = -EINVAL;
@@ -108,62 +95,55 @@ int  tipc_register_media(u32 media_type,
 	write_lock_bh(&tipc_net_lock);
 
 	if (tipc_mode != TIPC_NET_MODE) {
-		warn("Media <%s> rejected, not in networked mode yet\n", name);
+		warn("Media <%s> rejected, not in networked mode yet\n",
+		     m_ptr->name);
 		goto exit;
 	}
-	if (!media_name_valid(name)) {
-		warn("Media <%s> rejected, illegal name\n", name);
+	if (!media_name_valid(m_ptr->name)) {
+		warn("Media <%s> rejected, illegal name\n", m_ptr->name);
 		goto exit;
 	}
-	if (!bcast_addr) {
-		warn("Media <%s> rejected, no broadcast address\n", name);
+	if (m_ptr->bcast_addr.type != htonl(m_ptr->type_id)) {
+		warn("Media <%s> rejected, illegal broadcast address\n",
+		     m_ptr->name);
 		goto exit;
 	}
-	if ((bearer_priority < TIPC_MIN_LINK_PRI) ||
-	    (bearer_priority > TIPC_MAX_LINK_PRI)) {
-		warn("Media <%s> rejected, illegal priority (%u)\n", name,
-		     bearer_priority);
+	if ((m_ptr->priority < TIPC_MIN_LINK_PRI) ||
+	    (m_ptr->priority > TIPC_MAX_LINK_PRI)) {
+		warn("Media <%s> rejected, illegal priority (%u)\n",
+		     m_ptr->name, m_ptr->priority);
 		goto exit;
 	}
-	if ((link_tolerance < TIPC_MIN_LINK_TOL) ||
-	    (link_tolerance > TIPC_MAX_LINK_TOL)) {
-		warn("Media <%s> rejected, illegal tolerance (%u)\n", name,
-		     link_tolerance);
+	if ((m_ptr->tolerance < TIPC_MIN_LINK_TOL) ||
+	    (m_ptr->tolerance > TIPC_MAX_LINK_TOL)) {
+		warn("Media <%s> rejected, illegal tolerance (%u)\n",
+		     m_ptr->name, m_ptr->tolerance);
 		goto exit;
 	}
 
 	media_id = media_count++;
 	if (media_id >= MAX_MEDIA) {
-		warn("Media <%s> rejected, media limit reached (%u)\n", name,
-		     MAX_MEDIA);
+		warn("Media <%s> rejected, media limit reached (%u)\n",
+		     m_ptr->name, MAX_MEDIA);
 		media_count--;
 		goto exit;
 	}
 	for (i = 0; i < media_id; i++) {
-		if (media_list[i].type_id == media_type) {
-			warn("Media <%s> rejected, duplicate type (%u)\n", name,
-			     media_type);
+		if (media_list[i].type_id == m_ptr->type_id) {
+			warn("Media <%s> rejected, duplicate type (%u)\n",
+			     m_ptr->name, m_ptr->type_id);
 			media_count--;
 			goto exit;
 		}
-		if (!strcmp(name, media_list[i].name)) {
-			warn("Media <%s> rejected, duplicate name\n", name);
+		if (!strcmp(m_ptr->name, media_list[i].name)) {
+			warn("Media <%s> rejected, duplicate name\n",
+			     m_ptr->name);
 			media_count--;
 			goto exit;
 		}
 	}
 
-	m_ptr = &media_list[media_id];
-	m_ptr->type_id = media_type;
-	m_ptr->send_msg = send_msg;
-	m_ptr->enable_bearer = enable;
-	m_ptr->disable_bearer = disable;
-	m_ptr->addr2str = addr2str;
-	memcpy(&m_ptr->bcast_addr, bcast_addr, sizeof(*bcast_addr));
-	strcpy(m_ptr->name, name);
-	m_ptr->priority = bearer_priority;
-	m_ptr->tolerance = link_tolerance;
-	m_ptr->window = send_window_limit;
+	media_list[media_id] = *m_ptr;
 	res = 0;
 exit:
 	write_unlock_bh(&tipc_net_lock);
diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h
index d696f9e..148ed04 100644
--- a/net/tipc/bearer.h
+++ b/net/tipc/bearer.h
@@ -145,16 +145,7 @@ extern struct tipc_bearer tipc_bearers[];
 /*
  * TIPC routines available to supported media types
  */
-int tipc_register_media(u32 media_type,
-		 char *media_name, int (*enable)(struct tipc_bearer *),
-		 void (*disable)(struct tipc_bearer *),
-		 int (*send_msg)(struct sk_buff *,
-			struct tipc_bearer *, struct tipc_media_addr *),
-		 char *(*addr2str)(struct tipc_media_addr *a,
-			char *str_buf, int str_size),
-		 struct tipc_media_addr *bcast_addr, const u32 bearer_priority,
-		 const u32 link_tolerance,  /* [ms] */
-		 const u32 send_window_limit);
+int tipc_register_media(struct media *m_ptr);
 
 void tipc_recv_msg(struct sk_buff *buf, struct tipc_bearer *tb_ptr);
 
diff --git a/net/tipc/eth_media.c b/net/tipc/eth_media.c
index e728d4c..15c685b 100644
--- a/net/tipc/eth_media.c
+++ b/net/tipc/eth_media.c
@@ -38,9 +38,6 @@
 #include "bearer.h"
 
 #define MAX_ETH_BEARERS		MAX_BEARERS
-#define ETH_LINK_PRIORITY	TIPC_DEF_LINK_PRI
-#define ETH_LINK_TOLERANCE	TIPC_DEF_LINK_TOL
-#define ETH_LINK_WINDOW		TIPC_DEF_LINK_WIN
 
 /**
  * struct eth_bearer - Ethernet bearer data structure
@@ -257,6 +254,24 @@ static char *eth_addr2str(struct tipc_media_addr *a, char *str_buf, int str_size
 	return str_buf;
 }
 
+/*
+ * Ethernet media registration info
+ */
+
+static struct media eth_media_info = {
+	.send_msg	= send_msg,
+	.enable_bearer	= enable_bearer,
+	.disable_bearer	= disable_bearer,
+	.addr2str	= eth_addr2str,
+	.bcast_addr	= { htonl(TIPC_MEDIA_TYPE_ETH),
+			    { {0xff, 0xff, 0xff, 0xff, 0xff, 0xff} } },
+	.priority	= TIPC_DEF_LINK_PRI,
+	.tolerance	= TIPC_DEF_LINK_TOL,
+	.window		= TIPC_DEF_LINK_WIN,
+	.type_id	= TIPC_MEDIA_TYPE_ETH,
+	.name		= "eth"
+};
+
 /**
  * tipc_eth_media_start - activate Ethernet bearer support
  *
@@ -266,21 +281,14 @@ static char *eth_addr2str(struct tipc_media_addr *a, char *str_buf, int str_size
 
 int tipc_eth_media_start(void)
 {
-	struct tipc_media_addr bcast_addr;
 	int res;
 
 	if (eth_started)
 		return -EINVAL;
 
-	bcast_addr.type = htonl(TIPC_MEDIA_TYPE_ETH);
-	memset(&bcast_addr.dev_addr, 0xff, ETH_ALEN);
-
 	memset(eth_bearers, 0, sizeof(eth_bearers));
 
-	res = tipc_register_media(TIPC_MEDIA_TYPE_ETH, "eth",
-				  enable_bearer, disable_bearer, send_msg,
-				  eth_addr2str, &bcast_addr, ETH_LINK_PRIORITY,
-				  ETH_LINK_TOLERANCE, ETH_LINK_WINDOW);
+	res = tipc_register_media(&eth_media_info);
 	if (res)
 		return res;
 
-- 
1.7.4.4

^ permalink raw reply related

* [PATCH net-next 01/23] tipc: Enable use by containers having their own network namespace
From: Paul Gortmaker @ 2011-12-27 17:39 UTC (permalink / raw)
  To: davem; +Cc: netdev, allan.stephens, ying.xue, Paul Gortmaker
In-Reply-To: <1325007582-31610-1-git-send-email-paul.gortmaker@windriver.com>

From: Allan Stephens <allan.stephens@windriver.com>

Permits a Linux container to use TIPC sockets even when it has its own
network namespace defined by removing the check that prohibits such use.
This makes it possible for users who wish to isolate their container
network traffic from normal network traffic to utilize TIPC.

Signed-off-by: Allan Stephens <allan.stephens@windriver.com>
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
---
 net/tipc/socket.c |    3 ---
 1 files changed, 0 insertions(+), 3 deletions(-)

diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index 42b8324..e2f7c5d 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -185,9 +185,6 @@ static int tipc_create(struct net *net, struct socket *sock, int protocol,
 
 	/* Validate arguments */
 
-	if (!net_eq(net, &init_net))
-		return -EAFNOSUPPORT;
-
 	if (unlikely(protocol != 0))
 		return -EPROTONOSUPPORT;
 
-- 
1.7.4.4

^ permalink raw reply related

* [PATCH net-next 00/23] TIPC: Updates for what will be v3.3
From: Paul Gortmaker @ 2011-12-27 17:39 UTC (permalink / raw)
  To: davem; +Cc: netdev, allan.stephens, ying.xue, Paul Gortmaker

Hi Dave, 

Here are some more updates for TIPC, based on the backlog of stuff
that was unfortunately stacked away in sourceforge a while ago.

Given the timing, please feel free to defer these to the for-3.4
net-next if there isn't a convenient opportunity to process it
before 3.2 is officially released.  I can easily resend later.

Fortunately, the SF backlog will finally be 100% gone with the
pending stuff that will be sent in the next year for the 3.4
net-next, so that will be nice to have that task closed out.

I just finished testing this over the wire between an x86-32 and
an x86-64 box, with both taking turns being server and client.

Thanks,
Paul.

---
The following changes since commit 1ba9ac7c35b30d6b958a30240e21ddaea8d21b35:

  bonding: document undocumented active_slave sysfs entry. (2011-12-26 20:09:35 -0500)

are available in the git repository at:
  git://git.kernel.org/pub/scm/linux/kernel/git/paulg/linux.git tipc-Dec27-2011

Allan Stephens (23):
  tipc: Enable use by containers having their own network namespace
  tipc: Register new media using pre-compiled structure
  tipc: Optimize detection of duplicate media registration
  tipc: Eliminate duplication of media structures
  tipc: Streamline media registration error checking
  tipc: Improve handling of media address printing errors
  tipc: Add new address conversion routines for Ethernet media
  tipc: Hide media-specific addressing details from generic bearer code
  tipc: Ignore neighbor discovery messages containing invalid address
  tipc: Allow run-time alteration of default link settings
  tipc: Revise comment justifying release of configuration spinlock
  tipc: Minor optimization to deactivation of Ethernet media suppot
  tipc: Do timely cleanup of disabled Ethernet bearer resources
  tipc: Eliminate useless memset operations in Ethernet media support
  tipc: Minor correction to TIPC module unloading
  tipc: Eliminate useless check when network address is assigned
  tipc: Eliminate dynamic allocation of broadcast link data structures
  tipc: Ensure broadcast link spinlock is held when updating node map
  tipc: Handle broadcast attempt when no neighboring nodes exist
  tipc: Minor optimization of broadcast link transmit queue statistic
  tipc: Flush unsent broadcast messages when contact with last node is lost
  tipc: Ignore broadcast acknowledgements that are out-of-range
  tipc: Allow use of buf_seqno() helper routine by unicast links

 net/tipc/bcast.c      |  125 +++++++++++++++++++------------
 net/tipc/bcast.h      |    6 +-
 net/tipc/bearer.c     |  158 ++++++++++++++-------------------------
 net/tipc/bearer.h     |   58 +++++++++------
 net/tipc/config.c     |   13 ++--
 net/tipc/core.c       |    2 +-
 net/tipc/discover.c   |    7 +-
 net/tipc/eth_media.c  |  159 ++++++++++++++++++++++++++++++----------
 net/tipc/link.c       |  195 ++++++++++++++++++++++++++++++++----------------
 net/tipc/link.h       |   11 +++
 net/tipc/msg.c        |    9 ++-
 net/tipc/msg.h        |   16 ++---
 net/tipc/name_distr.c |   12 +--
 net/tipc/net.c        |    7 +-
 net/tipc/node.c       |    7 +-
 net/tipc/socket.c     |    3 -
 16 files changed, 466 insertions(+), 322 deletions(-)

-- 
1.7.4.4

^ permalink raw reply

* Re: [PATCH v5] ARM: net: JIT compiler for packet filters
From: Rabin Vincent @ 2011-12-27 17:29 UTC (permalink / raw)
  To: Mircea Gherzan; +Cc: linux-arm-kernel, linux, eric.dumazet, netdev
In-Reply-To: <1324601625-20351-1-git-send-email-mgherzan@gmail.com>

On Fri, Dec 23, 2011 at 06:23, Mircea Gherzan <mgherzan@gmail.com> wrote:
> Based of Matt Evans's PPC64 implementation.
>
> The compiler generates ARM instructions but interworking is
> supported for Thumb2 kernels.
>
> Supports both little and big endian. Unaligned loads are emitted
> for ARMv6+. Not all the BPF opcodes that deal with ancillary data
> are supported. The scratch memory of the filter lives on the stack.
> Hardware integer division is used if it is available.
>
> Enabled in the same way as for x86-64 and PPC64:
>
>        echo 1 > /proc/sys/net/core/bpf_jit_enable
>
> A value greater than 1 enables opcode output.
>
> Signed-off-by: Mircea Gherzan <mgherzan@gmail.com>
> ---

I've had a somewhat incomplete version of this (supporting ARMV6+ only,
but Thumb-2 too) sitting around for a while since I wasn't happy with
the amount of testing I gave it.

Anyway, I was able to use the tests I did already have to find some bugs
in this patch.

The failures are from test code which generates packets to cover all
possible paths for some test filters and then compares the result (only
the final return value) against the interpreter.  I only ran it for
ARMv7 with no frame pointers.

> +/*
> + * Emit an instruction that will be executed unconditionally.
> + */
> +static inline void emit(u32 inst, struct jit_ctx *ctx)
> +{
> +       _emit(ARM_COND_AL, inst, ctx);
> +}
> +
> +static u16 saved_regs(struct jit_ctx *ctx)
> +{
> +       u16 ret = 0;
> +
> +       if (ctx->skf->len > 1)
> +               ret |= 1 << r_A;
> +

TEST 6 ==========================================
BPF_STMT(BPF_RET+BPF_A, 0),
Code: e3a04000 e1a00004 e12fff1e (0000000000)
(0) retinterp 0 retjit 0
+OK
qemu: uncaught target signal 11 (Segmentation fault) - core dumped

All code
========
   0:	e3a04000 	mov	r4, #0	<- clobber
   4:	e1a00004 	mov	r0, r4
   8:	e12fff1e 	bx	lr

> +#ifdef CONFIG_FRAME_POINTER
> +       ret |= (1 << ARM_FP) | (1 << ARM_IP) | (1 << ARM_LR) | (1 << ARM_PC);
> +#else
> +       if (ctx->seen & SEEN_CALL)
> +               ret |= 1 << ARM_LR;
> +#endif
> +       if (ctx->seen & (SEEN_DATA | SEEN_SKB))
> +               ret |= 1 << r_skb;
> +       if (ctx->seen & SEEN_DATA)
> +               ret |= (1 << r_skb_data) | (1 << r_skb_hl);
> +       if (ctx->seen & SEEN_X)
> +               ret |= 1 << r_X;
> +
> +       return ret;
> +}
> +
> +static inline int mem_words_used(struct jit_ctx *ctx)
> +{
> +       u32 words = ctx->seen & SEEN_MEM;
> +       /* yes, we do waste some stack space IF there are "holes" in the set" */
> +       return 32 - __builtin_clz(words);

You could use fls(words) here.

> +}
> +
> +static inline bool is_load_to_a(u16 inst)
> +{
> +       switch (inst) {
> +       case BPF_S_LD_W_LEN:
> +       case BPF_S_LD_W_ABS:
> +       case BPF_S_LD_H_ABS:
> +       case BPF_S_LD_B_ABS:
> +       case BPF_S_ANC_CPU:
> +       case BPF_S_ANC_IFINDEX:
> +       case BPF_S_ANC_MARK:
> +       case BPF_S_ANC_PROTOCOL:
> +       case BPF_S_ANC_RXHASH:
> +       case BPF_S_ANC_QUEUE:
> +               return true;
> +       default:
> +               return false;
> +       }
> +}
> +
> +static void build_prologue(struct jit_ctx *ctx)
> +{
> +       u16 reg_set = saved_regs(ctx);
> +       u16 first_inst = ctx->skf->insns[0].code;
> +       u16 off;
> +
> +#ifdef CONFIG_FRAME_POINTER
> +       emit(ARM_MOV_R(ARM_IP, ARM_SP), ctx);
> +       emit(ARM_PUSH(reg_set), ctx);
> +       emit(ARM_SUB_I(ARM_FP, ARM_IP, 4), ctx);
> +#else
> +       if (reg_set)
> +               emit(ARM_PUSH(reg_set), ctx);
> +#endif
> +
> +       if (ctx->seen & (SEEN_DATA | SEEN_SKB))
> +               emit(ARM_MOV_R(r_skb, ARM_R0), ctx);
> +
> +       if (ctx->seen & SEEN_DATA) {
> +               off = offsetof(struct sk_buff, data);
> +               emit(ARM_LDR_I(r_skb_data, r_skb, off), ctx);
> +               /* headlen = len - data_len */
> +               off = offsetof(struct sk_buff, len);
> +               emit(ARM_LDR_I(r_skb_hl, r_skb, off), ctx);
> +               off = offsetof(struct sk_buff, data_len);
> +               emit(ARM_LDR_I(r_scratch, r_skb, off), ctx);
> +               emit(ARM_SUB_R(r_skb_hl, r_skb_hl, r_scratch), ctx);
> +       }
> +
> +       if (ctx->seen & SEEN_X)
> +               emit(ARM_MOV_I(r_X, 0), ctx);
> +
> +       /* do not leak kernel data to userspace */
> +       if ((first_inst != BPF_S_RET_K) && !(is_load_to_a(first_inst)))
> +               emit(ARM_MOV_I(r_A, 0), ctx);
> +
> +       /* stack space for the BPF_MEM words */
> +       if (ctx->seen & SEEN_MEM)
> +               emit(ARM_SUB_I(ARM_SP, ARM_SP, mem_words_used(ctx) * 4), ctx);
> +}
> +
> +static void build_epilogue(struct jit_ctx *ctx)
> +{
> +       u16 reg_set = saved_regs(ctx);
> +
> +       if (ctx->seen & SEEN_MEM)
> +               emit(ARM_ADD_I(ARM_SP, ARM_SP, mem_words_used(ctx) * 4), ctx);
> +
> +       reg_set &= ~(1 << ARM_LR);
> +
> +#ifdef CONFIG_FRAME_POINTER
> +       /* the first instruction of the prologue was: mov ip, sp */
> +       reg_set &= ~(1 << ARM_IP);
> +       reg_set |= (1 << ARM_SP);
> +       emit(ARM_LDM(ARM_SP, reg_set), ctx);
> +#else
> +       if (ctx->seen) {
> +               if (ctx->seen & SEEN_CALL)
> +                       reg_set |= 1 << ARM_PC;
> +               emit(ARM_POP(reg_set), ctx);
> +       }

TEST 9 ==========================================
BPF_STMT(BPF_ALU+BPF_ADD+BPF_K, 1000),
BPF_STMT(BPF_RET+BPF_A, 0)
Code: e92d0010 e3a04000 e2844ffa e1a00004 e12fff1e (0000000000)
(0) retinterp 0x3e8 retjit 0x3e8
+OK
qemu: uncaught target signal 11 (Segmentation fault) - core dumped

All code
========
   0:	e92d0010 	push	{r4}
   4:	e3a04000 	mov	r4, #0
   8:	e2844ffa 	add	r4, r4, #1000	; 0x3e8
   c:	e1a00004 	mov	r0, r4
  10:	e12fff1e 	bx	lr		<-- no pop

I added a || ctx->skf->len > 1 condition (still not correct because
of the earlier failure) to the if above since I had several tests that
would hit this bug.

> +
> +       if (!(ctx->seen & SEEN_CALL))
> +               emit(ARM_BX(ARM_LR), ctx);
> +#endif
> +}
> +
...
> +               case BPF_S_LD_B_ABS:
> +                       load_order = 0;
> +load:
> +                       emit_mov_i(r_off, k, ctx);
> +load_common:
> +                       ctx->seen |= SEEN_DATA | SEEN_CALL;
> +
> +                       if (load_order > 0) {
> +                               emit(ARM_SUB_I(r_scratch, r_skb_hl,
> +                                              1 << load_order), ctx);
> +                               emit(ARM_CMP_R(r_scratch, r_off), ctx);
> +                               condt = ARM_COND_HS;
> +                       } else {
> +                               emit(ARM_CMP_R(r_skb_hl, r_off), ctx);
> +                               condt = ARM_COND_HI;
> +                       }
> +
> +                       _emit(condt, ARM_ADD_R(r_scratch, r_off, r_skb_data),
> +                             ctx);
> +
> +                       if (load_order == 0)
> +                               _emit(condt, ARM_LDRB_I(r_A, r_scratch, 0),
> +                                     ctx);
> +                       else if (load_order == 1)
> +                               emit_load_be16(condt, r_A, r_scratch, ctx);
> +                       else if (load_order == 2)
> +                               emit_load_be32(condt, r_A, r_scratch, ctx);
> +
> +                       _emit(condt, ARM_B(b_imm(i + 1, ctx)), ctx);
> +
> +                       /* the slowpath */
> +                       emit_mov_i(ARM_R3, (u32)load_func[load_order], ctx);
> +                       emit(ARM_MOV_R(ARM_R0, r_skb), ctx);
> +                       /* the offset is already in R1 */
> +                       emit_blx_r(ARM_R3, ctx);
> +                       emit(ARM_MOV_R(r_A, ARM_R0), ctx);

You're missing the "if (invalid data reference) return 0" behaviour.

> +                       break;
> +               case BPF_S_LD_W_IND:
> +                       load_order = 2;
> +                       goto load_ind;
> +               case BPF_S_LD_H_IND:
> +                       load_order = 1;
> +                       goto load_ind;
> +               case BPF_S_LD_B_IND:
> +                       load_order = 0;
> +load_ind:
> +                       OP_IMM3(ARM_ADD, r_off, r_X, k, ctx);
> +                       goto load_common;
> +               case BPF_S_LDX_IMM:
> +                       ctx->seen |= SEEN_X;
> +                       emit_mov_i(r_X, k, ctx);
> +                       break;
> +               case BPF_S_LDX_W_LEN:
> +                       ctx->seen |= SEEN_X | SEEN_SKB;
> +                       emit(ARM_LDR_I(r_X, r_skb,
> +                                      offsetof(struct sk_buff, len)), ctx);
> +                       break;
> +               case BPF_S_LDX_MEM:
> +                       ctx->seen |= SEEN_X | SEEN_MEM_WORD(k);
> +                       emit(ARM_LDR_I(r_X, ARM_SP, SCRATCH_OFF(k)), ctx);
> +                       break;
> +               case BPF_S_LDX_B_MSH:
> +                       /* x = ((*(frame + k)) & 0xf) << 2; */
> +                       ctx->seen |= SEEN_X | SEEN_DATA | SEEN_CALL;
> +                       /* offset in r1: we might have to take the slow path */
> +                       emit_mov_i(r_off, k, ctx);
> +                       emit(ARM_CMP_R(r_skb_hl, r_off), ctx);

You don't appear to be performing the "punt to interpreter" handling for
the negative K values.

> +
> +                       /* load in r0: common with the slowpath */
> +                       _emit(ARM_COND_HI, ARM_LDRB_R(ARM_R0, r_skb_data,
> +                                                     ARM_R1), ctx);
> +                       /*
> +                        * emit_mov_i() might generate one or two instructions,
> +                        * the same holds for emit_blx_r()
> +                        */
> +                       _emit(ARM_COND_HI, ARM_B(b_imm(i + 1, ctx) - 2), ctx);
> +
> +                       emit(ARM_MOV_R(ARM_R0, r_skb), ctx);
> +                       /* r_off is r1 */
> +                       emit_mov_i(ARM_R3, (u32)jit_get_skb_b, ctx);
> +                       emit_blx_r(ARM_R3, ctx);

"if (invalid address) return 0" behaviour needed here too.

> +
> +                       emit(ARM_ORR_I(r_X, ARM_R0, 0x00f), ctx);

This should be AND, not ORR.

TEST 67 ==========================================
(tcp[0:2] > 1500 and tcp[0:2] < 1550) or (tcp[2:2] > 1500 and tcp[2:2] < 1550)
(0) retinterp 0 retjit 0
+OK
(1) retinterp 0 retjit 0
+OK
(2) retinterp 0 retjit 0
+OK
(3) retinterp 0 retjit 0
+OK
(4) retinterp 0 retjit 0
+OK
(5) retinterp 0 retjit 0
+OK
(6) retinterp 0 retjit 0
+OK
(7) retinterp 0 retjit 0
+OK
(8) retinterp 0 retjit 0
+OK
(9) retinterp 0xffff retjit 0
-ERROR different rets

> +                       emit(ARM_LSL_I(r_X, r_X, 2), ctx);
> +                       break;
> +               case BPF_S_ST:
> +                       ctx->seen |= SEEN_MEM_WORD(k);
> +                       emit(ARM_STR_I(r_A, ARM_SP, SCRATCH_OFF(k)), ctx);
> +                       break;
> +               case BPF_S_STX:
> +                       ctx->seen |= SEEN_MEM_WORD(k) | SEEN_X;
> +                       emit(ARM_STR_I(r_X, ARM_SP, SCRATCH_OFF(k)), ctx);
> +                       break;
> +               case BPF_S_ALU_ADD_K:
> +                       /* A += K */
> +                       OP_IMM3(ARM_ADD, r_A, r_A, k, ctx);
> +                       break;
> +               case BPF_S_ALU_ADD_X:
> +                       ctx->seen |= SEEN_X;
> +                       emit(ARM_ADD_R(r_A, r_A, r_X), ctx);
> +                       break;
> +               case BPF_S_ALU_SUB_K:
> +                       /* A -= K */
> +                       OP_IMM3(ARM_SUB, r_A, r_A, k, ctx);
> +                       break;
> +               case BPF_S_ALU_SUB_X:
> +                       ctx->seen |= SEEN_X;
> +                       emit(ARM_SUB_R(r_A, r_A, r_X), ctx);
> +                       break;
> +               case BPF_S_ALU_MUL_K:
> +                       /* A *= K */
> +                       emit_mov_i(r_scratch, k, ctx);
> +                       emit(ARM_MUL(r_A, r_A, r_scratch), ctx);
> +                       break;
> +               case BPF_S_ALU_MUL_X:
> +                       ctx->seen |= SEEN_X;
> +                       emit(ARM_MUL(r_A, r_A, r_X), ctx);
> +                       break;
> +               case BPF_S_ALU_DIV_K:
> +                       /* current k == reciprocal_value(userspace k) */
> +                       emit_mov_i(r_scratch, k, ctx);
> +                       /* A = top 32 bits of the product */
> +                       emit(ARM_UMULL(r_scratch, r_A, r_A, r_scratch), ctx);
> +                       break;
> +               case BPF_S_ALU_DIV_X:
> +                       ctx->seen |= SEEN_X;
> +                       emit(ARM_CMP_I(r_X, 0), ctx);
> +                       emit_err_ret(ARM_COND_EQ, ctx);
> +                       emit_udiv(r_A, r_A, r_X, ctx);
> +                       break;
> +               case BPF_S_ALU_OR_K:
> +                       /* A |= K */
> +                       OP_IMM3(ARM_ORR, r_A, r_A, k, ctx);
> +                       break;
> +               case BPF_S_ALU_OR_X:
> +                       ctx->seen |= SEEN_X;
> +                       emit(ARM_ORR_I(r_A, r_A, r_X), ctx);

TEST 19 ==========================================
BPF_STMT(BPF_ALU+BPF_OR+BPF_X, 0),
BPF_STMT(BPF_RET+BPF_A, 0)
Code: e92d0030 e3a05000 e3a04000 e3844005 e1a00004 e8bd0030 e12fff1e
(0000000000)
(0) retinterp 0 retjit 0x5
-ERROR different rets

All code
========
   0:	e92d0030 	push	{r4, r5}
   4:	e3a05000 	mov	r5, #0
   8:	e3a04000 	mov	r4, #0
   c:	e3844005 	orr	r4, r4, #5	<-- should be register
  10:	e1a00004 	mov	r0, r4
  14:	e8bd0030 	pop	{r4, r5}
  18:	e12fff1e 	bx	lr

> +                       break;
> +               case BPF_S_ALU_AND_K:
> +                       /* A &= K */
> +                       OP_IMM3(ARM_AND, r_A, r_A, k, ctx);
> +                       break;
> +               case BPF_S_ALU_AND_X:
> +                       ctx->seen |= SEEN_X;
> +                       emit(ARM_AND_R(r_A, r_A, r_X), ctx);
> +                       break;
> +               case BPF_S_ALU_LSH_K:
> +                       if (unlikely(k > 31))
> +                               return -1;
> +                       emit(ARM_LSL_I(r_A, r_A, k), ctx);
> +                       break;

TEST 23 ==========================================
BPF_STMT(BPF_ALU+BPF_LSH+BPF_K, 5),
BPF_STMT(BPF_RET+BPF_A, 0)
Code: e92d0010 e3a04000 e1a04294 e1a00004 e8bd0010 e12fff1e (0000000000)
(0) retinterp 0 retjit 0x1
-ERROR different rets

All code
========
   0:	e92d0010 	push	{r4}
   4:	e3a04000 	mov	r4, #0
   8:	e1a04294 	lsl	r4, r4, r2	<-- should be immediate
   c:	e1a00004 	mov	r0, r4
  10:	e8bd0010 	pop	{r4}
  14:	e12fff1e 	bx	lr

> +               case BPF_S_ALU_LSH_X:
> +                       ctx->seen |= SEEN_X;
> +                       emit(ARM_LSL_R(r_A, r_A, r_X), ctx);
> +                       break;
> +               case BPF_S_ALU_RSH_K:
> +                       if (unlikely(k > 31))
> +                               return -1;
> +                       emit(ARM_LSR_I(r_A, r_A, k), ctx);
> +                       break;

TEST 91 ==========================================
(ip[24] >> 1) + ip[25] == 1
(0) retinterp 0 retjit 0
+OK
(1) retinterp 0 retjit 0
+OK
(2) retinterp 0xffff retjit 0
-ERROR different rets

All code
========
  ...
  78:	e1a040b4 	strh	r4, [r0, r4]!	<-- rsh #1
  ...

(register/imm mixup)

> +               case BPF_S_ALU_RSH_X:
> +                       ctx->seen |= SEEN_X;
> +                       emit(ARM_LSR_R(r_A, r_A, r_X), ctx);
> +                       break;

You're missing NEG, which should be straightforward to implement.

> +               case BPF_S_JMP_JA:
> +                       /* pc += K */
> +                       emit(ARM_B(b_imm(i + k, ctx)), ctx);
> +                       break;

TEST 39 ==========================================
BPF_STMT(BPF_JMP+BPF_JA, 0),
BPF_STMT(BPF_LD+BPF_IMM, 0x123)
BPF_STMT(BPF_RET+BPF_A, 0)
Code: e92d0010 e3a04000 fffffffe e3004123 e1a00004 e8bd0010 e12fff1e
(0000000000)
qemu: uncaught target signal 4 (Illegal instruction) - core dumped
Illegal instruction

All code
========
   0:	e92d0010 	push	{r4}
   4:	e3a04000 	mov	r4, #0
   8:	fffffffe 	undefined instruction 0xfffffffe
   c:	e3004123 	movw	r4, #291	; 0x123
  10:	e1a00004 	mov	r0, r4
  14:	e8bd0010 	pop	{r4}
  18:	e12fff1e 	bx	lr

(1) ARM_B doesn't mask off the relevant bits
(2) b_imm should be passed i + k + 1, not i + k

> +               case BPF_S_JMP_JEQ_K:
> +                       /* pc += (A == K) ? pc->jt : pc->jf */
> +                       condt   = ARM_COND_EQ;
> +                       condf  = ARM_COND_NE;

Since condf == condt ^ 1, you can just do that in cond_jump and remove
the explicit assignments to it.

> +                       goto cmp_imm;
> +               case BPF_S_JMP_JGT_K:
> +                       /* pc += (A > K) ? pc->jt : pc->jf */
> +                       condt   = ARM_COND_HI;
> +                       condf  = ARM_COND_LS;
> +                       goto cmp_imm;
> +               case BPF_S_JMP_JGE_K:
> +                       /* pc += (A >= K) ? pc->jt : pc->jf */
> +                       condt   = ARM_COND_HI;
> +                       condf  = ARM_COND_LS;
> +                       /* (x >= y) IFF (x > y - 1) */
> +                       if (unlikely(k == 0))
> +                               return -1;
> +                       k--;

Why don't you just use ARM_COND_HS here?

> +cmp_imm:
> +                       imm12 = imm8m(k);
> +                       if (imm12 < 0) {
> +                               emit_mov_i_no8m(r_scratch, k, ctx);
> +                               emit(ARM_CMP_R(r_A, r_scratch), ctx);
> +                       } else {
> +                               emit(ARM_CMP_I(r_A, imm12), ctx);
> +                       }
> +cond_jump:
> +                       if (inst->jt)
> +                               _emit(condt, ARM_B(b_imm(i + inst->jt + 1,
> +                                                  ctx)), ctx);
> +                       if (inst->jf)
> +                               _emit(condf, ARM_B(b_imm(i + inst->jf + 1,
> +                                                  ctx)), ctx);
> +                       break;
> +               case BPF_S_JMP_JEQ_X:
> +                       /* pc += (A == X) ? pc->jt : pc->jf */
> +                       condt   = ARM_COND_EQ;
> +                       condf  = ARM_COND_NE;
> +                       goto cmp_x;
> +               case BPF_S_JMP_JGT_X:
> +                       /* pc += (A > X) ? pc->jt : pc->jf */
> +                       condt   = ARM_COND_HI;
> +                       condf  = ARM_COND_LS;
> +                       goto cmp_x;
> +               case BPF_S_JMP_JGE_X:
> +                       /* pc += (A >= X) ? pc->jt : pc->jf */
> +                       condt   = ARM_COND_CS;
> +                       condf  = ARM_COND_CC;
> +cmp_x:
> +                       ctx->seen |= SEEN_X;
> +                       emit(ARM_CMP_R(r_A, r_X), ctx);
> +                       goto cond_jump;
> +               case BPF_S_JMP_JSET_K:
> +                       /* pc += (A & K) ? pc->jt : pc->jf */
> +                       condt  = ARM_COND_NE;
> +                       /* not set iff all zeroes iff Z==1 iff EQ */
> +                       condf  = ARM_COND_EQ;
> +
> +                       imm12 = imm8m(k);
> +                       if (imm12 < 0) {
> +                               emit_mov_i_no8m(r_scratch, k, ctx);
> +                               emit(ARM_TST_R(r_A, r_scratch), ctx);
> +                       } else {
> +                               emit(ARM_TST_I(r_A, imm12), ctx);
> +                       }
> +                       goto cond_jump;
> +               case BPF_S_JMP_JSET_X:
> +                       /* pc += (A & X) ? pc->jt : pc->jf */
> +                       condt  = ARM_COND_NE;
> +                       condf  = ARM_COND_EQ;
> +                       emit(ARM_TST_R(r_A, r_X), ctx);
> +                       goto cond_jump;
> +               case BPF_S_RET_A:
> +                       emit(ARM_MOV_R(ARM_R0, r_A), ctx);
> +                       goto b_epilogue;
> +               case BPF_S_RET_K:
> +                       if ((k == 0) && (ctx->ret0_fp_idx < 0))
> +                               ctx->ret0_fp_idx = i;
> +                       emit_mov_i(ARM_R0, k, ctx);
> +b_epilogue:
> +                       if (i != ctx->skf->len - 1)
> +                               emit(ARM_B(b_imm(prog->len, ctx)), ctx);
> +                       break;
> +               case BPF_S_MISC_TAX:
> +                       /* X = A */
> +                       emit(ARM_MOV_R(r_X, r_A), ctx);
> +                       break;

TEST 37 ==========================================
BPF_STMT(BPF_MISC+BPF_TAX, 0),
BPF_STMT(BPF_RET+BPF_A, 0)
Code: e92d0010 e3a04000 e1a05004 e1a00004 e8bd0010 e12fff1e (0000000000)
(0) retinterp 0 retjit 0
+OK
qemu: uncaught target signal 11 (Segmentation fault) - core dumped

All code
========
   0:	e92d0010 	push	{r4}
   4:	e3a04000 	mov	r4, #0
   8:	e1a05004 	mov	r5, r4	<- clobber
   c:	e1a00004 	mov	r0, r4
  10:	e8bd0010 	pop	{r4}
  14:	e12fff1e 	bx	lr

> +               case BPF_S_MISC_TXA:
> +                       /* A = X */
> +                       emit(ARM_MOV_R(r_A, r_X), ctx);
> +                       break;

TEST 38 ==========================================
BPF_STMT(BPF_MISC+BPF_TXA, 0),
BPF_STMT(BPF_RET+BPF_A, 0)
Code: e92d0010 e3a04000 e1a04005 e1a00004 e8bd0010 e12fff1e (0000000000)
(0) retinterp 0 retjit 0
+OK
(1) retinterp 0 retjit 0x1
-ERROR different rets

All code
========
   0:	e92d0010 	push	{r4}
   4:	e3a04000 	mov	r4, #0
   8:	e1a04005 	mov	r4, r5	<- uninitialized
   c:	e1a00004 	mov	r0, r4
  10:	e8bd0010 	pop	{r4}
  14:	e12fff1e 	bx	lr

...
> +void bpf_jit_compile(struct sk_filter *fp)
> +{
> +       struct jit_ctx ctx;
> +       unsigned tmp_idx;
> +       unsigned alloc_size;
> +
> +       if (!bpf_jit_enable)
> +               return;
> +
> +       memset(&ctx, 0, sizeof(ctx));
> +       ctx.skf         = fp;
> +       ctx.ret0_fp_idx = -1;
> +
> +       ctx.offsets = kzalloc(GFP_KERNEL, 4 * (ctx.skf->len + 1));
> +       if (ctx.offsets == NULL)
> +               return;
> +
> +       /* fake pass to fill in the ctx->seen */
> +       if (unlikely(build_body(&ctx)))
> +               goto out;
> +
> +       tmp_idx = ctx.idx;
> +       build_prologue(&ctx);
> +       ctx.prologue_bytes = (ctx.idx - tmp_idx) * 4;
> +
> +#if __LINUX_ARM_ARCH__ < 7
> +       tmp_idx = ctx.idx;
> +       build_epilogue(&ctx);
> +       ctx.epilogue_bytes = (ctx.idx - tmp_idx) * 4;
> +
> +       ctx.idx += ctx.imm_count;
> +       if (ctx.imm_count) {
> +               ctx.imms = kzalloc(GFP_KERNEL, 4 * ctx.imm_count);
> +               if (ctx.imms == NULL)
> +                       goto out;
> +       }
> +#else
> +       /* there's nothing after the epilogue on ARMv7 */
> +       build_epilogue(&ctx);
> +#endif
> +
> +       alloc_size = 4 * ctx.idx;
> +       ctx.target = module_alloc(alloc_size > sizeof(struct work_struct) ?
> +                                 alloc_size : sizeof(struct work_struct));

max()

^ permalink raw reply

* Re: [PATCH net-next V2 0/2] igb: ptp hardware clock
From: Jeff Kirsher @ 2011-12-27 17:28 UTC (permalink / raw)
  To: Richard Cochran
  Cc: netdev, e1000-devel, Jacob Keller, John Ronciak, John Stultz,
	Thomas Gleixner
In-Reply-To: <cover.1324901880.git.richardcochran@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 1850 bytes --]

On Mon, 2011-12-26 at 13:26 +0100, Richard Cochran wrote:
> * ChangeLog V2
>    - Fixed wrong bit shifting in the 82576 code.
>    - Explained the timestamp locking with a comment in the code.
>    - Preserved the comments from the original timecompare implementation.
>    - Added an additional test within the overflow counter code to fix
>      a race condition. Details of the problem are given in the commit
>      message.
> 
> This patch series implements a PHC driver for the Intel 82576 and
> 82580 devices, as part of the igb driver.
> 
> The first patch adds the PHC driver code as a new source module but
> does not link it into the main igb driver. Because the system time
> counter is not so very wide, the code implements an overflow counter
> in software. Every read operation maintains the overflow counter, as
> does a "delayed work" watchdog. Only the base clock operations are
> implemented. The hardware does have some ancillary features, but these
> can be easily added later.
> 
> The second patch removes the timecompare code and links in the new
> functions.
> 
> I have tested the 82580 with good results. However, I don't have the
> 82576 and so would appreciate testing and feedback.
> 
> Thanks,
> Richard
> 
> 
> Richard Cochran (2):
>   igb: add PTP Hardware Clock code
>   igb: offer a PTP Hardware Clock instead of the timecompare method
> 
>  drivers/net/ethernet/intel/igb/Makefile   |    2 +-
>  drivers/net/ethernet/intel/igb/igb.h      |   21 +-
>  drivers/net/ethernet/intel/igb/igb_main.c |  167 +----------
>  drivers/net/ethernet/intel/igb/igb_ptp.c  |  486 +++++++++++++++++++++++++++++
>  4 files changed, 505 insertions(+), 171 deletions(-)
>  create mode 100644 drivers/net/ethernet/intel/igb/igb_ptp.c
> 

Thanks Richard, I have added this series to my queue.

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply

* [PATCH] net: fec: Adjust ENET MDIO timeouts
From: Fabio Estevam @ 2011-12-27 14:46 UTC (permalink / raw)
  To: netdev; +Cc: davem, shawn.guo, kernel, Rogerio Pimentel, Fabio Estevam

On extensive NFS boots on a mx6qsabrelite board it was noted that "FEC: MDIO read timeout" were occuring,
which caused failure on loading the FEC driver.

The original FEC_MII_TIMEOUT was set to 1 ms, which is too low when passed to the usecs_to_jiffies macro.

On ARM one jiffy is 10ms, so use msecs_to_jiffies instead and use a timeout of 30ms, which corresponds to 3 jiffies.

After running extensive NFS boots, the MDIO timeouts do not occur anymore with this change.

Signed-off-by: Rogerio Pimentel <rogerio.pimentel@freescale.com>
Signed-off-by: Fabio Estevam <fabio.estevam@freescale.com>
---
 drivers/net/ethernet/freescale/fec.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec.c b/drivers/net/ethernet/freescale/fec.c
index c136230..170a015 100644
--- a/drivers/net/ethernet/freescale/fec.c
+++ b/drivers/net/ethernet/freescale/fec.c
@@ -255,7 +255,7 @@ struct fec_enet_private {
 #define FEC_MMFR_TA		(2 << 16)
 #define FEC_MMFR_DATA(v)	(v & 0xffff)
 
-#define FEC_MII_TIMEOUT		1000 /* us */
+#define FEC_MII_TIMEOUT		30 /* ms */
 
 /* Transmitter timeout */
 #define TX_TIMEOUT (2 * HZ)
@@ -902,7 +902,7 @@ static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
 
 	/* wait for end of transfer */
 	time_left = wait_for_completion_timeout(&fep->mdio_done,
-			usecs_to_jiffies(FEC_MII_TIMEOUT));
+			msecs_to_jiffies(FEC_MII_TIMEOUT));
 	if (time_left == 0) {
 		fep->mii_timeout = 1;
 		printk(KERN_ERR "FEC: MDIO read timeout\n");
@@ -930,7 +930,7 @@ static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
 
 	/* wait for end of transfer */
 	time_left = wait_for_completion_timeout(&fep->mdio_done,
-			usecs_to_jiffies(FEC_MII_TIMEOUT));
+			msecs_to_jiffies(FEC_MII_TIMEOUT));
 	if (time_left == 0) {
 		fep->mii_timeout = 1;
 		printk(KERN_ERR "FEC: MDIO write timeout\n");
-- 
1.7.1

^ permalink raw reply related

* bonding device in balance-alb mode shows packet loss in kernel 3.2-rc6
From: Narendra_K @ 2011-12-27 14:31 UTC (permalink / raw)
  To: netdev; +Cc: fubar

[-- Attachment #1: Type: text/plain, Size: 4775 bytes --]

Hello,

On kernel version 3.2-rc6, when a bonding device is configured in 'balance-alb' mode,
ping reported packet losses. By looking at protocol trance, it seemed like the lost
packets had the destination MAC id of inactive slave. 

Scenario:

Host under test:

bond0 IP addr: 10.2.2.1 - balance-alb mode, 2 or more slaves.

Remote Host1: 10.2.2.11

Remote Host2: 10.2.2.2

Ping to Host 1 IP. Observe that there is no packet loss

# ping 10.2.2.11
PING 10.2.2.11 (10.2.2.11) 56(84) bytes of data.
64 bytes from 10.2.2.11: icmp_seq=1 ttl=64 time=0.156 ms
64 bytes from 10.2.2.11: icmp_seq=2 ttl=64 time=0.130 ms
64 bytes from 10.2.2.11: icmp_seq=3 ttl=64 time=0.151 ms
64 bytes from 10.2.2.11: icmp_seq=4 ttl=64 time=0.137 ms
64 bytes from 10.2.2.11: icmp_seq=5 ttl=64 time=0.151 ms
64 bytes from 10.2.2.11: icmp_seq=6 ttl=64 time=0.129 ms
^C
--- 10.2.2.11 ping statistics ---
6 packets transmitted, 6 received, 0% packet loss, time 4997ms
rtt min/avg/max/mdev = 0.129/0.142/0.156/0.014 ms

Now ping to Host2 IP. Observe that there is packet loss. It is reproducible almost
always.

# ping 10.2.2.2
PING 10.2.2.2 (10.2.2.2) 56(84) bytes of data.
64 bytes from 10.2.2.2: icmp_seq=6 ttl=64 time=0.108 ms
64 bytes from 10.2.2.2: icmp_seq=7 ttl=64 time=0.104 ms
64 bytes from 10.2.2.2: icmp_seq=8 ttl=64 time=0.119 ms
64 bytes from 10.2.2.2: icmp_seq=56 ttl=64 time=0.139 ms
64 bytes from 10.2.2.2: icmp_seq=57 ttl=64 time=0.111 ms
^C
--- 10.2.2.2 ping statistics ---
75 packets transmitted, 5 received, 93% packet loss, time 74037ms
rtt min/avg/max/mdev = 0.104/0.116/0.139/0.014 ms

More information:

Hardware information: 
Dell PowerEdge R610

# lspci | grep -i ether
01:00.0 Ethernet controller: Broadcom Corporation NetXtreme II BCM5709 Gigabit Ethernet (rev 20)
01:00.1 Ethernet controller: Broadcom Corporation NetXtreme II BCM5709 Gigabit Ethernet (rev 20)
02:00.0 Ethernet controller: Broadcom Corporation NetXtreme II BCM5709 Gigabit Ethernet (rev 20)
02:00.1 Ethernet controller: Broadcom Corporation NetXtreme II BCM5709 Gigabit Ethernet (rev 20)

Kernel version:
3.2.0-rc6

# ethtool -i bond0
driver: bonding
version: 3.7.1

By observing the packets on remote HOST2, the sequence is

1. 'bond0' broadcasts an ARP request with source MAC equal to
'bond0' MAC address and receives a ARP response to the same.
Next few packets are received.

2. After some, there are 2 ARP replies from 'bond0' to HOST2
with source MAC equal to 'inactive slave' MAC id. Now HOST2 sends
ICMP response with destnation MAC equal to inactive slave MAC id
and these packets are dropped.

The wireshark protocol trace is attached to this note.

3. The behavior was independent of the Network adapters models.

4. Also, I had few prints in 'eth_type_trans' and it seemed like the 'inactive slave'
was not receiving any frames destined to it (00:21:9b:9d:a5:74) except ARP broadcasts.
Setting the 'inactive slave' in 'promisc' mode made bond0 see the responses.

# cat /proc/net/bonding/bond0
Ethernet Channel Bonding Driver: v3.7.1 (April 27, 2011)

Bonding Mode: adaptive load balancing
Primary Slave: None
Currently Active Slave: em2
MII Status: up
MII Polling Interval (ms): 100
Up Delay (ms): 0
Down Delay (ms): 0

Slave Interface: em2
MII Status: up
Speed: 1000 Mbps
Duplex: full
Link Failure Count: 0
Permanent HW addr: 00:21:9b:9d:a5:72
Slave queue ID: 0

Slave Interface: em3
MII Status: up
Speed: 1000 Mbps
Duplex: full
Link Failure Count: 0
Permanent HW addr: 00:21:9b:9d:a5:74 <--- 1
Slave queue ID: 0

Slave Interface: em4
MII Status: up
Speed: 1000 Mbps
Duplex: full
Link Failure Count: 0
Permanent HW addr: 00:21:9b:9d:a5:76
Slave queue ID: 0


# ip addr show dev bond0
8: bond0: <BROADCAST,MULTICAST,MASTER,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
    link/ether 00:21:9b:9d:a5:72 brd ff:ff:ff:ff:ff:ff
    inet 10.2.2.1/24 brd 10.2.2.255 scope global bond0
    inet6 fe80::221:9bff:fe9d:a572/64 scope link
       valid_lft forever preferred_lft forever

# ip addr show dev em2
3: em2: <BROADCAST,MULTICAST,SLAVE,UP,LOWER_UP> mtu 1500 qdisc mq master bond0 state UP qlen 1000
    link/ether 00:21:9b:9d:a5:72 brd ff:ff:ff:ff:ff:ff

# ip addr show dev em3
4: em3: <BROADCAST,MULTICAST,SLAVE,UP,LOWER_UP> mtu 1500 qdisc mq master bond0 state UP qlen 1000
    link/ether 00:21:9b:9d:a5:74 brd ff:ff:ff:ff:ff:ff

# ip addr show dev em4
5: em4: <BROADCAST,MULTICAST,SLAVE,UP,LOWER_UP> mtu 1500 qdisc mq master bond0 state UP qlen 1000
    link/ether 00:21:9b:9d:a5:76 brd ff:ff:ff:ff:ff:ff

It would be great if you have any insight into this. Please let me know if any additional information is required.

With regards,
Narendra K



[-- Attachment #2: linux-3.2-rc6-balance-alb-protocol-trace --]
[-- Type: application/octet-stream, Size: 14230 bytes --]

^ permalink raw reply

* Re: [PATCH -next] net: calxeda xgmac ethernet driver add missing HAS_IOMEM dependency
From: Rob Herring @ 2011-12-27 14:16 UTC (permalink / raw)
  To: Heiko Carstens; +Cc: David S. Miller, netdev, linux-kernel
In-Reply-To: <1324994825-4197-1-git-send-email-heiko.carstens@de.ibm.com>

On 12/27/2011 08:07 AM, Heiko Carstens wrote:
> Fix allyesconfig build on architectures without IOMEM:
> 
> drivers/net/ethernet/calxeda/xgmac.c:1800:2:
>   error: implicit declaration of function 'iounmap' [-Werror=implicit-function-declaration]
> 
> Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
> Cc: Rob Herring <rob.herring@calxeda.com>

Thanks.

Acked-by: Rob Herring <rob.herring@calxeda.com>

> ---
>  drivers/net/ethernet/calxeda/Kconfig |    2 +-
>  1 files changed, 1 insertions(+), 1 deletions(-)
> 
> diff --git a/drivers/net/ethernet/calxeda/Kconfig b/drivers/net/ethernet/calxeda/Kconfig
> index a52e725..aba435c 100644
> --- a/drivers/net/ethernet/calxeda/Kconfig
> +++ b/drivers/net/ethernet/calxeda/Kconfig
> @@ -1,6 +1,6 @@
>  config NET_CALXEDA_XGMAC
>  	tristate "Calxeda 1G/10G XGMAC Ethernet driver"
> -
> +	depends on HAS_IOMEM
>  	select CRC32
>  	help
>  	  This is the driver for the XGMAC Ethernet IP block found on Calxeda

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox