MFC ng_ppp.c rev. 1.68, 1.69.
Add proper fine-grained node locking. Add 64bit statistic counters.
This commit is contained in:
parent
d0e06d1dd8
commit
90496dfcb1
@ -395,6 +395,10 @@ containing statistics for the corresponding link.
|
||||
Here
|
||||
.Dv NG_PPP_BUNDLE_LINKNUM
|
||||
is a valid link number corresponding to the multi-link bundle.
|
||||
.It Dv NGM_PPP_GET_LINK_STATS64
|
||||
Same as NGM_PPP_GET_LINK_STATS but returns
|
||||
.Dv "struct ng_ppp_link_stat64"
|
||||
containing 64bit counters.
|
||||
.It Dv NGM_PPP_CLR_LINK_STATS
|
||||
This command takes a two byte link number as an argument and
|
||||
clears the statistics for that link.
|
||||
@ -402,6 +406,10 @@ clears the statistics for that link.
|
||||
Same as
|
||||
.Dv NGM_PPP_GET_LINK_STATS ,
|
||||
but also atomically clears the statistics as well.
|
||||
.It Dv NGM_PPP_GETCLR_LINK_STATS64
|
||||
Same as NGM_PPP_GETCLR_LINK_STATS but returns
|
||||
.Dv "struct ng_ppp_link_stat64"
|
||||
containing 64bit counters.
|
||||
.El
|
||||
.Pp
|
||||
This node type also accepts the control messages accepted by the
|
||||
|
@ -196,7 +196,7 @@ struct ng_ppp_frag {
|
||||
/* Per-link private information */
|
||||
struct ng_ppp_link {
|
||||
struct ng_ppp_link_conf conf; /* link configuration */
|
||||
struct ng_ppp_link_stat stats; /* link stats */
|
||||
struct ng_ppp_link_stat64 stats; /* link stats */
|
||||
hook_p hook; /* connection to link data */
|
||||
int32_t seq; /* highest rec'd seq# - MSEQ */
|
||||
uint32_t latency; /* calculated link latency */
|
||||
@ -207,7 +207,7 @@ struct ng_ppp_link {
|
||||
/* Total per-node private information */
|
||||
struct ng_ppp_private {
|
||||
struct ng_ppp_bund_conf conf; /* bundle config */
|
||||
struct ng_ppp_link_stat bundleStats; /* bundle stats */
|
||||
struct ng_ppp_link_stat64 bundleStats; /* bundle stats */
|
||||
struct ng_ppp_link links[NG_PPP_MAX_LINKS];/* per-link info */
|
||||
int32_t xseq; /* next out MP seq # */
|
||||
int32_t mseq; /* min links[i].seq */
|
||||
@ -221,6 +221,8 @@ struct ng_ppp_private {
|
||||
frags;
|
||||
int qlen; /* fraq queue length */
|
||||
struct callout fragTimer; /* fraq queue check */
|
||||
struct mtx rmtx; /* recv mutex */
|
||||
struct mtx xmtx; /* xmit mutex */
|
||||
};
|
||||
typedef struct ng_ppp_private *priv_p;
|
||||
|
||||
@ -299,7 +301,7 @@ static int ng_ppp_mp_xmit(node_p node, item_p item, uint16_t proto);
|
||||
static int ng_ppp_mp_recv(node_p node, item_p item, uint16_t proto,
|
||||
uint16_t linkNum);
|
||||
static int ng_ppp_link_xmit(node_p node, item_p item, uint16_t proto,
|
||||
uint16_t linkNum);
|
||||
uint16_t linkNum, int plen);
|
||||
|
||||
static int ng_ppp_bypass(node_p node, item_p item, uint16_t proto,
|
||||
uint16_t linkNum);
|
||||
@ -381,6 +383,14 @@ static const struct ng_parse_type ng_ppp_stats_type = {
|
||||
&ng_ppp_stats_type_fields
|
||||
};
|
||||
|
||||
/* Parse type for struct ng_ppp_link_stat64 */
|
||||
static const struct ng_parse_struct_field ng_ppp_stats64_type_fields[]
|
||||
= NG_PPP_STATS64_TYPE_INFO;
|
||||
static const struct ng_parse_type ng_ppp_stats64_type = {
|
||||
&ng_parse_struct_type,
|
||||
&ng_ppp_stats64_type_fields
|
||||
};
|
||||
|
||||
/* List of commands and how to convert arguments to/from ASCII */
|
||||
static const struct ng_cmdlist ng_ppp_cmds[] = {
|
||||
{
|
||||
@ -425,6 +435,20 @@ static const struct ng_cmdlist ng_ppp_cmds[] = {
|
||||
&ng_parse_int16_type,
|
||||
&ng_ppp_stats_type
|
||||
},
|
||||
{
|
||||
NGM_PPP_COOKIE,
|
||||
NGM_PPP_GET_LINK_STATS64,
|
||||
"getstats64",
|
||||
&ng_parse_int16_type,
|
||||
&ng_ppp_stats64_type
|
||||
},
|
||||
{
|
||||
NGM_PPP_COOKIE,
|
||||
NGM_PPP_GETCLR_LINK_STATS64,
|
||||
"getclrstats64",
|
||||
&ng_parse_int16_type,
|
||||
&ng_ppp_stats64_type
|
||||
},
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
@ -476,6 +500,9 @@ ng_ppp_constructor(node_p node)
|
||||
priv->links[i].seq = MP_NOSEQ;
|
||||
ng_callout_init(&priv->fragTimer);
|
||||
|
||||
mtx_init(&priv->rmtx, "ng_ppp_recv", NULL, MTX_DEF);
|
||||
mtx_init(&priv->xmtx, "ng_ppp_xmit", NULL, MTX_DEF);
|
||||
|
||||
/* Done */
|
||||
return (0);
|
||||
}
|
||||
@ -515,9 +542,6 @@ ng_ppp_newhook(node_p node, hook_p hook, const char *name)
|
||||
!priv->conf.enableMultilink && priv->numActiveLinks >= 1)
|
||||
return (ENODEV);
|
||||
|
||||
/* MP recv code is not thread-safe. */
|
||||
NG_HOOK_FORCE_WRITER(hook);
|
||||
|
||||
} else { /* must be a non-link hook */
|
||||
int i;
|
||||
|
||||
@ -615,10 +639,13 @@ ng_ppp_rcvmsg(node_p node, item_p item, hook_p lasthook)
|
||||
case NGM_PPP_GET_LINK_STATS:
|
||||
case NGM_PPP_CLR_LINK_STATS:
|
||||
case NGM_PPP_GETCLR_LINK_STATS:
|
||||
case NGM_PPP_GET_LINK_STATS64:
|
||||
case NGM_PPP_GETCLR_LINK_STATS64:
|
||||
{
|
||||
struct ng_ppp_link_stat *stats;
|
||||
struct ng_ppp_link_stat64 *stats;
|
||||
uint16_t linkNum;
|
||||
|
||||
/* Process request. */
|
||||
if (msg->header.arglen != sizeof(uint16_t))
|
||||
ERROUT(EINVAL);
|
||||
linkNum = *((uint16_t *) msg->data);
|
||||
@ -627,14 +654,38 @@ ng_ppp_rcvmsg(node_p node, item_p item, hook_p lasthook)
|
||||
ERROUT(EINVAL);
|
||||
stats = (linkNum == NG_PPP_BUNDLE_LINKNUM) ?
|
||||
&priv->bundleStats : &priv->links[linkNum].stats;
|
||||
if (msg->header.cmd != NGM_PPP_CLR_LINK_STATS) {
|
||||
|
||||
/* Make 64bit reply. */
|
||||
if (msg->header.cmd == NGM_PPP_GET_LINK_STATS64 ||
|
||||
msg->header.cmd == NGM_PPP_GETCLR_LINK_STATS64) {
|
||||
NG_MKRESPONSE(resp, msg,
|
||||
sizeof(struct ng_ppp_link_stat64), M_NOWAIT);
|
||||
if (resp == NULL)
|
||||
ERROUT(ENOMEM);
|
||||
bcopy(stats, resp->data, sizeof(*stats));
|
||||
} else
|
||||
/* Make 32bit reply. */
|
||||
if (msg->header.cmd == NGM_PPP_GET_LINK_STATS ||
|
||||
msg->header.cmd == NGM_PPP_GETCLR_LINK_STATS) {
|
||||
struct ng_ppp_link_stat *rs;
|
||||
NG_MKRESPONSE(resp, msg,
|
||||
sizeof(struct ng_ppp_link_stat), M_NOWAIT);
|
||||
if (resp == NULL)
|
||||
ERROUT(ENOMEM);
|
||||
bcopy(stats, resp->data, sizeof(*stats));
|
||||
rs = (struct ng_ppp_link_stat *)resp->data;
|
||||
/* Truncate 64->32 bits. */
|
||||
rs->xmitFrames = stats->xmitFrames;
|
||||
rs->xmitOctets = stats->xmitOctets;
|
||||
rs->recvFrames = stats->recvFrames;
|
||||
rs->recvOctets = stats->recvOctets;
|
||||
rs->badProtos = stats->badProtos;
|
||||
rs->runts = stats->runts;
|
||||
rs->dupFragments = stats->dupFragments;
|
||||
rs->dropFragments = stats->dropFragments;
|
||||
}
|
||||
if (msg->header.cmd != NGM_PPP_GET_LINK_STATS)
|
||||
/* Clear stats. */
|
||||
if (msg->header.cmd != NGM_PPP_GET_LINK_STATS &&
|
||||
msg->header.cmd != NGM_PPP_GET_LINK_STATS64)
|
||||
bzero(stats, sizeof(*stats));
|
||||
break;
|
||||
}
|
||||
@ -684,6 +735,8 @@ ng_ppp_shutdown(node_p node)
|
||||
|
||||
/* Take down netgraph node */
|
||||
ng_ppp_frag_reset(node);
|
||||
mtx_destroy(&priv->rmtx);
|
||||
mtx_destroy(&priv->xmtx);
|
||||
bzero(priv, sizeof(*priv));
|
||||
FREE(priv, M_NETGRAPH_PPP);
|
||||
NG_NODE_SET_PRIVATE(node, NULL);
|
||||
@ -812,7 +865,7 @@ ng_ppp_rcvdata_bypass(hook_p hook, item_p item)
|
||||
return (ng_ppp_hcomp_xmit(NG_HOOK_NODE(hook), item, proto));
|
||||
else
|
||||
return (ng_ppp_link_xmit(NG_HOOK_NODE(hook), item, proto,
|
||||
linkNum));
|
||||
linkNum, 0));
|
||||
}
|
||||
|
||||
static int
|
||||
@ -1177,10 +1230,6 @@ ng_ppp_crypt_recv(node_p node, item_p item, uint16_t proto, uint16_t linkNum)
|
||||
{
|
||||
const priv_p priv = NG_NODE_PRIVATE(node);
|
||||
|
||||
/* Stats */
|
||||
priv->bundleStats.recvFrames++;
|
||||
priv->bundleStats.recvOctets += NGI_M(item)->m_pkthdr.len;
|
||||
|
||||
if (proto == PROT_CRYPTD) {
|
||||
if (priv->conf.enableDecryption &&
|
||||
priv->hooks[HOOK_INDEX_DECRYPT] != NULL) {
|
||||
@ -1234,7 +1283,7 @@ ng_ppp_rcvdata_decrypt(hook_p hook, item_p item)
|
||||
*/
|
||||
|
||||
static int
|
||||
ng_ppp_link_xmit(node_p node, item_p item, uint16_t proto, uint16_t linkNum)
|
||||
ng_ppp_link_xmit(node_p node, item_p item, uint16_t proto, uint16_t linkNum, int plen)
|
||||
{
|
||||
const priv_p priv = NG_NODE_PRIVATE(node);
|
||||
struct ng_ppp_link *link;
|
||||
@ -1244,8 +1293,7 @@ ng_ppp_link_xmit(node_p node, item_p item, uint16_t proto, uint16_t linkNum)
|
||||
|
||||
/* Check if link correct. */
|
||||
if (linkNum >= NG_PPP_MAX_LINKS) {
|
||||
NG_FREE_ITEM(item);
|
||||
return (ENETDOWN);
|
||||
ERROUT(ENETDOWN);
|
||||
}
|
||||
|
||||
/* Get link pointer (optimization). */
|
||||
@ -1253,8 +1301,7 @@ ng_ppp_link_xmit(node_p node, item_p item, uint16_t proto, uint16_t linkNum)
|
||||
|
||||
/* Check link status (if real). */
|
||||
if (link->hook == NULL) {
|
||||
NG_FREE_ITEM(item);
|
||||
return (ENETDOWN);
|
||||
ERROUT(ENETDOWN);
|
||||
}
|
||||
|
||||
/* Extract mbuf. */
|
||||
@ -1264,34 +1311,39 @@ ng_ppp_link_xmit(node_p node, item_p item, uint16_t proto, uint16_t linkNum)
|
||||
mru = link->conf.mru;
|
||||
if (mru != 0 && m->m_pkthdr.len > mru) {
|
||||
NG_FREE_M(m);
|
||||
NG_FREE_ITEM(item);
|
||||
return (EMSGSIZE);
|
||||
ERROUT(EMSGSIZE);
|
||||
}
|
||||
|
||||
/* Prepend protocol number, possibly compressed. */
|
||||
if ((m = ng_ppp_addproto(m, proto, link->conf.enableProtoComp)) ==
|
||||
NULL) {
|
||||
NG_FREE_ITEM(item);
|
||||
return (ENOBUFS);
|
||||
ERROUT(ENOBUFS);
|
||||
}
|
||||
|
||||
/* Prepend address and control field (unless compressed). */
|
||||
if (proto == PROT_LCP || !link->conf.enableACFComp) {
|
||||
if ((m = ng_ppp_prepend(m, &ng_ppp_acf, 2)) == NULL) {
|
||||
NG_FREE_ITEM(item);
|
||||
return (ENOBUFS);
|
||||
}
|
||||
if ((m = ng_ppp_prepend(m, &ng_ppp_acf, 2)) == NULL)
|
||||
ERROUT(ENOBUFS);
|
||||
}
|
||||
|
||||
/* Deliver frame. */
|
||||
len = m->m_pkthdr.len;
|
||||
NG_FWD_NEW_DATA(error, item, link->hook, m);
|
||||
|
||||
/* Update stats and 'bytes in queue' counter. */
|
||||
if (error == 0) {
|
||||
link->stats.xmitFrames++;
|
||||
link->stats.xmitOctets += len;
|
||||
mtx_lock(&priv->xmtx);
|
||||
|
||||
/* Update link stats. */
|
||||
link->stats.xmitFrames++;
|
||||
link->stats.xmitOctets += len;
|
||||
|
||||
/* Update bundle stats. */
|
||||
if (plen > 0) {
|
||||
priv->bundleStats.xmitFrames++;
|
||||
priv->bundleStats.xmitOctets += plen;
|
||||
}
|
||||
|
||||
/* Update 'bytes in queue' counter. */
|
||||
if (error == 0) {
|
||||
/* bytesInQueue and lastWrite required only for mp_strategy. */
|
||||
if (priv->conf.enableMultilink && !priv->allLinksEqual &&
|
||||
!priv->conf.enableRoundRobin) {
|
||||
@ -1305,6 +1357,11 @@ ng_ppp_link_xmit(node_p node, item_p item, uint16_t proto, uint16_t linkNum)
|
||||
link->bytesInQueue = 50 * 1600;
|
||||
}
|
||||
}
|
||||
mtx_unlock(&priv->xmtx);
|
||||
return (error);
|
||||
|
||||
done:
|
||||
NG_FREE_ITEM(item);
|
||||
return (error);
|
||||
}
|
||||
|
||||
@ -1321,47 +1378,54 @@ ng_ppp_rcvdata(hook_p hook, item_p item)
|
||||
struct ng_ppp_link * const link = &priv->links[linkNum];
|
||||
uint16_t proto;
|
||||
struct mbuf *m;
|
||||
int error = 0;
|
||||
|
||||
KASSERT(linkNum < NG_PPP_MAX_LINKS,
|
||||
("%s: bogus index 0x%x", __func__, index));
|
||||
|
||||
NGI_GET_M(item, m);
|
||||
|
||||
mtx_lock(&priv->rmtx);
|
||||
|
||||
/* Stats */
|
||||
link->stats.recvFrames++;
|
||||
link->stats.recvOctets += m->m_pkthdr.len;
|
||||
|
||||
/* Strip address and control fields, if present. */
|
||||
if (m->m_len < 2 && (m = m_pullup(m, 2)) == NULL) {
|
||||
NG_FREE_ITEM(item);
|
||||
return (ENOBUFS);
|
||||
}
|
||||
if (m->m_len < 2 && (m = m_pullup(m, 2)) == NULL)
|
||||
ERROUT(ENOBUFS);
|
||||
if (bcmp(mtod(m, uint8_t *), &ng_ppp_acf, 2) == 0)
|
||||
m_adj(m, 2);
|
||||
|
||||
if ((m = ng_ppp_cutproto(m, &proto)) == NULL) {
|
||||
NG_FREE_ITEM(item);
|
||||
return (ENOBUFS);
|
||||
}
|
||||
/* Get protocol number */
|
||||
if ((m = ng_ppp_cutproto(m, &proto)) == NULL)
|
||||
ERROUT(ENOBUFS);
|
||||
NGI_M(item) = m; /* Put changed m back into item. */
|
||||
|
||||
if (!PROT_VALID(proto)) {
|
||||
link->stats.badProtos++;
|
||||
NG_FREE_ITEM(item);
|
||||
return (EIO);
|
||||
ERROUT(EIO);
|
||||
}
|
||||
|
||||
/* LCP packets must go directly to bypass. */
|
||||
if (proto >= 0xB000)
|
||||
if (proto >= 0xB000) {
|
||||
mtx_unlock(&priv->rmtx);
|
||||
return (ng_ppp_bypass(node, item, proto, linkNum));
|
||||
|
||||
if (!link->conf.enableLink) {
|
||||
/* Non-LCP packets are denied on a disabled link. */
|
||||
NG_FREE_ITEM(item);
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* Other packets are denied on a disabled link. */
|
||||
if (!link->conf.enableLink)
|
||||
ERROUT(ENXIO);
|
||||
|
||||
return (ng_ppp_mp_recv(node, item, proto, linkNum));
|
||||
/* Proceed to multilink layer. Mutex will be unlocked inside. */
|
||||
error = ng_ppp_mp_recv(node, item, proto, linkNum);
|
||||
mtx_assert(&priv->rmtx, MA_NOTOWNED);
|
||||
return (error);
|
||||
|
||||
done:
|
||||
mtx_unlock(&priv->rmtx);
|
||||
NG_FREE_ITEM(item);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1429,9 +1493,16 @@ ng_ppp_mp_recv(node_p node, item_p item, uint16_t proto, uint16_t linkNum)
|
||||
struct ng_ppp_frag *qent;
|
||||
int i, diff, inserted;
|
||||
struct mbuf *m;
|
||||
int error = 0;
|
||||
|
||||
if ((!priv->conf.enableMultilink) || proto != PROT_MP)
|
||||
if ((!priv->conf.enableMultilink) || proto != PROT_MP) {
|
||||
/* Stats */
|
||||
priv->bundleStats.recvFrames++;
|
||||
priv->bundleStats.recvOctets += NGI_M(item)->m_pkthdr.len;
|
||||
|
||||
mtx_unlock(&priv->rmtx);
|
||||
return (ng_ppp_crypt_recv(node, item, proto, linkNum));
|
||||
}
|
||||
|
||||
NGI_GET_M(item, m);
|
||||
NG_FREE_ITEM(item);
|
||||
@ -1443,10 +1514,10 @@ ng_ppp_mp_recv(node_p node, item_p item, uint16_t proto, uint16_t linkNum)
|
||||
if (m->m_pkthdr.len < 2) {
|
||||
link->stats.runts++;
|
||||
NG_FREE_M(m);
|
||||
return (EINVAL);
|
||||
ERROUT(EINVAL);
|
||||
}
|
||||
if (m->m_len < 2 && (m = m_pullup(m, 2)) == NULL)
|
||||
return (ENOBUFS);
|
||||
ERROUT(ENOBUFS);
|
||||
|
||||
shdr = ntohs(*mtod(m, uint16_t *));
|
||||
frag->seq = MP_SHORT_EXTEND(shdr);
|
||||
@ -1460,10 +1531,10 @@ ng_ppp_mp_recv(node_p node, item_p item, uint16_t proto, uint16_t linkNum)
|
||||
if (m->m_pkthdr.len < 4) {
|
||||
link->stats.runts++;
|
||||
NG_FREE_M(m);
|
||||
return (EINVAL);
|
||||
ERROUT(EINVAL);
|
||||
}
|
||||
if (m->m_len < 4 && (m = m_pullup(m, 4)) == NULL)
|
||||
return (ENOBUFS);
|
||||
ERROUT(ENOBUFS);
|
||||
|
||||
lhdr = ntohl(*mtod(m, uint32_t *));
|
||||
frag->seq = MP_LONG_EXTEND(lhdr);
|
||||
@ -1480,7 +1551,7 @@ ng_ppp_mp_recv(node_p node, item_p item, uint16_t proto, uint16_t linkNum)
|
||||
if (diff < 0) {
|
||||
link->stats.dropFragments++;
|
||||
NG_FREE_M(m);
|
||||
return (0);
|
||||
ERROUT(0);
|
||||
}
|
||||
|
||||
/* Update highest received sequence number on this link and MSEQ */
|
||||
@ -1497,8 +1568,7 @@ ng_ppp_mp_recv(node_p node, item_p item, uint16_t proto, uint16_t linkNum)
|
||||
MALLOC(frag, struct ng_ppp_frag *, sizeof(*frag), M_NETGRAPH_PPP, M_NOWAIT);
|
||||
if (frag == NULL) {
|
||||
NG_FREE_M(m);
|
||||
ng_ppp_frag_process(node);
|
||||
return (ENOMEM);
|
||||
goto process;
|
||||
}
|
||||
*frag = frag0;
|
||||
|
||||
@ -1514,15 +1584,21 @@ ng_ppp_mp_recv(node_p node, item_p item, uint16_t proto, uint16_t linkNum)
|
||||
link->stats.dupFragments++;
|
||||
NG_FREE_M(frag->data);
|
||||
FREE(frag, M_NETGRAPH_PPP);
|
||||
return (EINVAL);
|
||||
ERROUT(EINVAL);
|
||||
}
|
||||
}
|
||||
if (!inserted)
|
||||
TAILQ_INSERT_HEAD(&priv->frags, frag, f_qent);
|
||||
priv->qlen++;
|
||||
|
||||
process:
|
||||
/* Process the queue */
|
||||
return ng_ppp_frag_process(node);
|
||||
/* NOTE: rmtx will be unlocked for sending time! */
|
||||
error = ng_ppp_frag_process(node);
|
||||
|
||||
done:
|
||||
mtx_unlock(&priv->rmtx);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
@ -1729,9 +1805,20 @@ ng_ppp_frag_process(node_p node)
|
||||
NG_FREE_M(m);
|
||||
continue;
|
||||
}
|
||||
if ((item = ng_package_data(m, NG_NOFLAGS)) != NULL)
|
||||
if ((item = ng_package_data(m, NG_NOFLAGS)) != NULL) {
|
||||
/* Stats */
|
||||
priv->bundleStats.recvFrames++;
|
||||
priv->bundleStats.recvOctets +=
|
||||
NGI_M(item)->m_pkthdr.len;
|
||||
|
||||
/* Drop mutex for the sending time.
|
||||
* Priv may change, but we are ready!
|
||||
*/
|
||||
mtx_unlock(&priv->rmtx);
|
||||
ng_ppp_crypt_recv(node, item, proto,
|
||||
NG_PPP_BUNDLE_LINKNUM);
|
||||
mtx_lock(&priv->rmtx);
|
||||
}
|
||||
}
|
||||
/* Delete dead fragments and try again */
|
||||
} while (ng_ppp_frag_trim(node) || ng_ppp_frag_drop(node));
|
||||
@ -1824,9 +1911,14 @@ ng_ppp_frag_checkstale(node_p node)
|
||||
}
|
||||
|
||||
/* Deliver packet */
|
||||
if ((item = ng_package_data(m, NG_NOFLAGS)) != NULL)
|
||||
if ((item = ng_package_data(m, NG_NOFLAGS)) != NULL) {
|
||||
/* Stats */
|
||||
priv->bundleStats.recvFrames++;
|
||||
priv->bundleStats.recvOctets += NGI_M(item)->m_pkthdr.len;
|
||||
|
||||
ng_ppp_crypt_recv(node, item, proto,
|
||||
NG_PPP_BUNDLE_LINKNUM);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1860,20 +1952,23 @@ ng_ppp_mp_xmit(node_p node, item_p item, uint16_t proto)
|
||||
int firstFragment;
|
||||
int activeLinkNum;
|
||||
struct mbuf *m;
|
||||
int len;
|
||||
int frags;
|
||||
int32_t seq;
|
||||
|
||||
/* At least one link must be active */
|
||||
if (priv->numActiveLinks == 0) {
|
||||
NG_FREE_ITEM(item);
|
||||
return (ENETDOWN);
|
||||
}
|
||||
|
||||
/* Save length for later stats. */
|
||||
len = NGI_M(item)->m_pkthdr.len;
|
||||
|
||||
/* Update stats. */
|
||||
priv->bundleStats.xmitFrames++;
|
||||
priv->bundleStats.xmitOctets += NGI_M(item)->m_pkthdr.len;
|
||||
|
||||
if (!priv->conf.enableMultilink)
|
||||
if (!priv->conf.enableMultilink) {
|
||||
return (ng_ppp_link_xmit(node, item, proto,
|
||||
priv->activeLinks[0]));
|
||||
priv->activeLinks[0], len));
|
||||
}
|
||||
|
||||
/* Extract mbuf. */
|
||||
NGI_GET_M(item, m);
|
||||
@ -1886,6 +1981,8 @@ ng_ppp_mp_xmit(node_p node, item_p item, uint16_t proto)
|
||||
/* Clear distribution plan */
|
||||
bzero(&distrib, priv->numActiveLinks * sizeof(distrib[0]));
|
||||
|
||||
mtx_lock(&priv->xmtx);
|
||||
|
||||
/* Round-robin strategy */
|
||||
if (priv->conf.enableRoundRobin) {
|
||||
activeLinkNum = priv->lastLink++ % priv->numActiveLinks;
|
||||
@ -1920,6 +2017,29 @@ ng_ppp_mp_xmit(node_p node, item_p item, uint16_t proto)
|
||||
ng_ppp_mp_strategy(node, m->m_pkthdr.len, distrib);
|
||||
|
||||
deliver:
|
||||
/* Estimate fragments count */
|
||||
frags = 0;
|
||||
for (activeLinkNum = priv->numActiveLinks - 1;
|
||||
activeLinkNum >= 0; activeLinkNum--) {
|
||||
const uint16_t linkNum = priv->activeLinks[activeLinkNum];
|
||||
struct ng_ppp_link *const link = &priv->links[linkNum];
|
||||
|
||||
frags += (distrib[activeLinkNum] + link->conf.mru - hdr_len - 1) /
|
||||
(link->conf.mru - hdr_len);
|
||||
}
|
||||
|
||||
/* Get out initial sequence number */
|
||||
seq = priv->xseq;
|
||||
|
||||
/* Update next sequence number */
|
||||
if (priv->conf.xmitShortSeq) {
|
||||
priv->xseq = (seq + frags) & MP_SHORT_SEQ_MASK;
|
||||
} else {
|
||||
priv->xseq = (seq + frags) & MP_LONG_SEQ_MASK;
|
||||
}
|
||||
|
||||
mtx_unlock(&priv->xmtx);
|
||||
|
||||
/* Send alloted portions of frame out on the link(s) */
|
||||
for (firstFragment = 1, activeLinkNum = priv->numActiveLinks - 1;
|
||||
activeLinkNum >= 0; activeLinkNum--) {
|
||||
@ -1955,9 +2075,8 @@ ng_ppp_mp_xmit(node_p node, item_p item, uint16_t proto)
|
||||
if (priv->conf.xmitShortSeq) {
|
||||
uint16_t shdr;
|
||||
|
||||
shdr = priv->xseq;
|
||||
priv->xseq =
|
||||
(priv->xseq + 1) & MP_SHORT_SEQ_MASK;
|
||||
shdr = seq;
|
||||
seq = (seq + 1) & MP_SHORT_SEQ_MASK;
|
||||
if (firstFragment)
|
||||
shdr |= MP_SHORT_FIRST_FLAG;
|
||||
if (lastFragment)
|
||||
@ -1967,9 +2086,8 @@ ng_ppp_mp_xmit(node_p node, item_p item, uint16_t proto)
|
||||
} else {
|
||||
uint32_t lhdr;
|
||||
|
||||
lhdr = priv->xseq;
|
||||
priv->xseq =
|
||||
(priv->xseq + 1) & MP_LONG_SEQ_MASK;
|
||||
lhdr = seq;
|
||||
seq = (seq + 1) & MP_LONG_SEQ_MASK;
|
||||
if (firstFragment)
|
||||
lhdr |= MP_LONG_FIRST_FLAG;
|
||||
if (lastFragment)
|
||||
@ -1986,7 +2104,7 @@ ng_ppp_mp_xmit(node_p node, item_p item, uint16_t proto)
|
||||
/* Send fragment */
|
||||
if ((item = ng_package_data(m2, NG_NOFLAGS)) != NULL) {
|
||||
error = ng_ppp_link_xmit(node, item, PROT_MP,
|
||||
linkNum);
|
||||
linkNum, (firstFragment?len:0));
|
||||
if (error != 0) {
|
||||
if (!lastFragment)
|
||||
NG_FREE_M(m);
|
||||
|
@ -48,6 +48,9 @@
|
||||
#define NG_PPP_NODE_TYPE "ppp"
|
||||
#define NGM_PPP_COOKIE 940897795
|
||||
|
||||
/* 64bit stats presence flag */
|
||||
#define NG_PPP_STATS64
|
||||
|
||||
/* Maximum number of supported links */
|
||||
#define NG_PPP_MAX_LINKS 16
|
||||
|
||||
@ -97,6 +100,8 @@ enum {
|
||||
NGM_PPP_GET_LINK_STATS, /* takes link #, returns stats struct */
|
||||
NGM_PPP_CLR_LINK_STATS, /* takes link #, clears link stats */
|
||||
NGM_PPP_GETCLR_LINK_STATS, /* takes link #, returns & clrs stats */
|
||||
NGM_PPP_GET_LINK_STATS64, /* takes link #, returns stats64 struct */
|
||||
NGM_PPP_GETCLR_LINK_STATS64, /* takes link #, returns stats64 & clrs */
|
||||
};
|
||||
|
||||
/* Multi-link sequence number state (for debugging) */
|
||||
@ -212,4 +217,29 @@ struct ng_ppp_link_stat {
|
||||
{ NULL } \
|
||||
}
|
||||
|
||||
/* Statistics struct for a link (or the bundle if NG_PPP_BUNDLE_LINKNUM) */
|
||||
struct ng_ppp_link_stat64 {
|
||||
u_int64_t xmitFrames; /* xmit frames on link */
|
||||
u_int64_t xmitOctets; /* xmit octets on link */
|
||||
u_int64_t recvFrames; /* recv frames on link */
|
||||
u_int64_t recvOctets; /* recv octets on link */
|
||||
u_int64_t badProtos; /* frames rec'd with bogus protocol */
|
||||
u_int64_t runts; /* Too short MP fragments */
|
||||
u_int64_t dupFragments; /* MP frames with duplicate seq # */
|
||||
u_int64_t dropFragments; /* MP fragments we had to drop */
|
||||
};
|
||||
|
||||
/* Keep this in sync with the above structure definition */
|
||||
#define NG_PPP_STATS64_TYPE_INFO { \
|
||||
{ "xmitFrames", &ng_parse_uint64_type }, \
|
||||
{ "xmitOctets", &ng_parse_uint64_type }, \
|
||||
{ "recvFrames", &ng_parse_uint64_type }, \
|
||||
{ "recvOctets", &ng_parse_uint64_type }, \
|
||||
{ "badProtos", &ng_parse_uint64_type }, \
|
||||
{ "runts", &ng_parse_uint64_type }, \
|
||||
{ "dupFragments", &ng_parse_uint64_type }, \
|
||||
{ "dropFragments", &ng_parse_uint64_type }, \
|
||||
{ NULL } \
|
||||
}
|
||||
|
||||
#endif /* _NETGRAPH_NG_PPP_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user