Lines Matching +full:lower +full:- +full:case
1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
4 * Copyright (c) 2004-2010 University of Zagreb
5 * Copyright (c) 2007-2008 FreeBSD Foundation
36 * The node has two hooks, upper and lower. Traffic flowing from upper to
37 * lower hook is referenced as downstream, and vice versa. Parameters for
101 struct hookinfo lower;
110 if (hinfo->cfg.wfq && hinfo->cfg.bandwidth) { \
111 ngp_f->vtime.tv_usec = now->tv_usec + ((uint64_t) (plen) \
112 + priv->overhead ) * hinfo->run.fifo_queues * \
113 8000000 / hinfo->cfg.bandwidth; \
114 ngp_f->vtime.tv_sec = now->tv_sec + \
115 ngp_f->vtime.tv_usec / 1000000; \
116 ngp_f->vtime.tv_usec = ngp_f->vtime.tv_usec % 1000000; \
117 TAILQ_FOREACH(ngp_f1, &hinfo->fifo_head, fifo_le) \
118 if (ngp_f1->vtime.tv_sec > ngp_f->vtime.tv_sec || \
119 (ngp_f1->vtime.tv_sec == ngp_f->vtime.tv_sec && \
120 ngp_f1->vtime.tv_usec > ngp_f->vtime.tv_usec)) \
123 TAILQ_INSERT_TAIL(&hinfo->fifo_head, ngp_f, fifo_le); \
127 TAILQ_INSERT_TAIL(&hinfo->fifo_head, ngp_f, fifo_le); \
135 /* zone for storing ngp_hdr-s */
258 /* Mark node as single-threaded */
261 ng_callout_init(&priv->timer);
274 bzero(&priv->upper, sizeof(priv->upper));
275 priv->upper.hook = hook;
276 NG_HOOK_SET_PRIVATE(hook, &priv->upper);
278 bzero(&priv->lower, sizeof(priv->lower));
279 priv->lower.hook = hook;
280 NG_HOOK_SET_PRIVATE(hook, &priv->lower);
284 /* Load non-zero initial cfg values */
286 hinfo->cfg.qin_size_limit = 50;
287 hinfo->cfg.fifo = 1;
288 hinfo->cfg.droptail = 1;
289 TAILQ_INIT(&hinfo->fifo_head);
290 TAILQ_INIT(&hinfo->qout_head);
308 switch (msg->header.typecookie) {
309 case NGM_PIPE_COOKIE:
310 switch (msg->header.cmd) {
311 case NGM_PIPE_GET_STATS:
312 case NGM_PIPE_CLR_STATS:
313 case NGM_PIPE_GETCLR_STATS:
314 if (msg->header.cmd != NGM_PIPE_CLR_STATS) {
321 stats = (struct ng_pipe_stats *) resp->data;
322 bcopy(&priv->upper.stats, &stats->downstream,
323 sizeof(stats->downstream));
324 bcopy(&priv->lower.stats, &stats->upstream,
325 sizeof(stats->upstream));
327 if (msg->header.cmd != NGM_PIPE_GET_STATS) {
328 bzero(&priv->upper.stats,
329 sizeof(priv->upper.stats));
330 bzero(&priv->lower.stats,
331 sizeof(priv->lower.stats));
334 case NGM_PIPE_GET_RUN:
340 run = (struct ng_pipe_run *) resp->data;
341 bcopy(&priv->upper.run, &run->downstream,
342 sizeof(run->downstream));
343 bcopy(&priv->lower.run, &run->upstream,
344 sizeof(run->upstream));
346 case NGM_PIPE_GET_CFG:
352 cfg = (struct ng_pipe_cfg *) resp->data;
353 bcopy(&priv->upper.cfg, &cfg->downstream,
354 sizeof(cfg->downstream));
355 bcopy(&priv->lower.cfg, &cfg->upstream,
356 sizeof(cfg->upstream));
357 cfg->delay = priv->delay;
358 cfg->overhead = priv->overhead;
359 cfg->header_offset = priv->header_offset;
360 if (cfg->upstream.bandwidth ==
361 cfg->downstream.bandwidth) {
362 cfg->bandwidth = cfg->upstream.bandwidth;
363 cfg->upstream.bandwidth = 0;
364 cfg->downstream.bandwidth = 0;
366 cfg->bandwidth = 0;
368 case NGM_PIPE_SET_CFG:
369 cfg = (struct ng_pipe_cfg *) msg->data;
370 if (msg->header.arglen != sizeof(*cfg)) {
375 if (cfg->delay == -1)
376 priv->delay = 0;
377 else if (cfg->delay > 0 && cfg->delay < 10000000)
378 priv->delay = cfg->delay;
380 if (cfg->bandwidth == -1) {
381 priv->upper.cfg.bandwidth = 0;
382 priv->lower.cfg.bandwidth = 0;
383 priv->overhead = 0;
384 } else if (cfg->bandwidth >= 100 &&
385 cfg->bandwidth <= 1000000000) {
386 priv->upper.cfg.bandwidth = cfg->bandwidth;
387 priv->lower.cfg.bandwidth = cfg->bandwidth;
388 if (cfg->bandwidth >= 10000000)
389 priv->overhead = 8+4+12; /* Ethernet */
391 priv->overhead = 10; /* HDLC */
394 if (cfg->overhead == -1)
395 priv->overhead = 0;
396 else if (cfg->overhead > 0 &&
397 cfg->overhead < MAX_OHSIZE)
398 priv->overhead = cfg->overhead;
400 if (cfg->header_offset == -1)
401 priv->header_offset = 0;
402 else if (cfg->header_offset > 0 &&
403 cfg->header_offset < 64)
404 priv->header_offset = cfg->header_offset;
406 prev_down = priv->upper.cfg.ber == 1 ||
407 priv->lower.cfg.ber == 1;
408 parse_cfg(&priv->upper.cfg, &cfg->downstream,
409 &priv->upper, priv);
410 parse_cfg(&priv->lower.cfg, &cfg->upstream,
411 &priv->lower, priv);
412 now_down = priv->upper.cfg.ber == 1 ||
413 priv->lower.cfg.ber == 1;
421 if (priv->lower.hook != NULL) {
426 flow_msg, priv->lower.hook,
429 if (priv->upper.hook != NULL) {
434 flow_msg, priv->upper.hook,
459 if (new->ber == -1) {
460 current->ber = 0;
461 if (hinfo->ber_p) {
462 free(hinfo->ber_p, M_NG_PIPE);
463 hinfo->ber_p = NULL;
465 } else if (new->ber >= 1 && new->ber <= 1000000000000) {
470 if (hinfo->ber_p == NULL)
471 hinfo->ber_p =
474 current->ber = new->ber;
480 * P_OK(BER,N) = (1 - 1/BER)^(N*8)
482 * We use a 64-bit fixed-point format with decimal point
485 p0 = one - one / new->ber;
488 hinfo->ber_p[fsize] = p;
496 if (new->qin_size_limit == -1)
497 current->qin_size_limit = 0;
498 else if (new->qin_size_limit >= 5)
499 current->qin_size_limit = new->qin_size_limit;
501 if (new->qout_size_limit == -1)
502 current->qout_size_limit = 0;
503 else if (new->qout_size_limit >= 5)
504 current->qout_size_limit = new->qout_size_limit;
506 if (new->duplicate == -1)
507 current->duplicate = 0;
508 else if (new->duplicate > 0 && new->duplicate <= 50)
509 current->duplicate = new->duplicate;
511 if (new->fifo) {
512 current->fifo = 1;
513 current->wfq = 0;
514 current->drr = 0;
517 if (new->wfq) {
518 current->fifo = 0;
519 current->wfq = 1;
520 current->drr = 0;
523 if (new->drr) {
524 current->fifo = 0;
525 current->wfq = 0;
527 if (new->drr >= 32)
528 current->drr = new->drr;
530 current->drr = 2048; /* default quantum */
533 if (new->droptail) {
534 current->droptail = 1;
535 current->drophead = 0;
538 if (new->drophead) {
539 current->droptail = 0;
540 current->drophead = 1;
543 if (new->bandwidth == -1) {
544 current->bandwidth = 0;
545 current->fifo = 1;
546 current->wfq = 0;
547 current->drr = 0;
548 } else if (new->bandwidth >= 100 && new->bandwidth <= 1000000000)
549 current->bandwidth = new->bandwidth;
551 if (current->bandwidth | priv->delay |
552 current->duplicate | current->ber)
553 hinfo->noqueue = 0;
555 hinfo->noqueue = 1;
569 if (m->m_len < sizeof(struct ip) + offset ||
570 ip->ip_v != 4 || ip->ip_hl << 2 != sizeof(struct ip))
573 i = ((u_int64_t) ip->ip_src.s_addr ^
574 ((u_int64_t) ip->ip_src.s_addr << 13) ^
575 ((u_int64_t) ip->ip_dst.s_addr << 7) ^
576 ((u_int64_t) ip->ip_dst.s_addr << 19));
581 * Receive data on a hook - both in upstream and downstream direction.
605 if (hinfo->run.qin_frames == 0 && hinfo->run.qout_frames == 0 &&
606 hinfo->noqueue) {
608 if (hinfo == &priv->lower)
609 dest = &priv->upper;
611 dest = &priv->lower;
614 plen = NGI_M(item)->m_pkthdr.len;
615 NG_FWD_ITEM_HOOK(error, item, dest->hook);
619 hinfo->stats.out_disc_frames++;
620 hinfo->stats.out_disc_octets += plen;
622 hinfo->stats.fwd_frames++;
623 hinfo->stats.fwd_octets += plen;
634 if (hinfo->run.qin_frames == 0) {
635 struct timeval *when = &hinfo->qin_utime;
636 if (when->tv_sec < now->tv_sec || (when->tv_sec == now->tv_sec
637 && when->tv_usec < now->tv_usec)) {
638 when->tv_sec = now->tv_sec;
639 when->tv_usec = now->tv_usec;
651 ngp_h->m = m;
653 if (hinfo->cfg.fifo)
656 hash = ip_hash(m, priv->header_offset);
659 TAILQ_FOREACH(ngp_f, &hinfo->fifo_head, fifo_le)
660 if (hash == ngp_f->hash)
665 NG_FREE_M(ngp_h->m);
669 TAILQ_INIT(&ngp_f->packet_head);
670 ngp_f->hash = hash;
671 ngp_f->packets = 1;
672 ngp_f->rr_deficit = hinfo->cfg.drr; /* DRR quantum */
673 hinfo->run.fifo_queues++;
674 TAILQ_INSERT_TAIL(&ngp_f->packet_head, ngp_h, ngp_link);
675 FIFO_VTIME_SORT(m->m_pkthdr.len);
677 TAILQ_INSERT_TAIL(&ngp_f->packet_head, ngp_h, ngp_link);
678 ngp_f->packets++;
680 hinfo->run.qin_frames++;
681 hinfo->run.qin_octets += m->m_pkthdr.len;
684 if (hinfo->run.qin_frames > hinfo->cfg.qin_size_limit) {
689 TAILQ_FOREACH(ngp_f1, &hinfo->fifo_head, fifo_le)
690 if (ngp_f1->packets > longest) {
691 longest = ngp_f1->packets;
696 if (hinfo->cfg.drophead)
697 ngp_h = TAILQ_FIRST(&ngp_f->packet_head);
699 ngp_h = TAILQ_LAST(&ngp_f->packet_head, p_head);
700 TAILQ_REMOVE(&ngp_f->packet_head, ngp_h, ngp_link);
701 m1 = ngp_h->m;
703 hinfo->run.qin_octets -= m1->m_pkthdr.len;
704 hinfo->stats.in_disc_octets += m1->m_pkthdr.len;
706 if (--(ngp_f->packets) == 0) {
707 TAILQ_REMOVE(&hinfo->fifo_head, ngp_f, fifo_le);
709 hinfo->run.fifo_queues--;
711 hinfo->run.qin_frames--;
712 hinfo->stats.in_disc_frames++;
724 * Dequeueing sequence - we basically do the following:
738 const node_p node = NG_HOOK_NODE(hinfo->hook);
748 if (hinfo == &priv->lower)
749 dest = &priv->upper;
751 dest = &priv->lower;
754 while ((ngp_f = TAILQ_FIRST(&hinfo->fifo_head))) {
755 when = &hinfo->qin_utime;
756 if (when->tv_sec > now->tv_sec || (when->tv_sec == now->tv_sec
757 && when->tv_usec > now->tv_usec))
760 ngp_h = TAILQ_FIRST(&ngp_f->packet_head);
761 m = ngp_h->m;
764 if (hinfo->cfg.drr) {
765 if (ngp_f->rr_deficit >= m->m_pkthdr.len) {
766 ngp_f->rr_deficit -= m->m_pkthdr.len;
768 ngp_f->rr_deficit += hinfo->cfg.drr;
769 TAILQ_REMOVE(&hinfo->fifo_head, ngp_f, fifo_le);
770 TAILQ_INSERT_TAIL(&hinfo->fifo_head,
783 if (hinfo->cfg.duplicate &&
784 prng32_bounded(100) <= hinfo->cfg.duplicate) {
787 ngp_dup->m = m_dup(m, M_NOWAIT);
788 if (ngp_dup->m == NULL) {
797 m = ngp_h->m;
799 TAILQ_REMOVE(&ngp_f->packet_head, ngp_h, ngp_link);
800 hinfo->run.qin_frames--;
801 hinfo->run.qin_octets -= m->m_pkthdr.len;
802 ngp_f->packets--;
806 if (hinfo->cfg.bandwidth) {
807 hinfo->qin_utime.tv_usec +=
808 ((uint64_t) m->m_pkthdr.len + priv->overhead ) *
809 8000000 / hinfo->cfg.bandwidth;
810 hinfo->qin_utime.tv_sec +=
811 hinfo->qin_utime.tv_usec / 1000000;
812 hinfo->qin_utime.tv_usec =
813 hinfo->qin_utime.tv_usec % 1000000;
815 when = &ngp_h->when;
816 when->tv_sec = hinfo->qin_utime.tv_sec;
817 when->tv_usec = hinfo->qin_utime.tv_usec;
820 if (ngp_f->packets) {
821 if (hinfo->cfg.wfq) {
822 TAILQ_REMOVE(&hinfo->fifo_head, ngp_f, fifo_le);
824 &ngp_f->packet_head)->m->m_pkthdr.len)
827 TAILQ_REMOVE(&hinfo->fifo_head, ngp_f, fifo_le);
829 hinfo->run.fifo_queues--;
833 if (hinfo->cfg.ber) {
837 hinfo->ber_p[priv->overhead + m->m_pkthdr.len]) {
838 hinfo->stats.out_disc_frames++;
839 hinfo->stats.out_disc_octets += m->m_pkthdr.len;
847 if (hinfo->cfg.qout_size_limit &&
848 hinfo->run.qout_frames>=hinfo->cfg.qout_size_limit) {
849 hinfo->stats.out_disc_frames++;
850 hinfo->stats.out_disc_octets += m->m_pkthdr.len;
857 when->tv_usec += priv->delay;
858 when->tv_sec += when->tv_usec / 1000000;
859 when->tv_usec = when->tv_usec % 1000000;
862 TAILQ_INSERT_TAIL(&hinfo->qout_head, ngp_h, ngp_link);
863 hinfo->run.qout_frames++;
864 hinfo->run.qout_octets += m->m_pkthdr.len;
868 while ((ngp_h = TAILQ_FIRST(&hinfo->qout_head))) {
869 when = &ngp_h->when;
870 m = ngp_h->m;
871 if (when->tv_sec > now->tv_sec ||
872 (when->tv_sec == now->tv_sec &&
873 when->tv_usec > now->tv_usec))
877 plen = m->m_pkthdr.len;
878 hinfo->run.qout_frames--;
879 hinfo->run.qout_octets -= plen;
882 TAILQ_REMOVE(&hinfo->qout_head, ngp_h, ngp_link);
885 NG_SEND_DATA(error, dest->hook, m, meta);
887 hinfo->stats.out_disc_frames++;
888 hinfo->stats.out_disc_octets += plen;
890 hinfo->stats.fwd_frames++;
891 hinfo->stats.fwd_octets += plen;
895 if ((hinfo->run.qin_frames != 0 || hinfo->run.qout_frames != 0) &&
896 !priv->timer_scheduled) {
897 ng_callout(&priv->timer, node, NULL, 1, ngp_callout, NULL, 0);
898 priv->timer_scheduled = 1;
912 priv->timer_scheduled = 0;
914 if (priv->upper.hook != NULL)
915 pipe_dequeue(&priv->upper, &now);
916 if (priv->lower.hook != NULL)
917 pipe_dequeue(&priv->lower, &now);
923 * This is tricky. If we have both a lower and upper hook, then we
933 if (priv->timer_scheduled)
934 ng_uncallout(&priv->timer, node);
935 if (priv->lower.hook && priv->upper.hook)
936 ng_bypass(priv->lower.hook, priv->upper.hook);
938 if (priv->upper.hook != NULL)
939 ng_rmhook_self(priv->upper.hook);
940 if (priv->lower.hook != NULL)
941 ng_rmhook_self(priv->lower.hook);
960 hinfo->hook = NULL;
963 while ((ngp_f = TAILQ_FIRST(&hinfo->fifo_head))) {
964 while ((ngp_h = TAILQ_FIRST(&ngp_f->packet_head))) {
965 TAILQ_REMOVE(&ngp_f->packet_head, ngp_h, ngp_link);
966 m_freem(ngp_h->m);
969 TAILQ_REMOVE(&hinfo->fifo_head, ngp_f, fifo_le);
974 while ((ngp_h = TAILQ_FIRST(&hinfo->qout_head))) {
975 TAILQ_REMOVE(&hinfo->qout_head, ngp_h, ngp_link);
976 m_freem(ngp_h->m);
981 if (hinfo->ber_p)
982 free(hinfo->ber_p, M_NG_PIPE);
987 if (priv->upper.hook == NULL && priv->lower.hook == NULL)
999 case MOD_LOAD:
1004 case MOD_UNLOAD: