PERFORCE change 118648 for review

Kip Macy kmacy at FreeBSD.org
Mon Apr 23 08:41:22 UTC 2007


http://perforce.freebsd.org/chv.cgi?CH=118648

Change 118648 by kmacy at kmacy_vt-x:opentoe_init on 2007/04/23 08:40:40

	bring l2t closer to being a working implementation by replacing "neighbour" with rtentry
	
	re-declare llinfo_arp outside of if_ether.c for the moment until accessor functions can be added
	disable VLAN support until the vlan tag for a route can be queried
	don't support custom resolution failure routines

Affected files ...

.. //depot/projects/opentoe/sys/dev/cxgb/cxgb_l2t.c#4 edit
.. //depot/projects/opentoe/sys/dev/cxgb/cxgb_l2t.h#4 edit

Differences ...

==== //depot/projects/opentoe/sys/dev/cxgb/cxgb_l2t.c#4 (text+ko) ====

@@ -44,6 +44,15 @@
 #include <sys/rwlock.h>
 
 
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <net/if.h>
+#include <net/ethernet.h>
+#include <net/if_vlan_var.h>
+#include <net/if_dl.h>
+#include <net/route.h>
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
 
 
 #include <dev/cxgb/common/cxgb_common.h>
@@ -54,12 +63,19 @@
 #include <dev/cxgb/common/jhash.h>
 #include <dev/cxgb/cxgb_offload.h>
 
-#include <net/if_vlan_var.h>
+#define VLAN_NONE 0xfff
+#define SDL(s) ((struct sockaddr_dl *)s) 
+#define RT_ENADDR(rt)  ((char *)LLADDR(SDL((rt))))
+#define rt_expire rt_rmx.rmx_expire 
 
-#define neigh_release(...)
+struct llinfo_arp { 
+        struct  callout la_timer; 
+        struct  rtentry *la_rt; 
+        struct  mbuf *la_hold;  /* last packet until resolved/timeout */ 
+        u_short la_preempt;     /* countdown for pre-expiry arps */ 
+        u_short la_asked;       /* # requests sent */ 
+}; 
 
-#define VLAN_NONE 0xfff
-
 /*
  * Module locking notes:  There is a RW lock protecting the L2 table as a
  * whole plus a spinlock per L2T entry.  Entry lookups and allocations happen
@@ -87,16 +103,20 @@
 }
 
 static inline void
-neigh_replace(struct l2t_entry *e, struct ifnet *n)
+neigh_replace(struct l2t_entry *e, struct rtentry *rt)
 {
-#if 0
-	neigh_hold(n);
-	if (e->neigh)
-		neigh_release(e->neigh);
-	e->neigh = n;
-#endif	
+	RT_LOCK(rt);
+	RT_ADDREF(rt);
+	RT_UNLOCK(rt);
+	
+	if (e->neigh) {
+		RT_LOCK(e->neigh);
+		RT_REMREF(e->neigh);
+		RT_UNLOCK(e->neigh);
+	}
+	e->neigh = rt;
 }
-#if 0
+
 /*
  * Set up an L2T entry and send any packets waiting in the arp queue.  The
  * supplied mbuf is used for the CPL_L2T_WRITE_REQ.  Must be called with the
@@ -121,9 +141,8 @@
 	req->params = htonl(V_L2T_W_IDX(e->idx) | V_L2T_W_IFF(e->smt_idx) |
 			    V_L2T_W_VLAN(e->vlan & EVL_VLID_MASK) |
 			    V_L2T_W_PRIO(vlan_prio(e)));
-#if 0	
-	memcpy(e->dmac, e->neigh->ha, sizeof(e->dmac));
-#endif	
+
+	memcpy(e->dmac, RT_ENADDR(e->neigh), sizeof(e->dmac));
 	memcpy(req->dst_mac, e->dmac, sizeof(req->dst_mac));
 	m->m_priority = CPL_PRIORITY_CONTROL;
 	cxgb_ofld_send(dev, m);
@@ -138,7 +157,7 @@
 
 	return 0;
 }
-#endif
+
 /*
  * Add a packet to the an L2T entry's queue of packets awaiting resolution.
  * Must be called with the entry's lock held.
@@ -158,12 +177,18 @@
 t3_l2t_send_slow(struct toedev *dev, struct mbuf *m,
 		     struct l2t_entry *e)
 {
+	struct rtentry *rt;
+	struct mbuf *m0;
+	
+	if ((m0 = m_gethdr(M_NOWAIT, MT_DATA)) == NULL)
+		return (ENOMEM);
+
+	rt = e->neigh;
+	
 again:
 	switch (e->state) {
 	case L2T_STATE_STALE:     /* entry is stale, kick off revalidation */
