summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Motin <mav@FreeBSD.org>2008-03-07 17:58:49 +0000
committerAlexander Motin <mav@FreeBSD.org>2008-03-07 17:58:49 +0000
commit04264dfa1258d1a5e10ef7e9e583ffb4fac6df70 (patch)
tree6f7368473b7ec3c22dd6c728b85a6412c22ce0e2
parent888e99520373b404132d1b07dfa876f636982ad5 (diff)
Notes
-rw-r--r--sys/netgraph/ng_pppoe.c167
1 files changed, 67 insertions, 100 deletions
diff --git a/sys/netgraph/ng_pppoe.c b/sys/netgraph/ng_pppoe.c
index 5d23cfb9125a..cc8a46000ee2 100644
--- a/sys/netgraph/ng_pppoe.c
+++ b/sys/netgraph/ng_pppoe.c
@@ -235,7 +235,7 @@ struct sess_con {
ng_ID_t creator; /* who to notify */
struct pppoe_full_hdr pkt_hdr; /* used when connected */
negp neg; /* used when negotiating */
- TAILQ_ENTRY(sess_con) sessions;
+ LIST_ENTRY(sess_con) sessions;
};
typedef struct sess_con *sessp;
@@ -244,7 +244,7 @@ typedef struct sess_con *sessp;
struct sess_hash_entry {
struct mtx mtx;
- TAILQ_HEAD(hhead, sess_con) head;
+ LIST_HEAD(hhead, sess_con) head;
};
/*
@@ -260,6 +260,7 @@ struct PPPoE {
#define COMPAT_3COM 0x00000001
#define COMPAT_DLINK 0x00000002
struct ether_header eh;
+ LIST_HEAD(, sess_con) listeners;
struct sess_hash_entry sesshash[SESSHASHSIZE];
};
typedef struct PPPoE *priv_p;
@@ -281,43 +282,6 @@ static int pppoe_send_event(sessp sp, enum cmd cmdid);
* Author: Michal Ostrowski <mostrows@styx.uwaterloo.ca> *
************************************************************************/
-/*
- * Generate a new session id
- * XXX find out the FreeBSD locking scheme.
- */
-static uint16_t
-get_new_sid(node_p node)
-{
- static int pppoe_sid = 10;
- hook_p hook;
- uint16_t val;
-
-restart:
- val = pppoe_sid++;
- /*
- * Spec says 0xFFFF is reserved.
- * Also don't use 0x0000
- */
- if (val == 0xffff) {
- pppoe_sid = 20;
- goto restart;
- }
-
- /* Check it isn't already in use. */
- LIST_FOREACH(hook, &node->nd_hooks, hk_hooks) {
- sessp sp = NG_HOOK_PRIVATE(hook);
-
- /* Skip any nonsession hook. */
- if (sp == NULL)
- continue;
- if (sp->Session_ID == val)
- goto restart;
- }
-
- CTR2(KTR_NET, "%20s: new sid %d", __func__, val);
-
- return (val);
-}
/*
@@ -452,21 +416,11 @@ make_packet(sessp sp) {
static hook_p
pppoe_match_svc(node_p node, const struct pppoe_tag *tag)
{
- hook_p hook;
-
- LIST_FOREACH(hook, &node->nd_hooks, hk_hooks) {
- sessp sp = NG_HOOK_PRIVATE(hook);
- negp neg;
-
- /* Skip any nonsession hook. */
- if (sp == NULL)
- continue;
-
- /* Skip any sessions which are not in LISTEN mode. */
- if (sp->state != PPPOE_LISTENING)
- continue;
+ const priv_p privp = NG_NODE_PRIVATE(node);
+ sessp sp;
- neg = sp->neg;
+ LIST_FOREACH(sp, &privp->listeners, sessions) {
+ negp neg = sp->neg;
/* Empty Service-Name matches any service. */
if (neg->service_len == 0)
@@ -484,9 +438,10 @@ pppoe_match_svc(node_p node, const struct pppoe_tag *tag)
ntohs(tag->tag_len)) == 0)
break;
}
- CTR3(KTR_NET, "%20s: matched %p for %s", __func__, hook, tag->tag_data);
+ CTR3(KTR_NET, "%20s: matched %p for %s", __func__,
+ sp?sp->hook:NULL, tag->tag_data);
- return (hook);
+ return (sp?sp->hook:NULL);
}
/*
@@ -498,27 +453,17 @@ pppoe_match_svc(node_p node, const struct pppoe_tag *tag)
static int
pppoe_broadcast_padi(node_p node, struct mbuf *m0)
{
- hook_p hook;
+ const priv_p privp = NG_NODE_PRIVATE(node);
+ sessp sp;
int error = 0;
- LIST_FOREACH(hook, &node->nd_hooks, hk_hooks) {
- sessp sp = NG_HOOK_PRIVATE(hook);
+ LIST_FOREACH(sp, &privp->listeners, sessions) {
struct mbuf *m;
- /*
- * Go through all listening hooks and
- * broadcast the PADI packet up there
- */
- if (sp == NULL)
- continue;
-
- if (sp->state != PPPOE_LISTENING)
- continue;
-
m = m_dup(m0, M_DONTWAIT);
if (m == NULL)
return (ENOMEM);
- NG_SEND_DATA_ONLY(error, hook, m);
+ NG_SEND_DATA_ONLY(error, sp->hook, m);
if (error)
return (error);
}
@@ -532,25 +477,15 @@ pppoe_broadcast_padi(node_p node, struct mbuf *m0)
static hook_p
pppoe_find_svc(node_p node, const char *svc_name, int svc_len)
{
- hook_p hook;
-
- LIST_FOREACH(hook, &node->nd_hooks, hk_hooks) {
- sessp sp = NG_HOOK_PRIVATE(hook);
- negp neg;
-
- /* Skip any nonsession hook. */
- if (sp == NULL)
- continue;
-
- /* Skip any sessions which are not in LISTEN mode. */
- if (sp->state != PPPOE_LISTENING)
- continue;
+ const priv_p privp = NG_NODE_PRIVATE(node);
+ sessp sp;
- neg = sp->neg;
+ LIST_FOREACH(sp, &privp->listeners, sessions) {
+ negp neg = sp->neg;
if (neg->service_len == svc_len &&
strncmp(svc_name, neg->service.data, svc_len) == 0)
- return (hook);
+ return (sp->hook);
}
return (NULL);
@@ -559,6 +494,42 @@ pppoe_find_svc(node_p node, const char *svc_name, int svc_len)
/**************************************************************************
* Routines to find a particular session that matches an incoming packet. *
**************************************************************************/
+/* Find free session and add to hash. */
+static uint16_t
+pppoe_getnewsession(sessp sp)
+{
+ const priv_p privp = NG_NODE_PRIVATE(NG_HOOK_NODE(sp->hook));
+ static uint16_t pppoe_sid = 1;
+ sessp tsp;
+ uint16_t val, hash;
+
+restart:
+ /* Atomicity is not needed here as value will be checked. */
+ val = pppoe_sid++;
+ /* Spec says 0xFFFF is reserved, also don't use 0x0000. */
+ if (val == 0xffff || val == 0x0000)
+ val = pppoe_sid = 1;
+
+ /* Check it isn't already in use. */
+ hash = SESSHASH(val);
+ mtx_lock(&privp->sesshash[hash].mtx);
+ LIST_FOREACH(tsp, &privp->sesshash[hash].head, sessions) {
+ if (tsp->Session_ID == val)
+ break;
+ }
+ if (!tsp) {
+ sp->Session_ID = val;
+ LIST_INSERT_HEAD(&privp->sesshash[hash].head, sp, sessions);
+ }
+ mtx_unlock(&privp->sesshash[hash].mtx);
+ if (tsp)
+ goto restart;
+
+ CTR2(KTR_NET, "%20s: new sid %d", __func__, val);
+
+ return (val);
+}
+
/* Add specified session to hash. */
static void
pppoe_addsession(sessp sp)
@@ -567,7 +538,7 @@ pppoe_addsession(sessp sp)
uint16_t hash = SESSHASH(sp->Session_ID);
mtx_lock(&privp->sesshash[hash].mtx);
- TAILQ_INSERT_HEAD(&privp->sesshash[hash].head, sp, sessions);
+ LIST_INSERT_HEAD(&privp->sesshash[hash].head, sp, sessions);
mtx_unlock(&privp->sesshash[hash].mtx);
}
@@ -579,7 +550,7 @@ pppoe_delsession(sessp sp)
uint16_t hash = SESSHASH(sp->Session_ID);
mtx_lock(&privp->sesshash[hash].mtx);
- TAILQ_REMOVE(&privp->sesshash[hash].head, sp, sessions);
+ LIST_REMOVE(sp, sessions);
mtx_unlock(&privp->sesshash[hash].mtx);
}
@@ -592,7 +563,7 @@ pppoe_findsession(priv_p privp, const struct pppoe_full_hdr *wh)
sessp sp = NULL;
mtx_lock(&privp->sesshash[hash].mtx);
- TAILQ_FOREACH(sp, &privp->sesshash[hash].head, sessions) {
+ LIST_FOREACH(sp, &privp->sesshash[hash].head, sessions) {
if (sp->Session_ID == session &&
bcmp(sp->pkt_hdr.eh.ether_dhost,
wh->eh.ether_shost, ETHER_ADDR_LEN) == 0) {
@@ -652,9 +623,10 @@ ng_pppoe_constructor(node_p node)
memset(&privp->eh.ether_dhost, 0xff, ETHER_ADDR_LEN);
privp->eh.ether_type = ETHERTYPE_PPPOE_DISC;
+ LIST_INIT(&privp->listeners);
for (i = 0; i < SESSHASHSIZE; i++) {
mtx_init(&privp->sesshash[i].mtx, "PPPoE hash mutex", NULL, MTX_DEF);
- TAILQ_INIT(&privp->sesshash[i].head);
+ LIST_INIT(&privp->sesshash[i].head);
}
CTR3(KTR_NET, "%20s: created node [%x] (%p)",
@@ -790,18 +762,12 @@ ng_pppoe_rcvmsg(node_p node, item_p item, hook_p lasthook)
/* Make sure strcmp will terminate safely. */
ourmsg->hook[sizeof(ourmsg->hook) - 1] = '\0';
- /* Cycle through all known hooks. */
- LIST_FOREACH(hook, &node->nd_hooks, hk_hooks) {
- if (NG_HOOK_NAME(hook) &&
- strcmp(NG_HOOK_NAME(hook), ourmsg->hook) ==
- 0)
- break;
- }
+ /* Find hook by name. */
+ hook = ng_findhook(node, ourmsg->hook);
if (hook == NULL)
LEAVE(ENOENT);
sp = NG_HOOK_PRIVATE(hook);
-
if (sp == NULL)
LEAVE(EINVAL);
@@ -923,6 +889,7 @@ ng_pppoe_rcvmsg(node_p node, item_p item, hook_p lasthook)
* Wait for PADI packet coming from Ethernet.
*/
sp->state = PPPOE_LISTENING;
+ LIST_INSERT_HEAD(&privp->listeners, sp, sessions);
break;
case NGM_PPPOE_OFFER:
/*
@@ -1545,9 +1512,7 @@ ng_pppoe_rcvdata_ether(hook_p hook, item_p item)
neg->pkt->pkt_header.ph.code = PADS_CODE;
if (sp->Session_ID == 0) {
neg->pkt->pkt_header.ph.sid =
- htons(sp->Session_ID
- = get_new_sid(node));
- pppoe_addsession(sp);
+ htons(pppoe_getnewsession(sp));
}
send_sessionid(sp);
neg->timeout = 0;
@@ -1813,7 +1778,9 @@ ng_pppoe_disconnect(hook_p hook)
privp->ethernet_hook, m);
}
}
- if (sp->Session_ID)
+ if (sp->state == PPPOE_LISTENING)
+ LIST_REMOVE(sp, sessions);
+ else if (sp->Session_ID)
pppoe_delsession(sp);
/*
* As long as we have somewhere to store the timeout handle,