Use more compact LIST instead of TAILQ for session hash.
Add all listening hooks into LIST to simplify searches. Use ng_findhook() instead of own equal implementation.
This commit is contained in:
parent
67196661ab
commit
dda30f129e
@ -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;
|
||||
@ -415,21 +416,11 @@ make_packet(sessp sp) {
|
||||
static hook_p
|
||||
pppoe_match_svc(node_p node, const struct pppoe_tag *tag)
|
||||
{
|
||||
hook_p hook;
|
||||
const priv_p privp = NG_NODE_PRIVATE(node);
|
||||
sessp sp;
|
||||
|
||||
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;
|
||||
|
||||
neg = sp->neg;
|
||||
LIST_FOREACH(sp, &privp->listeners, sessions) {
|
||||
negp neg = sp->neg;
|
||||
|
||||
/* Empty Service-Name matches any service. */
|
||||
if (neg->service_len == 0)
|
||||
@ -447,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);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -461,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);
|
||||
}
|
||||
@ -495,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;
|
||||
const priv_p privp = NG_NODE_PRIVATE(node);
|
||||
sessp sp;
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
@ -541,13 +513,13 @@ pppoe_getnewsession(sessp sp)
|
||||
/* Check it isn't already in use. */
|
||||
hash = SESSHASH(val);
|
||||
mtx_lock(&privp->sesshash[hash].mtx);
|
||||
TAILQ_FOREACH(tsp, &privp->sesshash[hash].head, sessions) {
|
||||
LIST_FOREACH(tsp, &privp->sesshash[hash].head, sessions) {
|
||||
if (tsp->Session_ID == val)
|
||||
break;
|
||||
}
|
||||
if (!tsp) {
|
||||
sp->Session_ID = val;
|
||||
TAILQ_INSERT_HEAD(&privp->sesshash[hash].head, sp, sessions);
|
||||
LIST_INSERT_HEAD(&privp->sesshash[hash].head, sp, sessions);
|
||||
}
|
||||
mtx_unlock(&privp->sesshash[hash].mtx);
|
||||
if (tsp)
|
||||
@ -566,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);
|
||||
}
|
||||
|
||||
@ -578,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);
|
||||
}
|
||||
|
||||
@ -591,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) {
|
||||
@ -651,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)",
|
||||
@ -789,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);
|
||||
|
||||
@ -922,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:
|
||||
/*
|
||||
@ -1810,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,
|
||||
|
Loading…
Reference in New Issue
Block a user