-#if 0		
-		neigh_event_send(e->neigh, NULL);
-#endif		
+		arpresolve(rt->rt_ifp, rt, m0, rt->rt_gateway, RT_ENADDR(rt));
 		mtx_lock(&e->lock);
 		if (e->state == L2T_STATE_STALE)
 			e->state = L2T_STATE_VALID;
@@ -179,6 +204,8 @@
 		arpq_enqueue(e, m);
 		mtx_unlock(&e->lock);
 
+		if ((m0 = m_gethdr(M_NOWAIT, MT_DATA)) == NULL)
+			return (ENOMEM);
 		/*
 		 * Only the first packet added to the arpq should kick off
 		 * resolution.  However, because the m_gethdr below can fail,
@@ -187,19 +214,15 @@
 		 * A better way would be to use a work request to retry L2T
 		 * entries when there's no memory.
 		 */
-#if 0		
-		if (!neigh_event_send(e->neigh, NULL)) {
-			if ((m = m_gethdr(M_NOWAIT, MT_DATA)) == NULL)
-				break;
+		if (arpresolve(rt->rt_ifp, rt, m0, rt->rt_gateway, RT_ENADDR(rt)) == 0) {
 
 			mtx_lock(&e->lock);
-			if (e->arpq_head)
+			if (e->arpq_head) 
 				setup_l2e_send_pending(dev, m, e);
-			else                           /* we lost the race */
-				m_free(m);
+			else
+				m_freem(m);
 			mtx_unlock(&e->lock);
 		}
-#endif		
 	}
 	return 0;
 }
@@ -207,12 +230,17 @@
 void
 t3_l2t_send_event(struct toedev *dev, struct l2t_entry *e)
 {
+	struct rtentry *rt;
+	struct mbuf *m0;
+	
+	if ((m0 = m_gethdr(M_NOWAIT, MT_DATA)) == NULL)
+		return;
+
+	rt = e->neigh;
 again:
 	switch (e->state) {
 	case L2T_STATE_STALE:     /* entry is stale, kick off revalidation */
-#if 0		
-		neigh_event_send(e->neigh, NULL);
-#endif		
+		arpresolve(rt->rt_ifp, rt, m0, rt->rt_gateway, RT_ENADDR(rt));
 		mtx_lock(&e->lock);
 		if (e->state == L2T_STATE_STALE) {
 			e->state = L2T_STATE_VALID;
@@ -228,7 +256,9 @@
 			goto again;
 		}
 		mtx_unlock(&e->lock);
-
+		
+		if ((m0 = m_gethdr(M_NOWAIT, MT_DATA)) == NULL)
+			return;
 		/*
 		 * Only the first packet added to the arpq should kick off
 		 * resolution.  However, because the alloc_skb below can fail,
@@ -237,13 +267,11 @@
 		 * A better way would be to use a work request to retry L2T
 		 * entries when there's no memory.
 		 */
-#if 0		
-		neigh_event_send(e->neigh, NULL);
-#endif		
+		arpresolve(rt->rt_ifp, rt, m0, rt->rt_gateway, RT_ENADDR(rt));
+
 	}
 	return;
 }
