Annotation of embedaddon/mpd/src/bund.c, revision 1.1.1.5.2.1
1.1 misho 1:
2: /*
3: * bund.c
4: *
5: * Written by Archie Cobbs <archie@freebsd.org>
6: * Copyright (c) 1995-1999 Whistle Communications, Inc. All rights reserved.
7: * See ``COPYRIGHT.whistle''
8: *
9: * Bundle handling stuff
10: */
11:
12: #include "ppp.h"
13: #include "bund.h"
14: #include "ipcp.h"
15: #include "ccp.h"
16: #include "mp.h"
17: #include "iface.h"
18: #include "link.h"
19: #include "msg.h"
20: #include "ngfunc.h"
21: #include "log.h"
22: #include "util.h"
23: #include "input.h"
24:
25: #include <netgraph.h>
26: #include <netgraph/ng_message.h>
27: #include <netgraph/ng_socket.h>
28: #include <netgraph/ng_iface.h>
29: #ifdef USE_NG_VJC
30: #include <netgraph/ng_vjc.h>
31: #endif
32:
33: /*
34: * DEFINITIONS
35: */
36:
37: /* #define DEBUG_BOD */
38:
39: #define BUND_REOPEN_DELAY 3 /* wait this long before closing */
40: #define BUND_REOPEN_PAUSE 3 /* wait this long before re-opening */
41:
42: #define BUND_MIN_TOT_BW 9600
43:
44: /* Set menu options */
45: enum {
46: SET_PERIOD,
47: SET_LOW_WATER,
48: SET_HIGH_WATER,
49: SET_MIN_CONNECT,
50: SET_MIN_DISCONNECT,
51: SET_LINKS,
52: SET_AUTHNAME,
53: SET_PASSWORD,
54: SET_RETRY,
55: SET_ACCEPT,
56: SET_DENY,
57: SET_ENABLE,
58: SET_DISABLE,
59: SET_YES,
60: SET_NO
61: };
62:
63: /*
64: * INTERNAL FUNCTIONS
65: */
66:
67: static int BundNgInit(Bund b);
68: static void BundNgShutdown(Bund b, int iface, int ppp);
69:
70: static void BundBmStart(Bund b);
71: static void BundBmStop(Bund b);
72: static void BundBmTimeout(void *arg);
73:
74: static void BundReasses(Bund b);
1.1.1.5 misho 75: static int BundSetCommand(Context ctx, int ac, const char *const av[], const void *arg);
1.1 misho 76:
77: static void BundNcpsUp(Bund b);
78: static void BundNcpsDown(Bund b);
79:
80: static void BundReOpenLinks(void *arg);
81: static void BundCloseLink(Link l);
82:
83: static void BundMsg(int type, void *cookie);
84:
85: /*
86: * GLOBAL VARIABLES
87: */
88:
89: struct discrim self_discrim;
90:
91: const struct cmdtab BundSetCmds[] = {
92: { "period {seconds}", "BoD sampling period",
93: BundSetCommand, NULL, 2, (void *) SET_PERIOD },
94: { "lowat {percent}", "BoD low water mark",
95: BundSetCommand, NULL, 2, (void *) SET_LOW_WATER },
96: { "hiwat {percent}", "BoD high water mark",
97: BundSetCommand, NULL, 2, (void *) SET_HIGH_WATER },
98: { "min-con {seconds}", "BoD min connected time",
99: BundSetCommand, NULL, 2, (void *) SET_MIN_CONNECT },
100: { "min-dis {seconds}", "BoD min disconnected time",
101: BundSetCommand, NULL, 2, (void *) SET_MIN_DISCONNECT },
102: { "links {link list ...}", "Links list for BoD/DoD",
103: BundSetCommand, NULL, 2, (void *) SET_LINKS },
104: { "fsm-timeout {seconds}", "FSM retry timeout",
105: BundSetCommand, NULL, 2, (void *) SET_RETRY },
106: { "accept {opt ...}", "Accept option",
107: BundSetCommand, NULL, 2, (void *) SET_ACCEPT },
108: { "deny {opt ...}", "Deny option",
109: BundSetCommand, NULL, 2, (void *) SET_DENY },
110: { "enable {opt ...}", "Enable option",
111: BundSetCommand, NULL, 2, (void *) SET_ENABLE },
112: { "disable {opt ...}", "Disable option",
113: BundSetCommand, NULL, 2, (void *) SET_DISABLE },
114: { "yes {opt ...}", "Enable and accept option",
115: BundSetCommand, NULL, 2, (void *) SET_YES },
116: { "no {opt ...}", "Disable and deny option",
117: BundSetCommand, NULL, 2, (void *) SET_NO },
1.1.1.5 misho 118: { NULL, NULL, NULL, NULL, 0, NULL },
1.1 misho 119: };
120:
121: /*
122: * INTERNAL VARIABLES
123: */
124:
125: static const struct confinfo gConfList[] = {
126: { 0, BUND_CONF_IPCP, "ipcp" },
127: { 0, BUND_CONF_IPV6CP, "ipv6cp" },
128: { 0, BUND_CONF_COMPRESSION, "compression" },
129: { 0, BUND_CONF_ENCRYPTION, "encryption" },
130: { 0, BUND_CONF_CRYPT_REQD, "crypt-reqd" },
131: { 0, BUND_CONF_BWMANAGE, "bw-manage" },
132: { 0, BUND_CONF_ROUNDROBIN, "round-robin" },
133: { 0, 0, NULL },
134: };
135:
136: /*
137: * BundOpen()
138: */
139:
140: void
141: BundOpen(Bund b)
142: {
143: REF(b);
144: MsgSend(&b->msgs, MSG_OPEN, b);
145: }
146:
147: /*
148: * BundClose()
149: */
150:
151: void
152: BundClose(Bund b)
153: {
154: REF(b);
155: MsgSend(&b->msgs, MSG_CLOSE, b);
156: }
157:
158: /*
159: * BundOpenCmd()
160: */
161:
162: int
163: BundOpenCmd(Context ctx)
164: {
165: if (ctx->bund->tmpl)
166: Error("impossible to open template");
167: BundOpen(ctx->bund);
168: return (0);
169: }
170:
171: /*
172: * BundCloseCmd()
173: */
174:
175: int
176: BundCloseCmd(Context ctx)
177: {
178: if (ctx->bund->tmpl)
179: Error("impossible to close template");
180: BundClose(ctx->bund);
181: return (0);
182: }
183:
184: /*
185: * BundJoin()
186: *
187: * This is called when a link enters the NETWORK phase.
188: *
189: * Verify that link is OK to come up as part of it's bundle.
190: * If so, join it to the bundle. Returns FALSE if there's a problem.
191: * If this is the first link to join, and it's not supporting
192: * multi-link, then prevent any further links from joining.
193: *
194: * Right now this is fairly simple minded: you have to define
195: * the links in a bundle first, then stick to that plan. For
196: * a server this might be too restrictive a policy.
197: *
198: * Returns zero if fails, otherwise the new number of up links.
199: */
200:
201: int
202: BundJoin(Link l)
203: {
204: Bund b, bt;
205: LcpState const lcp = &l->lcp;
206: int k;
207:
208: if (gShutdownInProgress) {
209: Log(LG_BUND, ("Shutdown sequence in progress, BundJoin() denied"));
210: return(0);
211: }
212:
213: if (!l->bund) {
214: b = NULL;
215: if (lcp->peer_mrru) {
216: for (k = 0; k < gNumBundles; k++) {
217: if (gBundles[k] && !gBundles[k]->tmpl && gBundles[k]->peer_mrru &&
218: MpDiscrimEqual(&lcp->peer_discrim, &gBundles[k]->peer_discrim) &&
219: !strcmp(lcp->auth.params.authname, gBundles[k]->params.authname)) {
220: break;
221: }
222: }
223: if (k != gNumBundles) {
224: b = gBundles[k];
225: }
226: }
227: if (!b) {
228: const char *bundt;
229: if (strncmp(l->lcp.auth.params.action, "bundle ", 7) == 0) {
230: bundt = l->lcp.auth.params.action + 7;
231: } else {
232: bundt = LinkMatchAction(l, 3, l->lcp.auth.params.authname);
233: }
234: if (bundt) {
235: if (strcmp(bundt,"##DROP##") == 0) {
236: /* Action told we must drop this connection */
237: Log(LG_BUND, ("[%s] Drop link", l->name));
238: return (0);
239: }
240: if ((bt = BundFind(bundt))) {
241: if (bt->tmpl) {
242: Log(LG_BUND, ("[%s] Creating new bundle using template \"%s\".", l->name, bundt));
243: b = BundInst(bt, NULL, 0, 0);
244: } else {
245: b = bt;
246: }
247: } else {
248: Log(LG_BUND, ("[%s] Bundle \"%s\" not found.", l->name, bundt));
249: return (0);
250: }
251: } else {
252: Log(LG_BUND, ("[%s] No bundle specified", l->name));
253: return (0);
254: }
255: if (!b) {
256: Log(LG_BUND, ("[%s] Bundle creation error", l->name));
257: return (0);
258: }
259: }
260: if (b->n_up > 0 &&
261: (b->peer_mrru == 0 || lcp->peer_mrru == 0 || lcp->want_mrru == 0)) {
262: Log(LG_BUND, ("[%s] Can't join bundle %s without "
263: "multilink negotiated.", l->name, b->name));
264: return (0);
265: }
266: if (b->n_up > 0 &&
267: (!MpDiscrimEqual(&lcp->peer_discrim, &b->peer_discrim) ||
268: strcmp(lcp->auth.params.authname, b->params.authname))) {
269: Log(LG_BUND, ("[%s] Can't join bundle %s with different "
270: "peer discriminator/authname.", l->name, b->name));
271: return (0);
272: }
273: k = 0;
274: while (k < NG_PPP_MAX_LINKS && b->links[k] != NULL)
275: k++;
276: if (k < NG_PPP_MAX_LINKS) {
277: l->bund = b;
278: l->bundleIndex = k;
279: b->links[k] = l;
280: b->n_links++;
281: } else {
282: Log(LG_BUND, ("[%s] No more then %d links per bundle allowed. "
283: "Can't join budle.", l->name, NG_PPP_MAX_LINKS));
284: return (0);
285: }
286: }
287:
288: b = l->bund;
289:
290: Log(LG_LINK, ("[%s] Link: Join bundle \"%s\"", l->name, b->name));
291:
292: b->open = TRUE; /* Open bundle on incoming */
293:
294: if (LinkNgJoin(l)) {
295: Log(LG_ERR, ("[%s] Bundle netgraph join failed", l->name));
296: l->bund = NULL;
297: b->links[l->bundleIndex] = NULL;
298: if (!b->stay)
299: BundShutdown(b);
300: return(0);
301: }
302: l->joined_bund = 1;
303: b->n_up++;
304:
305: LinkResetStats(l);
306:
307: if (b->n_up == 1) {
308:
309: /* Cancel re-open timer; we've come up somehow (eg, LCP renegotiation) */
310: TimerStop(&b->reOpenTimer);
311:
312: b->last_up = time(NULL);
313:
314: /* Copy auth params from the first link */
315: authparamsCopy(&l->lcp.auth.params,&b->params);
316:
317: /* Initialize multi-link stuff */
318: if ((b->peer_mrru = lcp->peer_mrru)) {
319: b->peer_discrim = lcp->peer_discrim;
320: }
321:
322: /* Start bandwidth management */
323: BundBmStart(b);
324: }
325:
326: /* Reasses MTU, bandwidth, etc. */
327: BundReasses(b);
328:
329: /* Configure this link */
330: b->pppConfig.links[l->bundleIndex].enableLink = 1;
1.1.1.4 misho 331: b->pppConfig.links[l->bundleIndex].mru = b->iface.mtu_override ?
332: b->iface.mtu_override : lcp->peer_mru;
1.1 misho 333: b->pppConfig.links[l->bundleIndex].enableACFComp = lcp->peer_acfcomp;
334: b->pppConfig.links[l->bundleIndex].enableProtoComp = lcp->peer_protocomp;
335: b->pppConfig.links[l->bundleIndex].bandwidth =
336: MIN((l->bandwidth / 8 + 5) / 10, NG_PPP_MAX_BANDWIDTH);
337: b->pppConfig.links[l->bundleIndex].latency =
338: MIN((l->latency + 500) / 1000, NG_PPP_MAX_LATENCY);
339:
340: /* What to do when the first link comes up */
341: if (b->n_up == 1) {
342:
343: /* Configure the bundle */
344: b->pppConfig.bund.enableMultilink = (lcp->peer_mrru && lcp->want_mrru)?1:0;
345: /* ng_ppp does not allow MRRU less then 1500 bytes. */
346: b->pppConfig.bund.mrru = (lcp->peer_mrru < 1500) ? 1500 : lcp->peer_mrru;
347: b->pppConfig.bund.xmitShortSeq = lcp->peer_shortseq;
348: b->pppConfig.bund.recvShortSeq = lcp->want_shortseq;
349: b->pppConfig.bund.enableRoundRobin =
350: Enabled(&b->conf.options, BUND_CONF_ROUNDROBIN);
351:
352: /* generate a uniq msession_id */
353: snprintf(b->msession_id, AUTH_MAX_SESSIONID, "%d-%s",
354: (int)(time(NULL) % 10000000), b->name);
355:
356: b->originate = l->originate;
357: }
358:
359: /* Update PPP node configuration */
360: NgFuncSetConfig(b);
361:
362: /* copy msession_id to link */
363: strlcpy(l->msession_id, b->msession_id, sizeof(l->msession_id));
364:
365: /* What to do when the first link comes up */
366: if (b->n_up == 1) {
367:
368: BundNcpsOpen(b);
369: BundNcpsUp(b);
370:
371: BundResetStats(b);
372:
373: #ifndef NG_PPP_STATS64
374: /* starting bundle statistics timer */
375: TimerInit(&b->statsUpdateTimer, "BundUpdateStats",
376: BUND_STATS_UPDATE_INTERVAL, BundUpdateStatsTimer, b);
377: TimerStartRecurring(&b->statsUpdateTimer);
378: #endif
379: }
380:
381: AuthAccountStart(l, AUTH_ACCT_START);
382:
383: return(b->n_up);
384: }
385:
386: /*
387: * BundLeave()
388: *
389: * This is called when a link leaves the NETWORK phase.
390: */
391:
392: void
393: BundLeave(Link l)
394: {
395: Bund b = l->bund;
396:
397: /* Elvis has left the bundle */
398: assert(b->n_up > 0);
399:
400: Log(LG_LINK, ("[%s] Link: Leave bundle \"%s\"", l->name, b->name));
401:
402: AuthAccountStart(l, AUTH_ACCT_STOP);
403:
404: /* Disable link */
405: b->pppConfig.links[l->bundleIndex].enableLink = 0;
406: b->pppConfig.links[l->bundleIndex].mru = LCP_DEFAULT_MRU;
407: NgFuncSetConfig(b);
408:
409: LinkNgLeave(l);
410: l->joined_bund = 0;
411: b->n_up--;
412:
413: /* Divorce link and bundle */
414: b->links[l->bundleIndex] = NULL;
415: b->n_links--;
416: l->bund = NULL;
417:
418: BundReasses(b);
419:
420: /* Forget session_ids */
421: l->msession_id[0] = 0;
422:
423: /* Special stuff when last link goes down... */
424: if (b->n_up == 0) {
425:
426: #ifndef NG_PPP_STATS64
427: /* stopping bundle statistics timer */
428: TimerStop(&b->statsUpdateTimer);
429: #endif
430:
431: /* Reset statistics and auth information */
432: BundBmStop(b);
433:
434: BundNcpsClose(b);
435: BundNcpsDown(b);
436:
437: #ifdef USE_NG_BPF
438: IfaceFreeStats(&b->iface.prevstats);
439: #endif
440:
441: authparamsDestroy(&b->params);
442:
443: b->msession_id[0] = 0;
444:
445: /* try to open again later */
446: if (b->open && Enabled(&b->conf.options, BUND_CONF_BWMANAGE) &&
447: !Enabled(&b->iface.options, IFACE_CONF_ONDEMAND) && !gShutdownInProgress) {
448: if (b->n_links != 0 || b->conf.linkst[0][0]) {
449: /* wait BUND_REOPEN_DELAY to see if it comes back up */
450: int delay = BUND_REOPEN_DELAY;
451: delay += ((random() ^ gPid ^ time(NULL)) & 1);
452: Log(LG_BUND, ("[%s] Bundle: Last link has gone, reopening in %d seconds",
453: b->name, delay));
454: TimerStop(&b->reOpenTimer);
455: TimerInit(&b->reOpenTimer, "BundReOpen",
456: delay * SECONDS, BundReOpenLinks, b);
457: TimerStart(&b->reOpenTimer);
458: return;
459: } else {
460: Log(LG_BUND, ("[%s] Bundle: Last link has gone, no links for bw-manage defined",
461: b->name));
462: }
463: }
464: b->open = FALSE;
465: if (!b->stay)
466: BundShutdown(b);
467: }
468: }
469:
470: /*
471: * BundReOpenLinks()
472: *
473: * The last link went down, and we waited BUND_REOPEN_DELAY seconds for
474: * it to come back up. It didn't, so close all the links and re-open them
475: * BUND_REOPEN_PAUSE seconds from now.
476: *
477: * The timer calling this is cancelled whenever any link comes up.
478: */
479:
480: static void
481: BundReOpenLinks(void *arg)
482: {
483: Bund b = (Bund)arg;
484:
485: Log(LG_BUND, ("[%s] Bundle: Last link has gone, reopening...", b->name));
486: BundOpenLinks(b);
487: }
488:
489: /*
490: * BundMsg()
491: *
492: * Deal with incoming message to the bundle
493: */
494:
495: static void
496: BundMsg(int type, void *arg)
497: {
498: Bund b = (Bund)arg;
499:
500: if (b->dead) {
501: UNREF(b);
502: return;
503: }
504: Log(LG_BUND, ("[%s] Bundle: %s event in state %s",
505: b->name, MsgName(type), b->open ? "OPENED" : "CLOSED"));
506: TimerStop(&b->reOpenTimer);
507: switch (type) {
508: case MSG_OPEN:
509: b->open = TRUE;
510: BundOpenLinks(b);
511: break;
512:
513: case MSG_CLOSE:
514: b->open = FALSE;
515: BundCloseLinks(b);
516: break;
517:
518: default:
519: assert(FALSE);
520: }
521: UNREF(b);
522: }
523:
524: /*
525: * BundOpenLinks()
526: *
527: * Open one link or all links, depending on whether bandwidth
528: * management is in effect or not.
529: */
530:
531: void
532: BundOpenLinks(Bund b)
533: {
534: int k;
535:
536: TimerStop(&b->reOpenTimer);
537: if (Enabled(&b->conf.options, BUND_CONF_BWMANAGE)) {
538: if (b->n_links != 0)
539: return;
540: for (k = 0; k < NG_PPP_MAX_LINKS; k++) {
541: if (b->links[k]) {
542: BundOpenLink(b->links[k]);
543: break;
544: } else if (b->conf.linkst[k][0]) {
545: BundCreateOpenLink(b, k);
546: break;
547: }
548: }
549: } else {
550: for (k = 0; k < NG_PPP_MAX_LINKS; k++) {
551: if (b->links[k])
552: BundOpenLink(b->links[k]);
553: else if (b->conf.linkst[k][0])
554: BundCreateOpenLink(b, k);
555: }
556: }
557: }
558:
559: /*
560: * BundCreateOpenLink()
561: */
562:
563: int
564: BundCreateOpenLink(Bund b, int n)
565: {
566: if (!b->links[n]) {
567: if (b->conf.linkst[n][0]) {
568: Link l;
569: Link lt = LinkFind(b->conf.linkst[n]);
570: if (!lt) {
571: Log(LG_BUND, ("[%s] Bund: Link \"%s\" not found", b->name, b->conf.linkst[n]));
572: return (-1);
573: }
574: if (PhysIsBusy(lt)) {
575: Log(LG_BUND, ("[%s] Bund: Link \"%s\" is busy", b->name, b->conf.linkst[n]));
576: return (-1);
577: }
578: if (lt->tmpl) {
579: l = LinkInst(lt, NULL, 0, 0);
580: } else
581: l = lt;
582: if (!l) {
583: Log(LG_BUND, ("[%s] Bund: Link \"%s\" creation error", b->name, b->conf.linkst[n]));
584: return (-1);
585: }
586: b->links[n] = l;
587: b->n_links++;
588: l->bund = b;
589: l->bundleIndex = n;
590: l->conf.max_redial = -1;
591: } else {
592: Log(LG_BUND, ("[%s] Bund: Link %d name not specified", b->name, n));
593: return (-1);
594: }
595: }
596: BundOpenLink(b->links[n]);
597: return (0);
598: }
599:
600: /*
601: * BundOpenLink()
602: */
603:
604: void
605: BundOpenLink(Link l)
606: {
607: Log(LG_BUND, ("[%s] opening link \"%s\"...", l->bund->name, l->name));
608: LinkOpen(l);
609: }
610:
611: /*
612: * BundCloseLinks()
613: *
614: * Close all links
615: */
616:
617: void
618: BundCloseLinks(Bund b)
619: {
620: int k;
621:
622: TimerStop(&b->reOpenTimer);
623: for (k = 0; k < NG_PPP_MAX_LINKS; k++)
624: if (b->links[k] && OPEN_STATE(b->links[k]->lcp.fsm.state))
625: BundCloseLink(b->links[k]);
626: }
627:
628: /*
629: * BundCloseLink()
630: */
631:
632: static void
633: BundCloseLink(Link l)
634: {
635: Log(LG_BUND, ("[%s] Bundle: closing link \"%s\"...", l->bund->name, l->name));
636: LinkClose(l);
637: }
638:
639: /*
640: * BundNcpsOpen()
641: */
642:
643: void
644: BundNcpsOpen(Bund b)
645: {
646: if (Enabled(&b->conf.options, BUND_CONF_IPCP))
647: IpcpOpen(b);
648: if (Enabled(&b->conf.options, BUND_CONF_IPV6CP))
649: Ipv6cpOpen(b);
650: if (Enabled(&b->conf.options, BUND_CONF_COMPRESSION))
651: CcpOpen(b);
652: if (Enabled(&b->conf.options, BUND_CONF_ENCRYPTION))
653: EcpOpen(b);
654: }
655:
656: /*
657: * BundNcpsUp()
658: */
659:
660: static void
661: BundNcpsUp(Bund b)
662: {
663: if (Enabled(&b->conf.options, BUND_CONF_IPCP))
664: IpcpUp(b);
665: if (Enabled(&b->conf.options, BUND_CONF_IPV6CP))
666: Ipv6cpUp(b);
667: if (Enabled(&b->conf.options, BUND_CONF_COMPRESSION))
668: CcpUp(b);
669: if (Enabled(&b->conf.options, BUND_CONF_ENCRYPTION))
670: EcpUp(b);
671: }
672:
673: void
674: BundNcpsStart(Bund b, int proto)
675: {
676: b->ncpstarted |= ((1<<proto)>>1);
677: }
678:
679: void
680: BundNcpsFinish(Bund b, int proto)
681: {
682: b->ncpstarted &= (~((1<<proto)>>1));
683: if (!b->ncpstarted) {
684: Log(LG_BUND, ("[%s] Bundle: No NCPs left. Closing links...", b->name));
685: RecordLinkUpDownReason(b, NULL, 0, STR_PROTO_ERR, NULL);
686: BundCloseLinks(b); /* We have nothing to live for */
687: }
688: }
689:
690: void
691: BundNcpsJoin(Bund b, int proto)
692: {
693: IfaceState iface = &b->iface;
694:
695: if (iface->dod) {
696: if (iface->ip_up) {
697: iface->ip_up = 0;
698: IfaceIpIfaceDown(b);
699: }
700: if (iface->ipv6_up) {
701: iface->ipv6_up = 0;
702: IfaceIpv6IfaceDown(b);
703: }
704: iface->dod = 0;
705: iface->up = 0;
706: IfaceDown(b);
707: }
708:
709: switch(proto) {
710: case NCP_IPCP:
711: if (!iface->ip_up) {
712: iface->ip_up = 1;
713: if (IfaceIpIfaceUp(b, 1)) {
714: iface->ip_up = 0;
715: return;
716: };
717: }
718: break;
719: case NCP_IPV6CP:
720: if (!iface->ipv6_up) {
721: iface->ipv6_up = 1;
722: if (IfaceIpv6IfaceUp(b, 1)) {
723: iface->ipv6_up = 0;
724: return;
725: };
726: }
727: break;
728: case NCP_NONE: /* Manual call by 'open iface' */
729: if (Enabled(&b->conf.options, BUND_CONF_IPCP) &&
730: !iface->ip_up) {
731: iface->ip_up = 1;
732: if (IfaceIpIfaceUp(b, 0)) {
733: iface->ip_up = 0;
734: return;
735: };
736: }
737: if (Enabled(&b->conf.options, BUND_CONF_IPV6CP) &&
738: !iface->ipv6_up) {
739: iface->ipv6_up = 1;
740: if (IfaceIpv6IfaceUp(b, 0)) {
741: iface->ipv6_up = 0;
742: return;
743: };
744: }
745: break;
746: }
747:
748: if (!iface->up) {
749: iface->up = 1;
750: if (proto == NCP_NONE) {
751: iface->dod = 1;
752: IfaceUp(b, 0);
753: } else {
754: IfaceUp(b, 1);
755: }
756: }
757: }
758:
759: void
760: BundNcpsLeave(Bund b, int proto)
761: {
762: IfaceState iface = &b->iface;
763: switch(proto) {
764: case NCP_IPCP:
765: if (iface->ip_up) {
766: iface->ip_up=0;
767: IfaceIpIfaceDown(b);
768: }
769: break;
770: case NCP_IPV6CP:
771: if (iface->ipv6_up) {
772: iface->ipv6_up=0;
773: IfaceIpv6IfaceDown(b);
774: }
775: break;
776: case NCP_NONE:
777: if (iface->ip_up) {
778: iface->ip_up=0;
779: IfaceIpIfaceDown(b);
780: }
781: if (iface->ipv6_up) {
782: iface->ipv6_up=0;
783: IfaceIpv6IfaceDown(b);
784: }
785: break;
786: }
787:
788: if ((iface->up) && (!iface->ip_up) && (!iface->ipv6_up)) {
789: iface->dod=0;
790: iface->up=0;
791: IfaceDown(b);
792: if (iface->open) {
793: if (Enabled(&b->conf.options, BUND_CONF_IPCP)) {
794: iface->ip_up=1;
795: if (IfaceIpIfaceUp(b, 0))
796: iface->ip_up = 0;
797: }
798: if (Enabled(&b->conf.options, BUND_CONF_IPV6CP)) {
799: iface->ipv6_up=1;
800: if (IfaceIpv6IfaceUp(b, 0))
801: iface->ipv6_up = 0;
802: }
803: if (iface->ip_up || iface->ipv6_up) {
804: iface->dod=1;
805: iface->up=1;
806: IfaceUp(b, 0);
807: }
808: }
809: }
810: }
811:
812: /*
813: * BundNcpsDown()
814: */
815:
816: static void
817: BundNcpsDown(Bund b)
818: {
819: if (Enabled(&b->conf.options, BUND_CONF_IPCP))
820: IpcpDown(b);
821: if (Enabled(&b->conf.options, BUND_CONF_IPV6CP))
822: Ipv6cpDown(b);
823: if (Enabled(&b->conf.options, BUND_CONF_COMPRESSION))
824: CcpDown(b);
825: if (Enabled(&b->conf.options, BUND_CONF_ENCRYPTION))
826: EcpDown(b);
827: }
828:
829: /*
830: * BundNcpsClose()
831: */
832:
833: void
834: BundNcpsClose(Bund b)
835: {
836: if (Enabled(&b->conf.options, BUND_CONF_IPCP))
837: IpcpClose(b);
838: if (Enabled(&b->conf.options, BUND_CONF_IPV6CP))
839: Ipv6cpClose(b);
840: if (Enabled(&b->conf.options, BUND_CONF_COMPRESSION))
841: CcpClose(b);
842: if (Enabled(&b->conf.options, BUND_CONF_ENCRYPTION))
843: EcpClose(b);
844: }
845:
846: /*
847: * BundReasses()
848: *
849: * Here we do a reassessment of things after a new link has been
850: * added to or removed from the bundle.
851: */
852:
853: static void
854: BundReasses(Bund b)
855: {
856: BundBm const bm = &b->bm;
857:
858: /* Update system interface parameters */
859: BundUpdateParams(b);
860:
861: Log(LG_BUND, ("[%s] Bundle: Status update: up %d link%s, total bandwidth %d bps",
862: b->name, b->n_up, b->n_up == 1 ? "" : "s", bm->total_bw));
863:
864: }
865:
866: /*
867: * BundUpdateParams()
868: *
869: * Recalculate interface MTU and bandwidth.
870: */
871:
872: void
873: BundUpdateParams(Bund b)
874: {
875: BundBm const bm = &b->bm;
876: int k, mtu, the_link = 0;
877:
878: /* Recalculate how much bandwidth we have */
879: bm->total_bw = 0;
880: for (k = 0; k < NG_PPP_MAX_LINKS; k++) {
881: if (b->links[k] && b->links[k]->lcp.phase == PHASE_NETWORK) {
882: bm->total_bw += b->links[k]->bandwidth;
883: the_link = k;
884: }
885: }
886: if (bm->total_bw < BUND_MIN_TOT_BW)
887: bm->total_bw = BUND_MIN_TOT_BW;
888:
889: /* Recalculate MTU corresponding to peer's MRU */
890: if (b->n_up == 0) {
891: mtu = NG_IFACE_MTU_DEFAULT; /* Reset to default settings */
892:
893: } else if (!b->peer_mrru) { /* If no multilink, use peer MRU */
894: mtu = MIN(b->links[the_link]->lcp.peer_mru,
1.1.1.3 misho 895: PhysGetMtu(b->links[the_link], 0));
1.1 misho 896:
897: } else { /* Multilink, use peer MRRU */
898: mtu = MIN(b->peer_mrru, MP_MAX_MRRU);
899: }
900:
901: /* Subtract to make room for various frame-bloating protocols */
902: if (b->n_up > 0) {
1.1.1.5.2.1! misho 903: if (Enabled(&b->conf.options, BUND_CONF_COMPRESSION) &&
! 904: b->pppConfig.bund.enableCompression)
1.1 misho 905: mtu = CcpSubtractBloat(b, mtu);
1.1.1.5.2.1! misho 906: if (Enabled(&b->conf.options, BUND_CONF_ENCRYPTION) &&
! 907: b->pppConfig.bund.enableEncryption)
1.1 misho 908: mtu = EcpSubtractBloat(b, mtu);
909: }
910:
911: /* Update interface MTU */
912: IfaceSetMTU(b, mtu);
913:
914: }
915:
916: /*
917: * BundCommand()
918: *
919: * Show list of all bundles or set bundle
920: */
921:
922: int
1.1.1.5 misho 923: BundCommand(Context ctx, int ac, const char *const av[], const void *arg)
1.1 misho 924: {
925: Bund sb;
926: int j, k;
927:
1.1.1.5 misho 928: (void)arg;
929:
1.1 misho 930: if (ac > 1)
931: return (-1);
932:
933: if (ac == 0) {
934: Printf("Defined bundles:\r\n");
935: for (k = 0; k < gNumBundles; k++) {
936: if ((sb = gBundles[k]) != NULL) {
937: Printf("\t%-15s", sb->name);
938: for (j = 0; j < NG_PPP_MAX_LINKS; j++) {
939: if (sb->links[j])
940: Printf("%s ", sb->links[j]->name);
941: }
942: Printf("\r\n");
943: }
944: }
945: return (0);
946: }
947:
948: if ((sb = BundFind(av[0])) == NULL) {
949: RESETREF(ctx->lnk, NULL);
950: RESETREF(ctx->bund, NULL);
951: RESETREF(ctx->rep, NULL);
952: Error("Bundle \"%s\" not defined.", av[0]);
953: }
954:
955: /* Change bundle, and link also if needed */
956: RESETREF(ctx->bund, sb);
957: if (ctx->lnk == NULL || ctx->lnk->bund != ctx->bund) {
958: RESETREF(ctx->lnk, ctx->bund->links[0]);
959: }
960: RESETREF(ctx->rep, NULL);
961: return(0);
962: }
963:
964: /*
965: * MSessionCommand()
966: */
967:
968: int
1.1.1.5 misho 969: MSessionCommand(Context ctx, int ac, const char *const av[], const void *arg)
1.1 misho 970: {
971: int k;
972:
1.1.1.5 misho 973: (void)arg;
974:
1.1 misho 975: if (ac > 1)
976: return (-1);
977:
978: if (ac == 0) {
979: Printf("Present msessions:\r\n");
980: for (k = 0; k < gNumBundles; k++) {
981: if (gBundles[k] && gBundles[k]->msession_id[0])
982: Printf("\t%s\r\n", gBundles[k]->msession_id);
983: }
984: return (0);
985: }
986:
987: /* Find bundle */
988: for (k = 0;
989: k < gNumBundles && (gBundles[k] == NULL ||
990: strcmp(gBundles[k]->msession_id, av[0]));
991: k++);
992: if (k == gNumBundles) {
993: /* Change default link and bundle */
994: RESETREF(ctx->lnk, NULL);
995: RESETREF(ctx->bund, NULL);
996: RESETREF(ctx->rep, NULL);
997: Error("msession \"%s\" is not found", av[0]);
998: }
999:
1000: /* Change default link and bundle */
1001: RESETREF(ctx->bund, gBundles[k]);
1002: if (ctx->lnk == NULL || ctx->lnk->bund != ctx->bund) {
1003: RESETREF(ctx->lnk, ctx->bund->links[0]);
1004: }
1005: RESETREF(ctx->rep, NULL);
1006:
1007: return(0);
1008: }
1009:
1010: /*
1011: * IfaceCommand()
1012: */
1013:
1014: int
1.1.1.5 misho 1015: IfaceCommand(Context ctx, int ac, const char *const av[], const void *arg)
1.1 misho 1016: {
1017: int k;
1018:
1.1.1.5 misho 1019: (void)arg;
1020:
1.1 misho 1021: if (ac > 1)
1022: return (-1);
1023:
1024: if (ac == 0) {
1025: Printf("Present ifaces:\r\n");
1026: for (k = 0; k < gNumBundles; k++) {
1027: if (gBundles[k] && gBundles[k]->iface.ifname[0])
1028: Printf("\t%s\t%s\r\n", gBundles[k]->iface.ifname, gBundles[k]->name);
1029: }
1030: return (0);
1031: }
1032:
1033: /* Find bundle */
1034: for (k = 0;
1035: k < gNumBundles && (gBundles[k] == NULL ||
1036: strcmp(gBundles[k]->iface.ifname, av[0]));
1037: k++);
1038: if (k == gNumBundles) {
1039: /* Change default link and bundle */
1040: RESETREF(ctx->lnk, NULL);
1041: RESETREF(ctx->bund, NULL);
1042: RESETREF(ctx->rep, NULL);
1043: Error("iface \"%s\" is not found", av[0]);
1044: }
1045:
1046: /* Change default link and bundle */
1047: RESETREF(ctx->bund, gBundles[k]);
1048: if (ctx->lnk == NULL || ctx->lnk->bund != ctx->bund) {
1049: RESETREF(ctx->lnk, ctx->bund->links[0]);
1050: }
1051: RESETREF(ctx->rep, NULL);
1052:
1053: return(0);
1054: }
1055:
1056: /*
1057: * BundCreate()
1058: */
1059:
1060: int
1.1.1.5 misho 1061: BundCreate(Context ctx, int ac, const char *const av[], const void *arg)
1.1 misho 1062: {
1063: Bund b, bt = NULL;
1064: u_char tmpl = 0;
1065: u_char stay = 0;
1066: int k;
1067:
1.1.1.5 misho 1068: (void)arg;
1069:
1.1 misho 1070: RESETREF(ctx->lnk, NULL);
1071: RESETREF(ctx->bund, NULL);
1072: RESETREF(ctx->rep, NULL);
1073:
1074: if (ac < 1)
1075: return(-1);
1076:
1077: if (strcmp(av[0], "template") == 0) {
1078: tmpl = 1;
1079: stay = 1;
1080: } else if (strcmp(av[0], "static") == 0)
1081: stay = 1;
1082:
1083: if (ac - stay < 1 || ac - stay > 2)
1084: return(-1);
1085:
1086: if (strlen(av[0 + stay]) >= (LINK_MAX_NAME - tmpl * (IFNUMLEN + 1)))
1087: Error("Bundle name \"%s\" is too long", av[0 + stay]);
1088:
1089: /* See if bundle name already taken */
1090: if ((b = BundFind(av[0 + stay])) != NULL)
1091: Error("Bundle \"%s\" already exists", av[0 + stay]);
1092:
1093: if (ac - stay == 2) {
1094: /* See if template name specified */
1095: if ((bt = BundFind(av[1 + stay])) == NULL)
1096: Error("Bundle template \"%s\" not found", av[1 + stay]);
1097: if (!bt->tmpl)
1098: Error("Bundle \"%s\" is not a template", av[1 + stay]);
1099: }
1100:
1101: if (bt) {
1102: b = BundInst(bt, av[0 + stay], tmpl, stay);
1103: } else {
1104: /* Create a new bundle structure */
1105: b = Malloc(MB_BUND, sizeof(*b));
1106: strlcpy(b->name, av[0 + stay], sizeof(b->name));
1107: b->tmpl = tmpl;
1108: b->stay = stay;
1109:
1110: /* Add bundle to the list of bundles and make it the current active bundle */
1111: for (k = 0; k < gNumBundles && gBundles[k] != NULL; k++);
1112: if (k == gNumBundles) /* add a new bundle pointer */
1113: LengthenArray(&gBundles, sizeof(*gBundles), &gNumBundles, MB_BUND);
1114:
1115: b->id = k;
1116: gBundles[k] = b;
1117: REF(b);
1118:
1119: /* Get message channel */
1120: MsgRegister(&b->msgs, BundMsg);
1121:
1122: /* Initialize bundle configuration */
1123: b->conf.retry_timeout = BUND_DEFAULT_RETRY;
1124: b->conf.bm_S = BUND_BM_DFL_S;
1125: b->conf.bm_Hi = BUND_BM_DFL_Hi;
1126: b->conf.bm_Lo = BUND_BM_DFL_Lo;
1127: b->conf.bm_Mc = BUND_BM_DFL_Mc;
1128: b->conf.bm_Md = BUND_BM_DFL_Md;
1129:
1130: Enable(&b->conf.options, BUND_CONF_IPCP);
1131: Disable(&b->conf.options, BUND_CONF_IPV6CP);
1132:
1133: Disable(&b->conf.options, BUND_CONF_BWMANAGE);
1134: Disable(&b->conf.options, BUND_CONF_COMPRESSION);
1135: Disable(&b->conf.options, BUND_CONF_ENCRYPTION);
1136: Disable(&b->conf.options, BUND_CONF_CRYPT_REQD);
1137:
1138: /* Init iface and NCP's */
1139: IfaceInit(b);
1140: IpcpInit(b);
1141: Ipv6cpInit(b);
1142: CcpInit(b);
1143: EcpInit(b);
1144:
1145: if (!tmpl) {
1146: /* Setup netgraph stuff */
1147: if (BundNgInit(b) < 0) {
1148: gBundles[b->id] = NULL;
1.1.1.2 misho 1149: IfaceDestroy(b);
1.1 misho 1150: Freee(b);
1151: Error("Bundle netgraph initialization failed");
1152: }
1153: }
1154: }
1155:
1156: RESETREF(ctx->bund, b);
1157:
1158: /* Done */
1159: return(0);
1160: }
1161:
1162: /*
1163: * BundDestroy()
1164: */
1165:
1166: int
1.1.1.5 misho 1167: BundDestroy(Context ctx, int ac, const char *const av[], const void *arg)
1.1 misho 1168: {
1169: Bund b;
1170:
1.1.1.5 misho 1171: (void)arg;
1172:
1.1 misho 1173: if (ac > 1)
1174: return(-1);
1175:
1176: if (ac == 1) {
1177: if ((b = BundFind(av[0])) == NULL)
1178: Error("Bund \"%s\" not found", av[0]);
1179: } else {
1180: if (ctx->bund) {
1181: b = ctx->bund;
1182: } else
1183: Error("No bundle selected to destroy");
1184: }
1185:
1186: if (b->tmpl) {
1187: b->tmpl = 0;
1188: b->stay = 0;
1189: BundShutdown(b);
1190: } else {
1191: b->stay = 0;
1192: if (b->n_up) {
1193: BundClose(b);
1194: } else {
1195: BundShutdown(b);
1196: }
1197: }
1198:
1199: return (0);
1200: }
1201:
1202: /*
1203: * BundInst()
1204: */
1205:
1206: Bund
1.1.1.5 misho 1207: BundInst(Bund bt, const char *name, int tmpl, int stay)
1.1 misho 1208: {
1209: Bund b;
1210: int k;
1211:
1212: /* Create a new bundle structure */
1213: b = Mdup(MB_BUND, bt, sizeof(*b));
1214: b->tmpl = tmpl;
1215: b->stay = stay;
1216: b->refs = 0;
1217:
1218: /* Add bundle to the list of bundles and make it the current active bundle */
1219: for (k = 0; k < gNumBundles && gBundles[k] != NULL; k++);
1220: if (k == gNumBundles) /* add a new bundle pointer */
1221: LengthenArray(&gBundles, sizeof(*gBundles), &gNumBundles, MB_BUND);
1222:
1223: b->id = k;
1224: if (name)
1225: strlcpy(b->name, name, sizeof(b->name));
1226: else
1227: snprintf(b->name, sizeof(b->name), "%s-%d", bt->name, k);
1228: gBundles[k] = b;
1229: REF(b);
1230:
1231: /* Inst iface and NCP's */
1232: IfaceInst(b, bt);
1233: IpcpInst(b, bt);
1234: Ipv6cpInst(b, bt);
1235: CcpInst(b, bt);
1236: EcpInst(b, bt);
1237:
1238: if (!tmpl) {
1239: /* Setup netgraph stuff */
1240: if (BundNgInit(b) < 0) {
1241: Log(LG_ERR, ("[%s] Bundle netgraph initialization failed", b->name));
1242: gBundles[b->id] = NULL;
1243: Freee(b);
1244: return(0);
1245: }
1246: }
1247:
1248: return (b);
1249: }
1250:
1251: /*
1252: * BundShutdown()
1253: *
1254: * Shutdown the netgraph stuff associated with bundle
1255: */
1256:
1257: void
1258: BundShutdown(Bund b)
1259: {
1260: Link l;
1261: int k;
1262:
1263: Log(LG_BUND, ("[%s] Bundle: Shutdown", b->name));
1264: for (k = 0; k < NG_PPP_MAX_LINKS; k++) {
1265: if ((l = b->links[k]) != NULL) {
1266: if (!l->stay)
1267: LinkShutdown(l);
1268: else {
1269: l->bund = NULL;
1270: b->links[k] = NULL;
1271: }
1272: }
1273: }
1274:
1275: if (b->hook[0])
1276: BundNgShutdown(b, 1, 1);
1277: gBundles[b->id] = NULL;
1278: MsgUnRegister(&b->msgs);
1279: b->dead = 1;
1280: IfaceDestroy(b);
1281: UNREF(b);
1282: }
1283:
1284: /*
1285: * BundStat()
1286: *
1287: * Show state of a bundle
1288: */
1289:
1290: int
1.1.1.5 misho 1291: BundStat(Context ctx, int ac, const char *const av[], const void *arg)
1.1 misho 1292: {
1293: Bund sb;
1294: int k, bw, tbw, nup;
1295: char buf[64];
1296:
1.1.1.5 misho 1297: (void)arg;
1298:
1.1 misho 1299: /* Find bundle they're talking about */
1300: switch (ac) {
1301: case 0:
1302: sb = ctx->bund;
1303: break;
1304: case 1:
1305: if ((sb = BundFind(av[0])) == NULL)
1306: Error("Bundle \"%s\" not defined", av[0]);
1307: break;
1308: default:
1309: return(-1);
1310: }
1311:
1312: /* Show stuff about the bundle */
1313: for (tbw = bw = nup = k = 0; k < NG_PPP_MAX_LINKS; k++) {
1314: if (sb->links[k]) {
1315: if (sb->links[k]->lcp.phase == PHASE_NETWORK) {
1316: nup++;
1317: bw += sb->links[k]->bandwidth;
1318: }
1319: tbw += sb->links[k]->bandwidth;
1320: }
1321: }
1322:
1323: Printf("Bundle '%s'%s:\r\n", sb->name, sb->tmpl?" (template)":(sb->stay?" (static)":""));
1324: Printf("\tLinks : ");
1325: BundShowLinks(ctx, sb);
1326: Printf("\tStatus : %s\r\n", sb->open ? "OPEN" : "CLOSED");
1327: if (sb->n_up)
1328: Printf("\tSession time : %ld seconds\r\n", (long int)(time(NULL) - sb->last_up));
1329: Printf("\tMultiSession Id: %s\r\n", sb->msession_id);
1330: Printf("\tTotal bandwidth: %u bits/sec\r\n", tbw);
1331: Printf("\tAvail bandwidth: %u bits/sec\r\n", bw);
1332: Printf("\tPeer authname : \"%s\"\r\n", sb->params.authname);
1333:
1334: /* Show configuration */
1335: Printf("Configuration:\r\n");
1.1.1.2 misho 1336: #ifdef SIOCSIFDESCR
1337: Printf("\tDesc. template : %s\r\n",
1338: sb->iface.conf.ifdescr ? sb->iface.conf.ifdescr : "<none>");
1339: Printf("\tDescription : %s\r\n",
1340: sb->iface.ifdescr ? sb->iface.ifdescr : "<none>");
1341: #endif
1.1 misho 1342: Printf("\tRetry timeout : %d seconds\r\n", sb->conf.retry_timeout);
1343: Printf("\tBW-manage:\r\n");
1344: Printf("\t Period : %d seconds\r\n", sb->conf.bm_S);
1345: Printf("\t Low mark : %d%%\r\n", sb->conf.bm_Lo);
1346: Printf("\t High mark : %d%%\r\n", sb->conf.bm_Hi);
1347: Printf("\t Min conn : %d seconds\r\n", sb->conf.bm_Mc);
1348: Printf("\t Min disc : %d seconds\r\n", sb->conf.bm_Md);
1349: Printf("\t Links : ");
1350: for (k = 0; k < NG_PPP_MAX_LINKS; k++)
1351: Printf("%s ", sb->conf.linkst[k]);
1352: Printf("\r\n");
1353: Printf("Bundle level options:\r\n");
1354: OptStat(ctx, &sb->conf.options, gConfList);
1355:
1356: /* Show peer info */
1357: Printf("Multilink PPP:\r\n");
1358: Printf("\tStatus : %s\r\n",
1359: sb->peer_mrru ? "Active" : "Inactive");
1360: if (sb->peer_mrru) {
1361: Printf("\tPeer MRRU : %d bytes\r\n", sb->peer_mrru);
1362: Printf("\tPeer auth name : \"%s\"\r\n", sb->params.authname);
1363: Printf("\tPeer discrimin.: %s\r\n", MpDiscrimText(&sb->peer_discrim, buf, sizeof(buf)));
1364: }
1365:
1366: if (!sb->tmpl) {
1367: /* Show stats */
1368: BundUpdateStats(sb);
1369: Printf("Traffic stats:\r\n");
1370:
1371: Printf("\tInput octets : %llu\r\n", (unsigned long long)sb->stats.recvOctets);
1372: Printf("\tInput frames : %llu\r\n", (unsigned long long)sb->stats.recvFrames);
1373: Printf("\tOutput octets : %llu\r\n", (unsigned long long)sb->stats.xmitOctets);
1374: Printf("\tOutput frames : %llu\r\n", (unsigned long long)sb->stats.xmitFrames);
1375: Printf("\tBad protocols : %llu\r\n", (unsigned long long)sb->stats.badProtos);
1376: Printf("\tRunts : %llu\r\n", (unsigned long long)sb->stats.runts);
1377: Printf("\tDup fragments : %llu\r\n", (unsigned long long)sb->stats.dupFragments);
1378: Printf("\tDrop fragments : %llu\r\n", (unsigned long long)sb->stats.dropFragments);
1379: }
1380:
1381: return(0);
1382: }
1383:
1384: /*
1385: * BundUpdateStats()
1386: */
1387:
1388: void
1389: BundUpdateStats(Bund b)
1390: {
1391: #ifndef NG_PPP_STATS64
1392: struct ng_ppp_link_stat stats;
1393: #endif
1394: int l = NG_PPP_BUNDLE_LINKNUM;
1395:
1396: #if (__FreeBSD_version < 602104 || (__FreeBSD_version >= 700000 && __FreeBSD_version < 700029))
1397: /* Workaround for broken ng_ppp bundle stats */
1398: if (!b->peer_mrru)
1399: l = 0;
1400: #endif
1401:
1402: #ifndef NG_PPP_STATS64
1403: if (NgFuncGetStats(b, l, &stats) != -1) {
1404: b->stats.xmitFrames += abs(stats.xmitFrames - b->oldStats.xmitFrames);
1405: b->stats.xmitOctets += abs(stats.xmitOctets - b->oldStats.xmitOctets);
1406: b->stats.recvFrames += abs(stats.recvFrames - b->oldStats.recvFrames);
1407: b->stats.recvOctets += abs(stats.recvOctets - b->oldStats.recvOctets);
1408: b->stats.badProtos += abs(stats.badProtos - b->oldStats.badProtos);
1409: b->stats.runts += abs(stats.runts - b->oldStats.runts);
1410: b->stats.dupFragments += abs(stats.dupFragments - b->oldStats.dupFragments);
1411: b->stats.dropFragments += abs(stats.dropFragments - b->oldStats.dropFragments);
1.1.1.4 misho 1412: b->oldStats = stats;
1.1 misho 1413: }
1414:
1415: #else
1416: NgFuncGetStats64(b, l, &b->stats);
1417: #endif
1418: }
1419:
1420: /*
1421: * BundUpdateStatsTimer()
1422: */
1423:
1424: void
1425: BundUpdateStatsTimer(void *cookie)
1426: {
1427: Bund b = (Bund)cookie;
1428: int k;
1429:
1430: BundUpdateStats(b);
1431: for (k = 0; k < NG_PPP_MAX_LINKS; k++) {
1432: if (b->links[k] && b->links[k]->joined_bund)
1433: LinkUpdateStats(b->links[k]);
1434: }
1435: }
1436:
1437: /*
1438: * BundResetStats()
1439: */
1440:
1441: void
1442: BundResetStats(Bund b)
1443: {
1444: NgFuncClrStats(b, NG_PPP_BUNDLE_LINKNUM);
1445: memset(&b->stats, 0, sizeof(b->stats));
1446: #ifndef NG_PPP_STATS64
1447: memset(&b->oldStats, 0, sizeof(b->oldStats));
1448: #endif
1449: }
1450:
1451: /*
1452: * BundShowLinks()
1453: */
1454:
1455: void
1456: BundShowLinks(Context ctx, Bund sb)
1457: {
1458: int j;
1459:
1460: for (j = 0; j < NG_PPP_MAX_LINKS; j++) {
1461: if (sb->links[j]) {
1462: Printf("%s[%s/%s] ", sb->links[j]->name,
1463: FsmStateName(sb->links[j]->lcp.fsm.state),
1464: gPhysStateNames[sb->links[j]->state]);
1465: }
1466: }
1467: Printf("\r\n");
1468: }
1469:
1470: /*
1471: * BundFind()
1472: *
1473: * Find a bundle structure
1474: */
1475:
1476: Bund
1477: BundFind(const char *name)
1478: {
1479: int k;
1480:
1481: for (k = 0;
1482: k < gNumBundles && (!gBundles[k] || strcmp(gBundles[k]->name, name));
1483: k++);
1484: return((k < gNumBundles) ? gBundles[k] : NULL);
1485: }
1486:
1487: /*
1488: * BundBmStart()
1489: *
1490: * Start bandwidth management timer
1491: */
1492:
1493: static void
1494: BundBmStart(Bund b)
1495: {
1496: int k;
1497:
1498: /* Reset bandwidth management stats */
1499: memset(&b->bm.traffic, 0, sizeof(b->bm.traffic));
1500: memset(&b->bm.avail, 0, sizeof(b->bm.avail));
1501: memset(&b->bm.wasUp, 0, sizeof(b->bm.wasUp));
1502: for (k = 0; k < NG_PPP_MAX_LINKS; k++) {
1503: if (b->links[k]) {
1504: memset(&b->links[k]->bm.idleStats,
1505: 0, sizeof(b->links[k]->bm.idleStats));
1506: }
1507: }
1508:
1509: /* Start bandwidth management timer */
1510: TimerStop(&b->bm.bmTimer);
1511: if (Enabled(&b->conf.options, BUND_CONF_BWMANAGE)) {
1512: TimerInit(&b->bm.bmTimer, "BundBm",
1513: (b->conf.bm_S * SECONDS) / BUND_BM_N,
1514: BundBmTimeout, b);
1515: TimerStart(&b->bm.bmTimer);
1516: }
1517: }
1518:
1519: /*
1520: * BundBmStop()
1521: */
1522:
1523: static void
1524: BundBmStop(Bund b)
1525: {
1526: TimerStop(&b->bm.bmTimer);
1527: }
1528:
1529: /*
1530: * BundBmTimeout()
1531: *
1532: * Do a bandwidth management update
1533: */
1534:
1535: static void
1536: BundBmTimeout(void *arg)
1537: {
1538: Bund b = (Bund)arg;
1539:
1540: const time_t now = time(NULL);
1541: u_int availTotal;
1542: u_int inUtilTotal = 0, outUtilTotal = 0;
1543: u_int inBitsTotal, outBitsTotal;
1544: u_int inUtil[BUND_BM_N]; /* Incoming % utilization */
1545: u_int outUtil[BUND_BM_N]; /* Outgoing % utilization */
1546: int j, k;
1547:
1548: /* Shift and update stats */
1549: memmove(&b->bm.wasUp[1], &b->bm.wasUp[0],
1550: (BUND_BM_N - 1) * sizeof(b->bm.wasUp[0]));
1551: b->bm.wasUp[0] = b->n_up;
1552: memmove(&b->bm.avail[1], &b->bm.avail[0],
1553: (BUND_BM_N - 1) * sizeof(b->bm.avail[0]));
1554: b->bm.avail[0] = b->bm.total_bw;
1555:
1556: /* Shift stats */
1557: memmove(&b->bm.traffic[0][1], &b->bm.traffic[0][0],
1558: (BUND_BM_N - 1) * sizeof(b->bm.traffic[0][0]));
1559: memmove(&b->bm.traffic[1][1], &b->bm.traffic[1][0],
1560: (BUND_BM_N - 1) * sizeof(b->bm.traffic[1][0]));
1561: b->bm.traffic[0][0] = 0;
1562: b->bm.traffic[1][0] = 0;
1563: for (k = 0; k < NG_PPP_MAX_LINKS; k++) {
1564: if (b->links[k] && b->links[k]->joined_bund) {
1565: Link const l = b->links[k];
1566:
1.1.1.5 misho 1567: #ifndef NG_PPP_STATS64
1.1 misho 1568: struct ng_ppp_link_stat oldStats;
1.1.1.5 misho 1569: #else
1570: struct ng_ppp_link_stat64 oldStats;
1571: #endif
1.1 misho 1572:
1573: /* Get updated link traffic statistics */
1574: oldStats = l->bm.idleStats;
1.1.1.5 misho 1575: #ifndef NG_PPP_STATS64
1.1 misho 1576: NgFuncGetStats(l->bund, l->bundleIndex, &l->bm.idleStats);
1.1.1.5 misho 1577: #else
1578: NgFuncGetStats64(l->bund, l->bundleIndex, &l->bm.idleStats);
1579: #endif
1.1 misho 1580: b->bm.traffic[0][0] += l->bm.idleStats.recvOctets - oldStats.recvOctets;
1581: b->bm.traffic[1][0] += l->bm.idleStats.xmitOctets - oldStats.xmitOctets;
1582: }
1583: }
1584:
1585: /* Compute utilizations */
1586: memset(&inUtil, 0, sizeof(inUtil));
1587: memset(&outUtil, 0, sizeof(outUtil));
1588: availTotal = inBitsTotal = outBitsTotal = 0;
1589: for (j = 0; j < BUND_BM_N; j++) {
1590: u_int avail, inBits, outBits;
1591:
1592: avail = (b->bm.avail[j] * b->conf.bm_S) / BUND_BM_N;
1593: inBits = b->bm.traffic[0][j] * 8;
1594: outBits = b->bm.traffic[1][j] * 8;
1595:
1596: availTotal += avail;
1597: inBitsTotal += inBits;
1598: outBitsTotal += outBits;
1599:
1600: /* Compute bandwidth utilizations as percentages */
1601: if (avail != 0) {
1602: inUtil[j] = ((float) inBits / avail) * 100;
1603: outUtil[j] = ((float) outBits / avail) * 100;
1604: }
1605: }
1606:
1607: /* Compute total averaged utilization */
1608: if (availTotal != 0) {
1609: inUtilTotal = ((float) inBitsTotal / availTotal) * 100;
1610: outUtilTotal = ((float) outBitsTotal / availTotal) * 100;
1611: }
1612:
1613: {
1614: char ins[100], outs[100];
1615:
1616: ins[0] = 0;
1617: for (j = 0; j < BUND_BM_N; j++) {
1618: snprintf(ins + strlen(ins), sizeof(ins) - strlen(ins),
1619: " %3u ", b->bm.wasUp[BUND_BM_N - 1 - j]);
1620: }
1621: Log(LG_BUND2, ("[%s] %s", b->name, ins));
1622:
1623: snprintf(ins, sizeof(ins), " IN util: total %3u%% ", inUtilTotal);
1624: snprintf(outs, sizeof(outs), "OUT util: total %3u%% ", outUtilTotal);
1625: for (j = 0; j < BUND_BM_N; j++) {
1626: snprintf(ins + strlen(ins), sizeof(ins) - strlen(ins),
1627: " %3u%%", inUtil[BUND_BM_N - 1 - j]);
1628: snprintf(outs + strlen(outs), sizeof(outs) - strlen(outs),
1629: " %3u%%", outUtil[BUND_BM_N - 1 - j]);
1630: }
1631: Log(LG_BUND2, ("[%s] %s", b->name, ins));
1632: Log(LG_BUND2, ("[%s] %s", b->name, outs));
1633: }
1634:
1635: /* See if it's time to bring up another link */
1636: if (now - b->bm.last_open >= b->conf.bm_Mc
1637: && (inUtilTotal >= b->conf.bm_Hi || outUtilTotal >= b->conf.bm_Hi)) {
1638: for (k = 0; k < NG_PPP_MAX_LINKS; k++) {
1639: cont:
1640: if (!b->links[k] && b->conf.linkst[k][0])
1641: break;
1642: }
1643: if (k < NG_PPP_MAX_LINKS) {
1644: Log(LG_BUND, ("[%s] opening link \"%s\" due to increased demand",
1645: b->name, b->conf.linkst[k]));
1646: b->bm.last_open = now;
1647: if (b->links[k]) {
1648: RecordLinkUpDownReason(NULL, b->links[k], 1, STR_PORT_NEEDED, NULL);
1649: BundOpenLink(b->links[k]);
1650: } else {
1651: if (BundCreateOpenLink(b, k)) {
1652: if (k < NG_PPP_MAX_LINKS) {
1653: k++;
1654: goto cont;
1655: }
1656: } else
1657: RecordLinkUpDownReason(NULL, b->links[k], 1, STR_PORT_NEEDED, NULL);
1658: }
1659: }
1660: }
1661:
1662: /* See if it's time to bring down a link */
1663: if (now - b->bm.last_close >= b->conf.bm_Md
1664: && (inUtilTotal < b->conf.bm_Lo && outUtilTotal < b->conf.bm_Lo)
1665: && b->n_links > 1) {
1666: k = NG_PPP_MAX_LINKS - 1;
1667: while (k >= 0 && (!b->links[k] || !OPEN_STATE(b->links[k]->lcp.fsm.state)))
1668: k--;
1669: assert(k >= 0);
1670: Log(LG_BUND, ("[%s] Bundle: closing link %s due to reduced demand",
1671: b->name, b->links[k]->name));
1672: b->bm.last_close = now;
1673: RecordLinkUpDownReason(NULL, b->links[k], 0, STR_PORT_UNNEEDED, NULL);
1674: BundCloseLink(b->links[k]);
1675: }
1676:
1677: /* Restart timer */
1678: TimerStart(&b->bm.bmTimer);
1679: }
1680:
1681: /*
1682: * BundNgInit()
1683: *
1684: * Setup the initial PPP netgraph framework. Initializes these fields
1685: * in the supplied bundle structure:
1686: *
1687: * iface.ifname - Interface name
1688: * csock - Control socket for socket netgraph node
1689: * dsock - Data socket for socket netgraph node
1690: *
1691: * Returns -1 if error.
1692: */
1693:
1694: static int
1695: BundNgInit(Bund b)
1696: {
1697: struct ngm_mkpeer mp;
1698: struct ngm_name nm;
1699: int newIface = 0;
1700: int newPpp = 0;
1701:
1702: /* Create new iface node */
1703: if (NgFuncCreateIface(b,
1704: b->iface.ifname, sizeof(b->iface.ifname)) < 0) {
1705: Log(LG_ERR, ("[%s] can't create netgraph interface", b->name));
1706: goto fail;
1707: }
1708: strlcpy(b->iface.ngname, b->iface.ifname, sizeof(b->iface.ngname));
1709: newIface = 1;
1710: b->iface.ifindex = if_nametoindex(b->iface.ifname);
1711: Log(LG_BUND|LG_IFACE, ("[%s] Bundle: Interface %s created",
1712: b->name, b->iface.ifname));
1713:
1714: /* Create new PPP node */
1715: snprintf(b->hook, sizeof(b->hook), "b%d", b->id);
1716: memset(&mp, 0, sizeof(mp));
1717: strcpy(mp.type, NG_PPP_NODE_TYPE);
1718: strcpy(mp.ourhook, b->hook);
1719: strcpy(mp.peerhook, NG_PPP_HOOK_BYPASS);
1720: if (NgSendMsg(gLinksCsock, ".:",
1721: NGM_GENERIC_COOKIE, NGM_MKPEER, &mp, sizeof(mp)) < 0) {
1722: Perror("[%s] can't create %s node at \"%s\"->\"%s\"",
1723: b->name, mp.type, ".:", mp.ourhook);
1724: goto fail;
1725: }
1726: newPpp = 1;
1727:
1728: /* Get PPP node ID */
1.1.1.5 misho 1729: if ((b->nodeID = NgGetNodeID(gLinksCsock, b->hook)) == 0) {
1730: Perror("[%s] Cannot get %s node id", b->name, NG_PPP_NODE_TYPE);
1731: goto fail;
1732: }
1.1 misho 1733:
1734: /* Give it a name */
1735: memset(&nm, 0, sizeof(nm));
1736: snprintf(nm.name, sizeof(nm.name), "mpd%d-%s", gPid, b->name);
1737: if (NgSendMsg(gLinksCsock, b->hook,
1738: NGM_GENERIC_COOKIE, NGM_NAME, &nm, sizeof(nm)) < 0) {
1739: Perror("[%s] can't name %s node \"%s\"",
1740: b->name, NG_PPP_NODE_TYPE, b->hook);
1741: goto fail;
1742: }
1743:
1744: /* OK */
1745: return(0);
1746:
1747: fail:
1748: BundNgShutdown(b, newIface, newPpp);
1749: return(-1);
1750: }
1751:
1752: /*
1753: * NgFuncShutdown()
1754: */
1755:
1756: void
1757: BundNgShutdown(Bund b, int iface, int ppp)
1758: {
1759: char path[NG_PATHSIZ];
1760:
1761: if (iface) {
1762: snprintf(path, sizeof(path), "%s:", b->iface.ngname);
1763: NgFuncShutdownNode(gLinksCsock, b->name, path);
1764: }
1765: if (ppp) {
1766: snprintf(path, sizeof(path), "[%x]:", b->nodeID);
1767: NgFuncShutdownNode(gLinksCsock, b->name, path);
1768: }
1769: b->hook[0] = 0;
1770: }
1771:
1772: /*
1773: * BundSetCommand()
1774: */
1775:
1776: static int
1.1.1.5 misho 1777: BundSetCommand(Context ctx, int ac, const char *const av[], const void *arg)
1.1 misho 1778: {
1779: Bund b = ctx->bund;
1780: int i, val;
1781:
1782: if (ac == 0)
1783: return(-1);
1784: switch ((intptr_t)arg) {
1785: case SET_PERIOD:
1786: b->conf.bm_S = atoi(*av);
1787: break;
1788: case SET_LOW_WATER:
1789: b->conf.bm_Lo = atoi(*av);
1790: break;
1791: case SET_HIGH_WATER:
1792: b->conf.bm_Hi = atoi(*av);
1793: break;
1794: case SET_MIN_CONNECT:
1795: b->conf.bm_Mc = atoi(*av);
1796: break;
1797: case SET_MIN_DISCONNECT:
1798: b->conf.bm_Md = atoi(*av);
1799: break;
1800: case SET_LINKS:
1801: if (ac > NG_PPP_MAX_LINKS)
1802: return (-1);
1803: for (i = 0; i < ac; i++)
1804: strlcpy(b->conf.linkst[i], av[i], LINK_MAX_NAME);
1805: for (; i < NG_PPP_MAX_LINKS; i++)
1806: b->conf.linkst[i][0] = 0;
1807: break;
1808:
1809: case SET_RETRY:
1810: val = atoi(*av);
1811: if (val < 1 || val > 10)
1812: Error("[%s] incorrect fsm-timeout value %d", b->name, val);
1813: else
1814: b->conf.retry_timeout = val;
1815: break;
1816:
1817: case SET_ACCEPT:
1818: AcceptCommand(ac, av, &b->conf.options, gConfList);
1819: break;
1820:
1821: case SET_DENY:
1822: DenyCommand(ac, av, &b->conf.options, gConfList);
1823: break;
1824:
1825: case SET_ENABLE:
1826: EnableCommand(ac, av, &b->conf.options, gConfList);
1827: break;
1828:
1829: case SET_DISABLE:
1830: DisableCommand(ac, av, &b->conf.options, gConfList);
1831: break;
1832:
1833: case SET_YES:
1834: YesCommand(ac, av, &b->conf.options, gConfList);
1835: break;
1836:
1837: case SET_NO:
1838: NoCommand(ac, av, &b->conf.options, gConfList);
1839: break;
1840:
1841: default:
1842: assert(0);
1843: }
1844: return(0);
1845: }
1846:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>