The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/altq/altq_blue.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: altq_blue.c,v 1.9.2.1 2004/06/27 13:25:27 he Exp $     */
    2 /*      $KAME: altq_blue.c,v 1.8 2002/01/07 11:25:40 kjc Exp $  */
    3 
    4 /*
    5  * Copyright (C) 1997-2000
    6  *      Sony Computer Science Laboratories Inc.  All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY SONY CSL AND CONTRIBUTORS ``AS IS'' AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  * ARE DISCLAIMED.  IN NO EVENT SHALL SONY CSL OR CONTRIBUTORS BE LIABLE
   21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  *
   29  */
   30 /*
   31  * Copyright (c) 1990-1994 Regents of the University of California.
   32  * All rights reserved.
   33  *
   34  * Redistribution and use in source and binary forms, with or without
   35  * modification, are permitted provided that the following conditions
   36  * are met:
   37  * 1. Redistributions of source code must retain the above copyright
   38  *    notice, this list of conditions and the following disclaimer.
   39  * 2. Redistributions in binary form must reproduce the above copyright
   40  *    notice, this list of conditions and the following disclaimer in the
   41  *    documentation and/or other materials provided with the distribution.
   42  * 3. All advertising materials mentioning features or use of this software
   43  *    must display the following acknowledgement:
   44  *      This product includes software developed by the Computer Systems
   45  *      Engineering Group at Lawrence Berkeley Laboratory.
   46  * 4. Neither the name of the University nor of the Laboratory may be used
   47  *    to endorse or promote products derived from this software without
   48  *    specific prior written permission.
   49  *
   50  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   51  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   52  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   53  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   54  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   55  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   56  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   57  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   58  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   59  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   60  * SUCH DAMAGE.
   61  */
   62 
   63 #include <sys/cdefs.h>
   64 __KERNEL_RCSID(0, "$NetBSD: altq_blue.c,v 1.9.2.1 2004/06/27 13:25:27 he Exp $");
   65 
   66 #if defined(__FreeBSD__) || defined(__NetBSD__)
   67 #include "opt_altq.h"
   68 #if (__FreeBSD__ != 2)
   69 #include "opt_inet.h"
   70 #ifdef __FreeBSD__
   71 #include "opt_inet6.h"
   72 #endif
   73 #endif
   74 #endif /* __FreeBSD__ || __NetBSD__ */
   75 #ifdef ALTQ_BLUE        /* blue is enabled by ALTQ_BLUE option in opt_altq.h */
   76 
   77 #include <sys/param.h>
   78 #include <sys/malloc.h>
   79 #include <sys/mbuf.h>
   80 #include <sys/socket.h>
   81 #include <sys/sockio.h>
   82 #include <sys/systm.h>
   83 #include <sys/proc.h>
   84 #include <sys/errno.h>
   85 #include <sys/kernel.h>
   86 
   87 #include <net/if.h>
   88 #include <net/if_types.h>
   89 #include <netinet/in.h>
   90 #include <netinet/in_systm.h>
   91 #include <netinet/ip.h>
   92 #ifdef INET6
   93 #include <netinet/ip6.h>
   94 #endif
   95 
   96 #include <altq/altq.h>
   97 #include <altq/altq_conf.h>
   98 #include <altq/altq_blue.h>
   99 
  100 /*
  101  * Blue is proposed and implemented by Wu-chang Feng <wuchang@eecs.umich.edu>.
  102  * more information on Blue is available from
  103  * http://www.thefengs.com/wuchang/work/blue/
  104  */
  105 
  106 /* fixed-point uses 12-bit decimal places */
  107 #define FP_SHIFT        12      /* fixed-point shift */
  108 
  109 #define BLUE_LIMIT      200     /* default max queue length */
  110 
  111 /* blue_list keeps all blue_state_t's allocated. */
  112 static blue_queue_t *blue_list = NULL;
  113 
  114 /* internal function prototypes */
  115 static int blue_enqueue __P((struct ifaltq *, struct mbuf *,
  116                              struct altq_pktattr *));
  117 static struct mbuf *blue_dequeue __P((struct ifaltq *, int));
  118 static int drop_early __P((blue_t *));
  119 static int mark_ecn __P((struct mbuf *, struct altq_pktattr *, int));
  120 static int blue_detach __P((blue_queue_t *));
  121 static int blue_request __P((struct ifaltq *, int, void *));
  122 
  123 /*
  124  * blue device interface
  125  */
  126 altqdev_decl(blue);
  127 
  128 int
  129 blueopen(dev, flag, fmt, p)
  130         dev_t dev;
  131         int flag, fmt;
  132         struct proc *p;
  133 {
  134         /* everything will be done when the queueing scheme is attached. */
  135         return 0;
  136 }
  137 
  138 int
  139 blueclose(dev, flag, fmt, p)
  140         dev_t dev;
  141         int flag, fmt;
  142         struct proc *p;
  143 {
  144         blue_queue_t *rqp;
  145         int err, error = 0;
  146 
  147         while ((rqp = blue_list) != NULL) {
  148                 /* destroy all */
  149                 err = blue_detach(rqp);
  150                 if (err != 0 && error == 0)
  151                         error = err;
  152         }
  153 
  154         return error;
  155 }
  156 
  157 int
  158 blueioctl(dev, cmd, addr, flag, p)
  159         dev_t dev;
  160         ioctlcmd_t cmd;
  161         caddr_t addr;
  162         int flag;
  163         struct proc *p;
  164 {
  165         blue_queue_t *rqp;
  166         struct blue_interface *ifacep;
  167         struct ifnet *ifp;
  168         int     error = 0;
  169 
  170         /* check super-user privilege */
  171         switch (cmd) {
  172         case BLUE_GETSTATS:
  173                 break;
  174         default:
  175 #if (__FreeBSD_version > 400000)
  176                 if ((error = suser(p)) != 0)
  177                         return (error);
  178 #else
  179                 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
  180                         return (error);
  181 #endif
  182                 break;
  183         }
  184     
  185         switch (cmd) {
  186 
  187         case BLUE_ENABLE:
  188                 ifacep = (struct blue_interface *)addr;
  189                 if ((rqp = altq_lookup(ifacep->blue_ifname, ALTQT_BLUE)) == NULL) {
  190                         error = EBADF;
  191                         break;
  192                 }
  193                 error = altq_enable(rqp->rq_ifq);
  194                 break;
  195 
  196         case BLUE_DISABLE:
  197                 ifacep = (struct blue_interface *)addr;
  198                 if ((rqp = altq_lookup(ifacep->blue_ifname, ALTQT_BLUE)) == NULL) {
  199                         error = EBADF;
  200                         break;
  201                 }
  202                 error = altq_disable(rqp->rq_ifq);
  203                 break;
  204 
  205         case BLUE_IF_ATTACH:
  206                 ifp = ifunit(((struct blue_interface *)addr)->blue_ifname);
  207                 if (ifp == NULL) {
  208                         error = ENXIO;
  209                         break;
  210                 }
  211 
  212                 /* allocate and initialize blue_state_t */
  213                 MALLOC(rqp, blue_queue_t *, sizeof(blue_queue_t), M_DEVBUF, M_WAITOK);
  214                 (void)memset(rqp, 0, sizeof(blue_queue_t));
  215 
  216                 MALLOC(rqp->rq_q, class_queue_t *, sizeof(class_queue_t),
  217                        M_DEVBUF, M_WAITOK);
  218                 (void)memset(rqp->rq_q, 0, sizeof(class_queue_t));
  219 
  220                 MALLOC(rqp->rq_blue, blue_t *, sizeof(blue_t), M_DEVBUF, M_WAITOK); 
  221                 (void)memset(rqp->rq_blue, 0, sizeof(blue_t));
  222 
  223                 rqp->rq_ifq = &ifp->if_snd;
  224                 qtail(rqp->rq_q) = NULL;
  225                 qlen(rqp->rq_q) = 0;
  226                 qlimit(rqp->rq_q) = BLUE_LIMIT;
  227 
  228                 /* default packet time: 1000 bytes / 10Mbps * 8 * 1000000 */
  229                 blue_init(rqp->rq_blue, 0, 800, 1000, 50000);
  230 
  231                 /*
  232                  * set BLUE to this ifnet structure.
  233                  */
  234                 error = altq_attach(rqp->rq_ifq, ALTQT_BLUE, rqp,
  235                                     blue_enqueue, blue_dequeue, blue_request,
  236                                     NULL, NULL);
  237                 if (error) {
  238                         FREE(rqp->rq_blue, M_DEVBUF);
  239                         FREE(rqp->rq_q, M_DEVBUF);
  240                         FREE(rqp, M_DEVBUF);
  241                         break;
  242                 }
  243 
  244                 /* add this state to the blue list */
  245                 rqp->rq_next = blue_list;
  246                 blue_list = rqp;
  247                 break;
  248 
  249         case BLUE_IF_DETACH:
  250                 ifacep = (struct blue_interface *)addr;
  251                 if ((rqp = altq_lookup(ifacep->blue_ifname, ALTQT_BLUE)) == NULL) {
  252                         error = EBADF;
  253                         break;
  254                 }
  255                 error = blue_detach(rqp);
  256                 break;
  257 
  258         case BLUE_GETSTATS:
  259                 do {
  260                         struct blue_stats *q_stats;
  261                         blue_t *rp;
  262 
  263                         q_stats = (struct blue_stats *)addr;
  264                         if ((rqp = altq_lookup(q_stats->iface.blue_ifname,
  265                                              ALTQT_BLUE)) == NULL) {
  266                                 error = EBADF;
  267                                 break;
  268                         }
  269 
  270                         q_stats->q_len     = qlen(rqp->rq_q);
  271                         q_stats->q_limit   = qlimit(rqp->rq_q);
  272 
  273                         rp = rqp->rq_blue;
  274                         q_stats->q_pmark = rp->blue_pmark;
  275                         q_stats->xmit_packets  = rp->blue_stats.xmit_packets;
  276                         q_stats->xmit_bytes    = rp->blue_stats.xmit_bytes;
  277                         q_stats->drop_packets  = rp->blue_stats.drop_packets;
  278                         q_stats->drop_bytes    = rp->blue_stats.drop_bytes;
  279                         q_stats->drop_forced   = rp->blue_stats.drop_forced;
  280                         q_stats->drop_unforced = rp->blue_stats.drop_unforced;
  281                         q_stats->marked_packets = rp->blue_stats.marked_packets;
  282 
  283                 } while (0);
  284                 break;
  285 
  286         case BLUE_CONFIG:
  287                 do {
  288                         struct blue_conf *fc;
  289                         int limit;
  290 
  291                         fc = (struct blue_conf *)addr;
  292                         if ((rqp = altq_lookup(fc->iface.blue_ifname,
  293                                                ALTQT_BLUE)) == NULL) {
  294                                 error = EBADF;
  295                                 break;
  296                         }
  297                         limit = fc->blue_limit;
  298                         qlimit(rqp->rq_q) = limit;
  299                         fc->blue_limit = limit; /* write back the new value */
  300                         if (fc->blue_pkttime > 0)
  301                                 rqp->rq_blue->blue_pkttime = fc->blue_pkttime;
  302                         if (fc->blue_max_pmark > 0)
  303                                 rqp->rq_blue->blue_max_pmark = fc->blue_max_pmark;
  304                         if (fc->blue_hold_time > 0)
  305                                 rqp->rq_blue->blue_hold_time = fc->blue_hold_time;
  306                         rqp->rq_blue->blue_flags = fc->blue_flags;
  307                         
  308                         blue_init(rqp->rq_blue, rqp->rq_blue->blue_flags,
  309                                   rqp->rq_blue->blue_pkttime,
  310                                   rqp->rq_blue->blue_max_pmark,
  311                                   rqp->rq_blue->blue_hold_time);
  312                 } while (0);
  313                 break;
  314 
  315         default:
  316                 error = EINVAL;
  317                 break;
  318         }
  319         return error;
  320 }
  321 
  322 static int blue_detach(rqp)
  323         blue_queue_t *rqp;
  324 {
  325         blue_queue_t *tmp;
  326         int error = 0;
  327 
  328         if (ALTQ_IS_ENABLED(rqp->rq_ifq))
  329                 altq_disable(rqp->rq_ifq);
  330 
  331         if ((error = altq_detach(rqp->rq_ifq)))
  332                 return (error);
  333 
  334         if (blue_list == rqp)
  335                 blue_list = rqp->rq_next;
  336         else {
  337                 for (tmp = blue_list; tmp != NULL; tmp = tmp->rq_next)
  338                         if (tmp->rq_next == rqp) {
  339                                 tmp->rq_next = rqp->rq_next;
  340                                 break;
  341                         }
  342                 if (tmp == NULL)
  343                         printf("blue_detach: no state found in blue_list!\n");
  344         }
  345 
  346         FREE(rqp->rq_q, M_DEVBUF);
  347         FREE(rqp->rq_blue, M_DEVBUF);
  348         FREE(rqp, M_DEVBUF);
  349         return (error);
  350 }
  351 
  352 /*
  353  * blue support routines
  354  */
  355 
  356 int 
  357 blue_init(rp, flags, pkttime, blue_max_pmark, blue_hold_time)
  358         blue_t  *rp;
  359         int     flags;
  360         int     pkttime;
  361         int     blue_max_pmark;
  362         int     blue_hold_time;
  363 {
  364         int npkts_per_sec;
  365         
  366         rp->blue_idle = 1;
  367         rp->blue_flags = flags;
  368         rp->blue_pkttime = pkttime;
  369         rp->blue_max_pmark = blue_max_pmark;
  370         rp->blue_hold_time = blue_hold_time;
  371         if (pkttime == 0)
  372                 rp->blue_pkttime = 1;
  373 
  374         /* when the link is very slow, adjust blue parameters */
  375         npkts_per_sec = 1000000 / rp->blue_pkttime;
  376         if (npkts_per_sec < 50) {
  377         }
  378         else if (npkts_per_sec < 300) {
  379         }
  380 
  381         microtime(&rp->blue_last);
  382         return (0);
  383 }
  384 
  385 /*
  386  * enqueue routine:
  387  *
  388  *      returns: 0 when successfully queued.
  389  *               ENOBUFS when drop occurs.
  390  */
  391 static int
  392 blue_enqueue(ifq, m, pktattr)
  393         struct ifaltq *ifq;
  394         struct mbuf *m;
  395         struct altq_pktattr *pktattr;
  396 {
  397         blue_queue_t *rqp = (blue_queue_t *)ifq->altq_disc;
  398         int error = 0;
  399 
  400         if (blue_addq(rqp->rq_blue, rqp->rq_q, m, pktattr) == 0)
  401                 ifq->ifq_len++;
  402         else
  403                 error = ENOBUFS;
  404         return error;
  405 }
  406 
  407 #define DTYPE_NODROP    0       /* no drop */
  408 #define DTYPE_FORCED    1       /* a "forced" drop */
  409 #define DTYPE_EARLY     2       /* an "unforced" (early) drop */
  410 
  411 int
  412 blue_addq(rp, q, m, pktattr)
  413         blue_t *rp;
  414         class_queue_t *q;
  415         struct mbuf *m;
  416         struct altq_pktattr *pktattr;
  417 {
  418         int droptype;
  419     
  420         /*
  421          * if we were idle, this is an enqueue onto an empty queue
  422          * and we should decrement marking probability
  423          * 
  424          */
  425         if (rp->blue_idle) {
  426                 struct timeval now;
  427                 int t;
  428                 rp->blue_idle = 0;
  429                 microtime(&now);
  430                 t = (now.tv_sec - rp->blue_last.tv_sec);
  431                 if ( t > 1) {
  432                         rp->blue_pmark = 1;
  433                         microtime(&rp->blue_last);
  434                 } else {
  435                         t = t * 1000000 + (now.tv_usec - rp->blue_last.tv_usec);
  436                         if (t > rp->blue_hold_time) {
  437                                 rp->blue_pmark--;
  438                                 if (rp->blue_pmark < 0) rp->blue_pmark = 0;
  439                                 microtime(&rp->blue_last);
  440                         }
  441                 }
  442         }
  443 
  444         /* see if we drop early */
  445         droptype = DTYPE_NODROP;
  446         if (drop_early(rp) && qlen(q) > 1) {
  447                 /* mark or drop by blue */
  448                 if ((rp->blue_flags & BLUEF_ECN) &&
  449                     mark_ecn(m, pktattr, rp->blue_flags)) {
  450                         /* successfully marked.  do not drop. */
  451 #ifdef BLUE_STATS
  452                         rp->blue_stats.marked_packets++;
  453 #endif
  454                 } else { 
  455                         /* unforced drop by blue */
  456                         droptype = DTYPE_EARLY;
  457                 }
  458         }
  459 
  460         /*
  461          * if the queue length hits the hard limit, it's a forced drop.
  462          */
  463         if (droptype == DTYPE_NODROP && qlen(q) >= qlimit(q))
  464                 droptype = DTYPE_FORCED;
  465 
  466         /* if successful or forced drop, enqueue this packet. */
  467         if (droptype != DTYPE_EARLY)
  468                 _addq(q, m);
  469 
  470         if (droptype != DTYPE_NODROP) {
  471                 if (droptype == DTYPE_EARLY) {
  472                         /* drop the incoming packet */
  473 #ifdef BLUE_STATS
  474                         rp->blue_stats.drop_unforced++;
  475 #endif
  476                 } else {
  477                         struct timeval now;
  478                         int t;
  479                         /* forced drop, select a victim packet in the queue. */
  480                         m = _getq_random(q);
  481                         microtime(&now);
  482                         t = (now.tv_sec - rp->blue_last.tv_sec);
  483                         t = t * 1000000 + (now.tv_usec - rp->blue_last.tv_usec);
  484                         if (t > rp->blue_hold_time) {
  485                                 rp->blue_pmark += rp->blue_max_pmark >> 3;
  486                                 if (rp->blue_pmark > rp->blue_max_pmark)
  487                                         rp->blue_pmark = rp->blue_max_pmark;
  488                                 microtime(&rp->blue_last);
  489                         }
  490 #ifdef BLUE_STATS
  491                         rp->blue_stats.drop_forced++;
  492 #endif
  493                 }
  494 #ifdef BLUE_STATS
  495                 rp->blue_stats.drop_packets++;
  496                 rp->blue_stats.drop_bytes += m->m_pkthdr.len;
  497 #endif
  498                 m_freem(m);
  499                 return (-1);
  500         }
  501         /* successfully queued */
  502         return (0);
  503 }
  504 
  505 /*
  506  * early-drop probability is kept in blue_pmark
  507  *
  508  */
  509 static int
  510 drop_early(rp)
  511         blue_t *rp;
  512 {
  513         if ((random() % rp->blue_max_pmark) < rp->blue_pmark) {
  514                 /* drop or mark */
  515                 return (1);
  516         }
  517         /* no drop/mark */
  518         return (0);
  519 }
  520 
  521 /*
  522  * try to mark CE bit to the packet.
  523  *    returns 1 if successfully marked, 0 otherwise.
  524  */
  525 static int
  526 mark_ecn(m, pktattr, flags)
  527         struct mbuf *m;
  528         struct altq_pktattr *pktattr;
  529         int flags;
  530 {
  531         struct mbuf *m0;
  532 
  533         if (pktattr == NULL ||
  534             (pktattr->pattr_af != AF_INET && pktattr->pattr_af != AF_INET6))
  535                 return (0);
  536 
  537         /* verify that pattr_hdr is within the mbuf data */
  538         for (m0 = m; m0 != NULL; m0 = m0->m_next)
  539                 if ((pktattr->pattr_hdr >= m0->m_data) &&
  540                     (pktattr->pattr_hdr < m0->m_data + m0->m_len))
  541                         break;
  542         if (m0 == NULL) {
  543                 /* ick, pattr_hdr is stale */
  544                 pktattr->pattr_af = AF_UNSPEC;
  545                 return (0);
  546         }
  547 
  548         switch (pktattr->pattr_af) {
  549         case AF_INET:
  550                 if (flags & BLUEF_ECN4) {
  551                         struct ip *ip = (struct ip *)pktattr->pattr_hdr;
  552                         u_int8_t otos;
  553                         int sum;
  554             
  555                         if (ip->ip_v != 4)
  556                                 return (0);     /* version mismatch! */
  557                         if ((ip->ip_tos & IPTOS_ECN_MASK) == IPTOS_ECN_NOTECT)
  558                                 return (0);     /* not-ECT */
  559                         if ((ip->ip_tos & IPTOS_ECN_MASK) == IPTOS_ECN_CE)
  560                                 return (1);     /* already marked */
  561 
  562                         /*
  563                          * ecn-capable but not marked,
  564                          * mark CE and update checksum
  565                          */
  566                         otos = ip->ip_tos;
  567                         ip->ip_tos |= IPTOS_ECN_CE;
  568                         /*
  569                          * update checksum (from RFC1624)
  570                          *         HC' = ~(~HC + ~m + m')
  571                          */
  572                         sum = ~ntohs(ip->ip_sum) & 0xffff;
  573                         sum += (~otos & 0xffff) + ip->ip_tos;
  574                         sum = (sum >> 16) + (sum & 0xffff);
  575                         sum += (sum >> 16);  /* add carry */
  576                         ip->ip_sum = htons(~sum & 0xffff);
  577                         return (1);
  578                 }
  579                 break;
  580 #ifdef INET6
  581         case AF_INET6:
  582                 if (flags & BLUEF_ECN6) {
  583                         struct ip6_hdr *ip6 = (struct ip6_hdr *)pktattr->pattr_hdr;
  584                         u_int32_t flowlabel;
  585 
  586                         flowlabel = ntohl(ip6->ip6_flow);
  587                         if ((flowlabel >> 28) != 6)
  588                                 return (0);     /* version mismatch! */
  589                         if ((flowlabel & (IPTOS_ECN_MASK << 20)) ==
  590                             (IPTOS_ECN_NOTECT << 20))
  591                                 return (0);     /* not-ECT */
  592                         if ((flowlabel & (IPTOS_ECN_MASK << 20)) ==
  593                             (IPTOS_ECN_CE << 20))
  594                                 return (1);     /* already marked */
  595                         /*
  596                          * ecn-capable but not marked,  mark CE
  597                          */
  598                         flowlabel |= (IPTOS_ECN_CE << 20);
  599                         ip6->ip6_flow = htonl(flowlabel);
  600                         return (1);
  601                 }
  602                 break;
  603 #endif  /* INET6 */
  604         }
  605 
  606         /* not marked */
  607         return (0);
  608 }
  609 
  610 /*
  611  * dequeue routine:
  612  *      must be called in splnet.
  613  *
  614  *      returns: mbuf dequeued.
  615  *               NULL when no packet is available in the queue.
  616  */
  617 
  618 static struct mbuf *
  619 blue_dequeue(ifq, op)
  620         struct ifaltq *ifq;
  621         int op;
  622 {
  623         blue_queue_t *rqp = (blue_queue_t *)ifq->altq_disc;
  624         struct mbuf *m = NULL;
  625 
  626         if (op == ALTDQ_POLL)
  627                 return (qhead(rqp->rq_q));
  628         
  629         m = blue_getq(rqp->rq_blue, rqp->rq_q);
  630         if (m != NULL)
  631                 ifq->ifq_len--;
  632         return m;
  633 }
  634 
  635 struct mbuf *blue_getq(rp, q)
  636         blue_t *rp;
  637         class_queue_t *q;
  638 {
  639         struct mbuf *m;
  640         
  641         if ((m = _getq(q)) == NULL) {
  642                 if (rp->blue_idle == 0) {
  643                         rp->blue_idle = 1;
  644                         microtime(&rp->blue_last);
  645                 }
  646                 return NULL;
  647         }
  648 
  649         rp->blue_idle = 0;
  650 #ifdef BLUE_STATS
  651         rp->blue_stats.xmit_packets++;
  652         rp->blue_stats.xmit_bytes += m->m_pkthdr.len;
  653 #endif
  654         return (m);
  655 }
  656 
  657 static int
  658 blue_request(ifq, req, arg)
  659         struct ifaltq *ifq;
  660         int req;
  661         void *arg;
  662 {
  663         blue_queue_t *rqp = (blue_queue_t *)ifq->altq_disc;
  664 
  665         switch (req) {
  666         case ALTRQ_PURGE:
  667                 _flushq(rqp->rq_q);
  668                 if (ALTQ_IS_ENABLED(ifq))
  669                         ifq->ifq_len = 0;
  670                 break;
  671         }
  672         return (0);
  673 }
  674 
  675 
  676 #ifdef KLD_MODULE
  677 
  678 static struct altqsw blue_sw =
  679         {"blue", blueopen, blueclose, blueioctl};
  680 
  681 ALTQ_MODULE(altq_blue, ALTQT_BLUE, &blue_sw);
  682 
  683 #endif /* KLD_MODULE */
  684 
  685 #endif /* ALTQ_BLUE */

Cache object: c50fb56a42aada331c9da6d9960562a8


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.