-#if 0
 /*
  * Allocate a free L2T entry.  Must be called with l2t_data.lock held.
  */
@@ -281,7 +309,7 @@
 	}
 	return e;
 }
-#endif
+
 /*
  * Called when an L2T entry has no more users.  The entry is left in the hash
  * table since it is likely to be reused but we also bump nfree to indicate
@@ -299,7 +327,9 @@
 	mtx_lock(&e->lock);
 	if (atomic_load_acq_int(&e->refcnt) == 0) {  /* hasn't been recycled */
 		if (e->neigh) {
-			neigh_release(e->neigh);
+			RT_LOCK(e->neigh);
+			RT_REMREF(e->neigh);
+			RT_UNLOCK(e->neigh);
 			e->neigh = NULL;
 		}
 	}
@@ -312,36 +342,34 @@
  * Must be called with softirqs disabled.
  */
 static inline void
-reuse_entry(struct l2t_entry *e, struct ifnet *neigh)
+reuse_entry(struct l2t_entry *e, struct rtentry *neigh)
 {
-#ifdef notyet	
-	unsigned int nud_state;
+	struct llinfo_arp *la;
+
+	la = (struct llinfo_arp *)neigh->rt_llinfo; 
 
 	mtx_lock(&e->lock);                /* avoid race with t3_l2t_free */
-
 	if (neigh != e->neigh)
 		neigh_replace(e, neigh);
-	nud_state = neigh->nud_state;
-	if (memcmp(e->dmac, neigh->ha, sizeof(e->dmac)) ||
-	    !(nud_state & NUD_VALID))
+	
+	if (memcmp(e->dmac, RT_ENADDR(neigh), sizeof(e->dmac)) ||
+	    (neigh->rt_expire > time_uptime))
 		e->state = L2T_STATE_RESOLVING;
-	else if (nud_state & NUD_CONNECTED)
+	else if (la->la_hold == NULL)
 		e->state = L2T_STATE_VALID;
 	else
 		e->state = L2T_STATE_STALE;
 	mtx_unlock(&e->lock);
-#endif	
 }
 
 struct l2t_entry *
-t3_l2t_get(struct toedev *dev, struct ifnet *neigh,
+t3_l2t_get(struct toedev *dev, struct rtentry *neigh,
 			     unsigned int smt_idx)
 {
-#if 0	
 	struct l2t_entry *e;
 	struct l2t_data *d = L2DATA(dev);
-	u32 addr = *(u32 *) neigh->primary_key;
-	int ifidx = neigh->if_index;
+	u32 addr = *(u32 *) rt_key(neigh);
+	int ifidx = neigh->rt_ifp->if_index;
 	int hash = arp_hash(addr, ifidx, d);
 
 	rw_wlock(&d->lock);
@@ -366,17 +394,20 @@
 		e->smt_idx = smt_idx;
 		atomic_store_rel_int(&e->refcnt, 1);
 		neigh_replace(e, neigh);
-		if (neigh->dev->priv_flags & IFF_802_1Q_VLAN)
+#ifdef notyet
+		/* 
+		 * XXX need to add accessor function for vlan tag
+		 */
+		if (neigh->rt_ifp->if_vlantrunk)
 			e->vlan = VLAN_DEV_INFO(neigh->dev)->vlan_id;
 		else
+#endif			    
 			e->vlan = VLAN_NONE;
 		mtx_unlock(&e->lock);
 	}
 done:
 	rw_wunlock(&d->lock);
 	return e;
-#endif
-	return (NULL);
 }
 
 /*
@@ -387,41 +418,43 @@
  * XXX: maybe we should abandon the latter behavior and just require a failure
  * handler.
  */
-#if 0
 static void
 handle_failed_resolution(struct toedev *dev, struct mbuf *arpq)
 {
 
 	while (arpq) {
 		struct mbuf *m = arpq;
+#ifdef notyet		
 		struct l2t_mbuf_cb *cb = L2T_MBUF_CB(m);
-
+#endif
 		arpq = m->m_next;
 		m->m_next = NULL;
+#ifdef notyet		
 		if (cb->arp_failure_handler)
 			cb->arp_failure_handler(dev, m);
 		else
+#endif			
 			cxgb_ofld_send(dev, m);
 	}
 
 }
-#endif
+
 #if defined(NETEVENT) || !defined(CONFIG_CHELSIO_T3_MODULE)
 /*
  * Called when the host's ARP layer makes a change to some entry that is
  * loaded into the HW L2 table.
  */
 void
-t3_l2t_update(struct toedev *dev, struct ifnet *neigh)
+t3_l2t_update(struct toedev *dev, struct rtentry *neigh)
 {
-#if 0	
 	struct l2t_entry *e;
 	struct mbuf *arpq = NULL;
 	struct l2t_data *d = L2DATA(dev);
-	u32 addr = *(u32 *) neigh->primary_key;
-	int ifidx = neigh->dev->ifindex;
+	u32 addr = *(u32 *) rt_key(neigh);
+	int ifidx = neigh->rt_ifp->if_index;
 	int hash = arp_hash(addr, ifidx, d);
-
+	struct llinfo_arp *la;
+	
 	rw_rlock(&d->lock);
 	for (e = d->l2tab[hash].first; e; e = e->next)
 		if (e->addr == addr && e->ifindex == ifidx) {
@@ -436,17 +469,19 @@
 	if (atomic_load_acq_int(&e->refcnt)) {
 		if (neigh != e->neigh)
 			neigh_replace(e, neigh);
-
+		
+		la = (struct llinfo_arp *)neigh->rt_llinfo; 
 		if (e->state == L2T_STATE_RESOLVING) {
-			if (neigh->nud_state & NUD_FAILED) {
+			
+			if (la->la_asked >= 5 /* arp_maxtries */) {
 				arpq = e->arpq_head;
 				e->arpq_head = e->arpq_tail = NULL;
-			} else if (neigh_is_connected(neigh))
+			} else if (la->la_hold == NULL)
 				setup_l2e_send_pending(dev, NULL, e);
 		} else {
-			e->state = neigh_is_connected(neigh) ?
+			e->state = (la->la_hold == NULL) ?
 				L2T_STATE_VALID : L2T_STATE_STALE;
-			if (memcmp(e->dmac, neigh->ha, 6))
+			if (memcmp(e->dmac, RT_ENADDR(neigh), 6))
 				setup_l2e_send_pending(dev, NULL, e);
 		}
 	}
@@ -454,18 +489,17 @@
 
 	if (arpq)
 		handle_failed_resolution(dev, arpq);
-#endif
 }
 #else
 /*
  * Called from a kprobe, interrupts are off.
  */
 void
-t3_l2t_update(struct toedev *dev, struct ifnet *neigh)
+t3_l2t_update(struct toedev *dev, struct rtentry *neigh)
 {
 	struct l2t_entry *e;
 	struct l2t_data *d = L2DATA(dev);
-	u32 addr = *(u32 *) neigh->primary_key;
+	u32 addr = *(u32 *) rt_key(neigh);
 	int ifidx = neigh->dev->ifindex;
 	int hash = arp_hash(addr, ifidx, d);
 
@@ -490,7 +524,7 @@
 {
 	struct mbuf *arpq = NULL;
 	struct l2t_entry *e = (struct l2t_entry *)data;
-	struct ifnet *neigh = e->neigh;
+	struct rtentry *neigh = e->neigh;
 	struct toedev *dev = e->tdev;
 
 	barrier();
@@ -510,7 +544,7 @@
 		} else {
 			e->state = neigh_is_connected(neigh) ?
 				L2T_STATE_VALID : L2T_STATE_STALE;
-			if (memcmp(e->dmac, neigh->ha, sizeof(e->dmac)))
+			if (memcmp(e->dmac, RT_ENADDR(neigh), sizeof(e->dmac)))
 				setup_l2e_send_pending(dev, NULL, e);
 		}
 	}

==== //depot/projects/opentoe/sys/dev/cxgb/cxgb_l2t.h#4 (text+ko) ====

@@ -20,20 +20,20 @@
  * first element in its chain through its first pointer.
  */
 struct l2t_entry {
-	uint16_t state;                  /* entry state */
-	uint16_t idx;                    /* entry index */
-	uint32_t addr;                   /* dest IP address */
-	int ifindex;                /* neighbor's net_device's ifindex */
-	uint16_t smt_idx;                /* SMT index */
-	uint16_t vlan;                   /* VLAN TCI (id: bits 0-11, prio: 13-15 */
-	struct ifnet *neigh;    /* associated neighbour */
-	struct l2t_entry *first;    /* start of hash chain */
-	struct l2t_entry *next;     /* next l2t_entry on chain */
-	struct mbuf *arpq_head;  /* queue of packets awaiting resolution */
+	uint16_t state;               /* entry state */
+	uint16_t idx;                 /* entry index */
+	uint32_t addr;                /* dest IP address */
+	int ifindex;                  /* neighbor's net_device's ifindex */
+	uint16_t smt_idx;             /* SMT index */
+	uint16_t vlan;                /* VLAN TCI (id: bits 0-11, prio: 13-15 */
+	struct rtentry *neigh;        /* associated neighbour */
+	struct l2t_entry *first;      /* start of hash chain */
+	struct l2t_entry *next;       /* next l2t_entry on chain */
+	struct mbuf *arpq_head;       /* queue of packets awaiting resolution */
 	struct mbuf *arpq_tail;
 	struct mtx lock;
-	volatile uint32_t refcnt;            /* entry reference count */
-	uint8_t dmac[6];                 /* neighbour's MAC address */
+	volatile uint32_t refcnt;     /* entry reference count */
+	uint8_t dmac[6];              /* neighbour's MAC address */
 #ifndef NETEVENT
 #ifdef CONFIG_CHELSIO_T3_MODULE
 	struct timer_list update_timer;
@@ -45,7 +45,7 @@
 struct l2t_data {
 	unsigned int nentries;      /* number of entries */
 	struct l2t_entry *rover;    /* starting point for next allocation */
-	volatile uint32_t nfree;             /* number of free entries */
+	volatile uint32_t nfree;    /* number of free entries */
 	struct rwlock lock;
 	struct l2t_entry l2tab[0];
 };
@@ -65,21 +65,24 @@
  */
 #define L2T_MBUF_CB(skb) ((struct l2t_mbuf_cb *)(skb)->cb)
 
-#ifdef notyet
-static inline void set_arp_failure_handler(struct mbuf *m,
+
+static __inline void set_arp_failure_handler(struct mbuf *m,
 					   arp_failure_handler_func hnd)
 {
+#if 0
 	L2T_SKB_CB(skb)->arp_failure_handler = hnd;
+#endif
+	panic("implement me");
 }
-#endif
+
 /*
  * Getting to the L2 data from an offload device.
  */
 #define L2DATA(dev) ((dev)->l2opt)
 
 void t3_l2e_free(struct l2t_data *d, struct l2t_entry *e);
-void t3_l2t_update(struct toedev *dev, struct ifnet *ifp);
-struct l2t_entry *t3_l2t_get(struct toedev *dev, struct ifnet *neigh,
+void t3_l2t_update(struct toedev *dev, struct rtentry *ifp);
+struct l2t_entry *t3_l2t_get(struct toedev *dev, struct rtentry *neigh,
 			     unsigned int smt_idx);
 int t3_l2t_send_slow(struct toedev *dev, struct mbuf *m,
 		     struct l2t_entry *e);


More information about the p4-projects mailing list