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/netgraph/atm/sscop/ng_sscop.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 /*-
    2  * Copyright (c) 2001-2003
    3  *      Fraunhofer Institute for Open Communication Systems (FhG Fokus).
    4  *      All rights reserved.
    5  *
    6  * Author: Harti Brandt <harti@freebsd.org>
    7  *
    8  * Redistribution of this software and documentation and use in source and
    9  * binary forms, with or without modification, are permitted provided that
   10  * the following conditions are met:
   11  *
   12  * 1. Redistributions of source code or documentation must retain the above
   13  *    copyright notice, this list of conditions and the following disclaimer.
   14  * 2. Redistributions in binary form must reproduce the above copyright
   15  *    notice, this list of conditions and the following disclaimer in the
   16  *    documentation and/or other materials provided with the distribution.
   17  *
   18  * THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS
   19  * AND ITS CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
   20  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   21  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
   22  * FRAUNHOFER FOKUS OR ITS CONTRIBUTORS  BE LIABLE FOR ANY DIRECT, INDIRECT,
   23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
   25  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   26  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   27  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
   28  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   29  *
   30  * Netgraph module for ITU-T Q.2110 SSCOP.
   31  */
   32 
   33 #include <sys/cdefs.h>
   34 __FBSDID("$FreeBSD$");
   35 
   36 #include <sys/param.h>
   37 #include <sys/systm.h>
   38 #include <sys/kernel.h>
   39 #include <sys/malloc.h>
   40 #include <sys/mbuf.h>
   41 #include <sys/errno.h>
   42 #include <sys/syslog.h>
   43 #include <sys/socket.h>
   44 #include <sys/socketvar.h>
   45 #include <sys/callout.h>
   46 #include <sys/sbuf.h>
   47 #include <sys/stdint.h>
   48 #include <machine/stdarg.h>
   49 
   50 #include <netgraph/ng_message.h>
   51 #include <netgraph/netgraph.h>
   52 #include <netgraph/ng_parse.h>
   53 #include <netnatm/saal/sscopdef.h>
   54 #include <netgraph/atm/ng_sscop.h>
   55 #include <netgraph/atm/sscop/ng_sscop_cust.h>
   56 #include <netnatm/saal/sscop.h>
   57 
   58 #define DDD printf("%s: %d\n", __func__, __LINE__)
   59 
   60 #ifdef SSCOP_DEBUG
   61 #define VERBOSE(P,M,F)                                                  \
   62     do {                                                                \
   63         if (sscop_getdebug((P)->sscop) & (M))                           \
   64                 sscop_verbose F ;                                       \
   65     } while(0)
   66 #else
   67 #define VERBOSE(P,M,F)
   68 #endif
   69 
   70 MALLOC_DEFINE(M_NG_SSCOP, "netgraph_sscop", "netgraph sscop node");
   71 
   72 MODULE_DEPEND(ng_sscop, ngatmbase, 1, 1, 1);
   73 
   74 struct stats {
   75         uint64_t        in_packets;
   76         uint64_t        out_packets;
   77         uint64_t        aa_signals;
   78         uint64_t        errors;
   79         uint64_t        data_delivered;
   80         uint64_t        aa_dropped;
   81         uint64_t        maa_dropped;
   82         uint64_t        maa_signals;
   83         uint64_t        in_dropped;
   84         uint64_t        out_dropped;
   85 };
   86 
   87 /*
   88  * Private data
   89  */
   90 struct priv {
   91         hook_p          upper;          /* SAAL interface */
   92         hook_p          lower;          /* AAL5 interface */
   93         hook_p          manage;         /* management interface */
   94 
   95         struct sscop    *sscop;         /* sscop state */
   96         int             enabled;        /* whether the protocol is enabled */
   97         int             flow;           /* flow control states */
   98         struct stats    stats;          /* sadistics */
   99 };
  100 
  101 /*
  102  * Parse PARAM type
  103  */
  104 static const struct ng_parse_struct_field ng_sscop_param_type_info[] = 
  105     NG_SSCOP_PARAM_INFO;
  106 
  107 static const struct ng_parse_type ng_sscop_param_type = {
  108         &ng_parse_struct_type,
  109         ng_sscop_param_type_info
  110 };
  111 
  112 /*
  113  * Parse a SET PARAM type.
  114  */
  115 static const struct ng_parse_struct_field ng_sscop_setparam_type_info[] =
  116     NG_SSCOP_SETPARAM_INFO;
  117 
  118 static const struct ng_parse_type ng_sscop_setparam_type = {
  119         &ng_parse_struct_type,
  120         ng_sscop_setparam_type_info,
  121 };
  122 
  123 /*
  124  * Parse a SET PARAM response
  125  */
  126 static const struct ng_parse_struct_field ng_sscop_setparam_resp_type_info[] =
  127     NG_SSCOP_SETPARAM_RESP_INFO;
  128 
  129 static const struct ng_parse_type ng_sscop_setparam_resp_type = {
  130         &ng_parse_struct_type,
  131         ng_sscop_setparam_resp_type_info,
  132 };
  133 
  134 static const struct ng_cmdlist ng_sscop_cmdlist[] = {
  135         {
  136           NGM_SSCOP_COOKIE,
  137           NGM_SSCOP_GETPARAM,
  138           "getparam",
  139           NULL,
  140           &ng_sscop_param_type
  141         },
  142         {
  143           NGM_SSCOP_COOKIE,
  144           NGM_SSCOP_SETPARAM,
  145           "setparam",
  146           &ng_sscop_setparam_type,
  147           &ng_sscop_setparam_resp_type
  148         },
  149         {
  150           NGM_SSCOP_COOKIE,
  151           NGM_SSCOP_ENABLE,
  152           "enable",
  153           NULL,
  154           NULL
  155         },
  156         {
  157           NGM_SSCOP_COOKIE,
  158           NGM_SSCOP_DISABLE,
  159           "disable",
  160           NULL,
  161           NULL
  162         },
  163         {
  164           NGM_SSCOP_COOKIE,
  165           NGM_SSCOP_GETDEBUG,
  166           "getdebug",
  167           NULL,
  168           &ng_parse_hint32_type
  169         },
  170         {
  171           NGM_SSCOP_COOKIE,
  172           NGM_SSCOP_SETDEBUG,
  173           "setdebug",
  174           &ng_parse_hint32_type,
  175           NULL
  176         },
  177         {
  178           NGM_SSCOP_COOKIE,
  179           NGM_SSCOP_GETSTATE,
  180           "getstate",
  181           NULL,
  182           &ng_parse_uint32_type
  183         },
  184         { 0 }
  185 };
  186 
  187 static ng_constructor_t ng_sscop_constructor;
  188 static ng_shutdown_t    ng_sscop_shutdown;
  189 static ng_rcvmsg_t      ng_sscop_rcvmsg;
  190 static ng_newhook_t     ng_sscop_newhook;
  191 static ng_disconnect_t  ng_sscop_disconnect;
  192 static ng_rcvdata_t     ng_sscop_rcvlower;
  193 static ng_rcvdata_t     ng_sscop_rcvupper;
  194 static ng_rcvdata_t     ng_sscop_rcvmanage;
  195 
  196 static int ng_sscop_mod_event(module_t, int, void *);
  197 
  198 static struct ng_type ng_sscop_typestruct = {
  199         .version =      NG_ABI_VERSION,
  200         .name =         NG_SSCOP_NODE_TYPE,
  201         .mod_event =    ng_sscop_mod_event,
  202         .constructor =  ng_sscop_constructor,
  203         .rcvmsg =       ng_sscop_rcvmsg,
  204         .shutdown =     ng_sscop_shutdown,
  205         .newhook =      ng_sscop_newhook,
  206         .rcvdata =      ng_sscop_rcvlower,
  207         .disconnect =   ng_sscop_disconnect,
  208         .cmdlist =      ng_sscop_cmdlist,
  209 };
  210 NETGRAPH_INIT(sscop, &ng_sscop_typestruct);
  211 
  212 static void sscop_send_manage(struct sscop *, void *, enum sscop_maasig,
  213         struct SSCOP_MBUF_T *, u_int, u_int);
  214 static void sscop_send_upper(struct sscop *, void *, enum sscop_aasig,
  215         struct SSCOP_MBUF_T *, u_int);
  216 static void sscop_send_lower(struct sscop *, void *,
  217         struct SSCOP_MBUF_T *);
  218 static void sscop_verbose(struct sscop *, void *, const char *, ...)
  219         __printflike(3, 4);
  220 
  221 static const struct sscop_funcs sscop_funcs = {
  222         sscop_send_manage,
  223         sscop_send_upper,
  224         sscop_send_lower,
  225         sscop_verbose
  226 };
  227 
  228 static void
  229 sscop_verbose(struct sscop *sscop, void *arg, const char *fmt, ...)
  230 {
  231         va_list ap;
  232 
  233         va_start(ap, fmt);
  234         printf("sscop(%p): ", sscop);
  235         vprintf(fmt, ap);
  236         va_end(ap);
  237         printf("\n");
  238 }
  239 
  240 /************************************************************/
  241 /*
  242  * NODE MANAGEMENT
  243  */
  244 static int
  245 ng_sscop_constructor(node_p node)
  246 {
  247         struct priv *p;
  248 
  249         p = malloc(sizeof(*p), M_NG_SSCOP, M_WAITOK | M_ZERO);
  250 
  251         if ((p->sscop = sscop_create(node, &sscop_funcs)) == NULL) {
  252                 free(p, M_NG_SSCOP);
  253                 return (ENOMEM);
  254         }
  255         NG_NODE_SET_PRIVATE(node, p);
  256 
  257         /* All data message received by the node are expected to change the
  258          * node's state. Therefor we must ensure, that we have a writer lock. */
  259         NG_NODE_FORCE_WRITER(node);
  260 
  261         return (0);
  262 }
  263 static int
  264 ng_sscop_shutdown(node_p node)
  265 {
  266         struct priv *priv = NG_NODE_PRIVATE(node);
  267 
  268         sscop_destroy(priv->sscop);
  269 
  270         free(priv, M_NG_SSCOP);
  271         NG_NODE_SET_PRIVATE(node, NULL);
  272 
  273         NG_NODE_UNREF(node);
  274 
  275         return (0);
  276 }
  277 
  278 /************************************************************/
  279 /*
  280  * CONTROL MESSAGES
  281  */
  282 /*
  283  * Flow control message from upper layer.
  284  * This is very experimental:
  285  * If we get a message from the upper layer, that somebody has passed its
  286  * high water mark, we stop updating the receive window.
  287  * If we get a low watermark passed, then we raise the window up
  288  * to max - current.
  289  * If we get a queue status and it indicates a current below the
  290  * high watermark, we unstop window updates (if they are stopped) and
  291  * raise the window to highwater - current.
  292  */
  293 static int
  294 flow_upper(node_p node, struct ng_mesg *msg)
  295 {
  296         struct ngm_queue_state *q;
  297         struct priv *priv = NG_NODE_PRIVATE(node);
  298         u_int window, space;
  299 
  300         if (msg->header.arglen != sizeof(struct ngm_queue_state))
  301                 return (EINVAL);
  302         q = (struct ngm_queue_state *)msg->data;
  303 
  304         switch (msg->header.cmd) {
  305           case NGM_HIGH_WATER_PASSED:
  306                 if (priv->flow) {
  307                         VERBOSE(priv, SSCOP_DBG_FLOW, (priv->sscop, priv,
  308                             "flow control stopped"));
  309                         priv->flow = 0;
  310                 }
  311                 break;
  312 
  313           case NGM_LOW_WATER_PASSED:
  314                 window = sscop_window(priv->sscop, 0);
  315                 space = q->max_queuelen_packets - q->current;
  316                 if (space > window) {
  317                         VERBOSE(priv, SSCOP_DBG_FLOW, (priv->sscop, priv,
  318                             "flow control opened window by %u messages",
  319                             space - window));
  320                         (void)sscop_window(priv->sscop, space - window);
  321                 }
  322                 priv->flow = 1;
  323                 break;
  324 
  325           case NGM_SYNC_QUEUE_STATE:
  326                 if (q->high_watermark <= q->current)
  327                         break;
  328                 window = sscop_window(priv->sscop, 0);
  329                 if (priv->flow)
  330                         space = q->max_queuelen_packets - q->current;
  331                 else
  332                         space = q->high_watermark - q->current;
  333                 if (space > window) {
  334                         VERBOSE(priv, SSCOP_DBG_FLOW, (priv->sscop, priv,
  335                             "flow control opened window by %u messages",
  336                             space - window));
  337                         (void)sscop_window(priv->sscop, space - window);
  338                 }
  339                 priv->flow = 1;
  340                 break;
  341 
  342           default:
  343                 return (EINVAL);
  344         }
  345         return (0);
  346 }
  347 
  348 static int
  349 flow_lower(node_p node, struct ng_mesg *msg)
  350 {
  351         struct priv *priv = NG_NODE_PRIVATE(node);
  352 
  353         if (msg->header.arglen != sizeof(struct ngm_queue_state))
  354                 return (EINVAL);
  355 
  356         switch (msg->header.cmd) {
  357           case NGM_HIGH_WATER_PASSED:
  358                 sscop_setbusy(priv->sscop, 1);
  359                 break;
  360 
  361           case NGM_LOW_WATER_PASSED:
  362                 sscop_setbusy(priv->sscop, 1);
  363                 break;
  364 
  365           default:
  366                 return (EINVAL);
  367         }
  368         return (0);
  369 }
  370 
  371 /*
  372  * Produce a readable status description
  373  */
  374 static int
  375 text_status(node_p node, struct priv *priv, char *arg, u_int len)
  376 {
  377         struct sbuf sbuf;
  378 
  379         sbuf_new(&sbuf, arg, len, 0);
  380 
  381         if (priv->upper)
  382                 sbuf_printf(&sbuf, "upper hook: %s connected to %s:%s\n",
  383                     NG_HOOK_NAME(priv->upper),
  384                     NG_NODE_NAME(NG_HOOK_NODE(NG_HOOK_PEER(priv->upper))),
  385                     NG_HOOK_NAME(NG_HOOK_PEER(priv->upper)));
  386         else
  387                 sbuf_printf(&sbuf, "upper hook: <not connected>\n");
  388 
  389         if (priv->lower)
  390                 sbuf_printf(&sbuf, "lower hook: %s connected to %s:%s\n",
  391                     NG_HOOK_NAME(priv->lower),
  392                     NG_NODE_NAME(NG_HOOK_NODE(NG_HOOK_PEER(priv->lower))),
  393                     NG_HOOK_NAME(NG_HOOK_PEER(priv->lower)));
  394         else
  395                 sbuf_printf(&sbuf, "lower hook: <not connected>\n");
  396 
  397         if (priv->manage)
  398                 sbuf_printf(&sbuf, "manage hook: %s connected to %s:%s\n",
  399                     NG_HOOK_NAME(priv->manage),
  400                     NG_NODE_NAME(NG_HOOK_NODE(NG_HOOK_PEER(priv->manage))),
  401                     NG_HOOK_NAME(NG_HOOK_PEER(priv->manage)));
  402         else
  403                 sbuf_printf(&sbuf, "manage hook: <not connected>\n");
  404 
  405         sbuf_printf(&sbuf, "sscop state: %s\n",
  406             !priv->enabled ? "<disabled>" :
  407             sscop_statename(sscop_getstate(priv->sscop)));
  408 
  409         sbuf_printf(&sbuf, "input packets:  %ju\n",
  410             (uintmax_t)priv->stats.in_packets);
  411         sbuf_printf(&sbuf, "input dropped:  %ju\n",
  412             (uintmax_t)priv->stats.in_dropped);
  413         sbuf_printf(&sbuf, "output packets: %ju\n",
  414             (uintmax_t)priv->stats.out_packets);
  415         sbuf_printf(&sbuf, "output dropped: %ju\n",
  416             (uintmax_t)priv->stats.out_dropped);
  417         sbuf_printf(&sbuf, "aa signals:     %ju\n",
  418             (uintmax_t)priv->stats.aa_signals);
  419         sbuf_printf(&sbuf, "aa dropped:     %ju\n",
  420             (uintmax_t)priv->stats.aa_dropped);
  421         sbuf_printf(&sbuf, "maa signals:    %ju\n",
  422             (uintmax_t)priv->stats.maa_signals);
  423         sbuf_printf(&sbuf, "maa dropped:    %ju\n",
  424             (uintmax_t)priv->stats.maa_dropped);
  425         sbuf_printf(&sbuf, "errors:         %ju\n",
  426             (uintmax_t)priv->stats.errors);
  427         sbuf_printf(&sbuf, "data delivered: %ju\n",
  428             (uintmax_t)priv->stats.data_delivered);
  429         sbuf_printf(&sbuf, "window:         %u\n",
  430             sscop_window(priv->sscop, 0));
  431 
  432         sbuf_finish(&sbuf);
  433         return (sbuf_len(&sbuf));
  434 }
  435 
  436 /*
  437  * Control message received.
  438  */
  439 static int
  440 ng_sscop_rcvmsg(node_p node, item_p item, hook_p lasthook)
  441 {
  442         struct priv *priv = NG_NODE_PRIVATE(node);
  443         struct ng_mesg *resp = NULL;
  444         struct ng_mesg *msg;
  445         int error = 0;
  446 
  447         NGI_GET_MSG(item, msg);
  448 
  449         switch (msg->header.typecookie) {
  450           case NGM_GENERIC_COOKIE:
  451                 switch (msg->header.cmd) {
  452                   case NGM_TEXT_STATUS:
  453                         NG_MKRESPONSE(resp, msg, NG_TEXTRESPONSE, M_NOWAIT);
  454                         if (resp == NULL) {
  455                                 error = ENOMEM;
  456                                 break;
  457                         }
  458 
  459                         resp->header.arglen = text_status(node, priv,
  460                             (char *)resp->data, resp->header.arglen) + 1;
  461                         break;
  462 
  463                   default:
  464                         error = EINVAL;
  465                         break;
  466                 }
  467                 break;
  468 
  469           case NGM_FLOW_COOKIE:
  470                 if (priv->enabled && lasthook != NULL) {
  471                         if (lasthook == priv->upper)
  472                                 error = flow_upper(node, msg);
  473                         else if (lasthook == priv->lower)
  474                                 error = flow_lower(node, msg);
  475                 }
  476                 break;
  477 
  478           case NGM_SSCOP_COOKIE:
  479                 switch (msg->header.cmd) {
  480                   case NGM_SSCOP_GETPARAM:
  481                     {
  482                         struct sscop_param *p;
  483 
  484                         NG_MKRESPONSE(resp, msg, sizeof(*p), M_NOWAIT);
  485                         if (resp == NULL) {
  486                                 error = ENOMEM;
  487                                 break;
  488                         }
  489                         p = (struct sscop_param *)resp->data;
  490                         sscop_getparam(priv->sscop, p);
  491                         break;
  492                     }
  493 
  494                   case NGM_SSCOP_SETPARAM:
  495                     {
  496                         struct ng_sscop_setparam *arg;
  497                         struct ng_sscop_setparam_resp *p;
  498 
  499                         if (msg->header.arglen != sizeof(*arg)) {
  500                                 error = EINVAL;
  501                                 break;
  502                         }
  503                         if (priv->enabled) {
  504                                 error = EISCONN;
  505                                 break;
  506                         }
  507                         arg = (struct ng_sscop_setparam *)msg->data;
  508                         NG_MKRESPONSE(resp, msg, sizeof(*p), M_NOWAIT);
  509                         if (resp == NULL) {
  510                                 error = ENOMEM;
  511                                 break;
  512                         }
  513                         p = (struct ng_sscop_setparam_resp *)resp->data;
  514                         p->mask = arg->mask;
  515                         p->error = sscop_setparam(priv->sscop,
  516                             &arg->param, &p->mask);
  517                         break;
  518                     }
  519 
  520                   case NGM_SSCOP_ENABLE:
  521                         if (msg->header.arglen != 0) {
  522                                 error = EINVAL;
  523                                 break;
  524                         }
  525                         if (priv->enabled) {
  526                                 error = EBUSY;
  527                                 break;
  528                         }
  529                         priv->enabled = 1;
  530                         priv->flow = 1;
  531                         memset(&priv->stats, 0, sizeof(priv->stats));
  532                         break;
  533 
  534                   case NGM_SSCOP_DISABLE:
  535                         if (msg->header.arglen != 0) {
  536                                 error = EINVAL;
  537                                 break;
  538                         }
  539                         if (!priv->enabled) {
  540                                 error = ENOTCONN;
  541                                 break;
  542                         }
  543                         priv->enabled = 0;
  544                         sscop_reset(priv->sscop);
  545                         break;
  546 
  547                   case NGM_SSCOP_GETDEBUG:
  548                         if (msg->header.arglen != 0) {
  549                                 error = EINVAL;
  550                                 break;
  551                         }
  552                         NG_MKRESPONSE(resp, msg, sizeof(u_int32_t), M_NOWAIT);
  553                         if(resp == NULL) {
  554                                 error = ENOMEM;
  555                                 break;
  556                         }
  557                         *(u_int32_t *)resp->data = sscop_getdebug(priv->sscop);
  558                         break;
  559 
  560                   case NGM_SSCOP_SETDEBUG:
  561                         if (msg->header.arglen != sizeof(u_int32_t)) {
  562                                 error = EINVAL;
  563                                 break;
  564                         }
  565                         sscop_setdebug(priv->sscop, *(u_int32_t *)msg->data);
  566                         break;
  567 
  568                   case NGM_SSCOP_GETSTATE:
  569                         if (msg->header.arglen != 0) {
  570                                 error = EINVAL;
  571                                 break;
  572                         }
  573                         NG_MKRESPONSE(resp, msg, sizeof(u_int32_t), M_NOWAIT);
  574                         if(resp == NULL) {
  575                                 error = ENOMEM;
  576                                 break;
  577                         }
  578                         *(u_int32_t *)resp->data =
  579                             priv->enabled ? (sscop_getstate(priv->sscop) + 1)
  580                                           : 0;
  581                         break;
  582 
  583                   default:
  584                         error = EINVAL;
  585                         break;
  586                 }
  587                 break;
  588 
  589           default:
  590                 error = EINVAL;
  591                 break;
  592         }
  593 
  594         NG_RESPOND_MSG(error, node, item, resp);
  595         NG_FREE_MSG(msg);
  596 
  597         return (error);
  598 }
  599 
  600 /************************************************************/
  601 /*
  602  * HOOK MANAGEMENT
  603  */
  604 static int
  605 ng_sscop_newhook(node_p node, hook_p hook, const char *name)
  606 {
  607         struct priv *priv = NG_NODE_PRIVATE(node);
  608 
  609         if(strcmp(name, "upper") == 0) {
  610                 priv->upper = hook;
  611                 NG_HOOK_SET_RCVDATA(hook, ng_sscop_rcvupper);
  612         } else if(strcmp(name, "lower") == 0) {
  613                 priv->lower = hook;
  614         } else if(strcmp(name, "manage") == 0) {
  615                 priv->manage = hook;
  616                 NG_HOOK_SET_RCVDATA(hook, ng_sscop_rcvmanage);
  617         } else
  618                 return EINVAL;
  619 
  620         return 0;
  621 }
  622 static int
  623 ng_sscop_disconnect(hook_p hook)
  624 {
  625         node_p node = NG_HOOK_NODE(hook);
  626         struct priv *priv = NG_NODE_PRIVATE(node);
  627 
  628         if(hook == priv->upper)
  629                 priv->upper = NULL;
  630         else if(hook == priv->lower)
  631                 priv->lower = NULL;
  632         else if(hook == priv->manage)
  633                 priv->manage = NULL;
  634 
  635         if(NG_NODE_NUMHOOKS(node) == 0) {
  636                 if(NG_NODE_IS_VALID(node))
  637                         ng_rmnode_self(node);
  638         } else {
  639                 /*
  640                  * Imply a release request, if the upper layer is
  641                  * disconnected.
  642                  */
  643                 if(priv->upper == NULL && priv->lower != NULL &&
  644                    priv->enabled &&
  645                    sscop_getstate(priv->sscop) != SSCOP_IDLE) {
  646                         sscop_aasig(priv->sscop, SSCOP_RELEASE_request,
  647                             NULL, 0);
  648                 }
  649         }
  650         return 0;
  651 }
  652 
  653 /************************************************************/
  654 /*
  655  * DATA
  656  */
  657 static int
  658 ng_sscop_rcvlower(hook_p hook, item_p item)
  659 {
  660         struct priv *priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
  661         struct mbuf *m;
  662 
  663         if (!priv->enabled) {
  664                 NG_FREE_ITEM(item);
  665                 return EINVAL;
  666         }
  667 
  668         /*
  669          * If we are disconnected at the upper layer and in the IDLE
  670          * state, drop any incoming packet.
  671          */
  672         if (priv->upper != NULL || sscop_getstate(priv->sscop) != SSCOP_IDLE) {
  673                 NGI_GET_M(item, m);
  674                 priv->stats.in_packets++;
  675                 sscop_input(priv->sscop, m);
  676         } else {
  677                 priv->stats.in_dropped++;
  678         }
  679         NG_FREE_ITEM(item);
  680 
  681         return (0);
  682 }
  683 
  684 static void
  685 sscop_send_lower(struct sscop *sscop, void *p, struct mbuf *m)
  686 {
  687         node_p node = (node_p)p;
  688         struct priv *priv = NG_NODE_PRIVATE(node);
  689         int error;
  690 
  691         if (priv->lower == NULL) {
  692                 m_freem(m);
  693                 priv->stats.out_dropped++;
  694                 return;
  695         }
  696 
  697         priv->stats.out_packets++;
  698         NG_SEND_DATA_ONLY(error, priv->lower, m);
  699 }
  700 
  701 static int
  702 ng_sscop_rcvupper(hook_p hook, item_p item)
  703 {
  704         struct priv *priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
  705         struct sscop_arg a;
  706         struct mbuf *m;
  707 
  708         if (!priv->enabled) {
  709                 NG_FREE_ITEM(item);
  710                 return (EINVAL);
  711         }
  712 
  713         /*
  714          * If the lower layer is not connected allow to proceed.
  715          * The lower layer sending function will drop outgoing frames,
  716          * and the sscop will timeout any establish requests.
  717          */
  718         NGI_GET_M(item, m);
  719         NG_FREE_ITEM(item);
  720 
  721         if (!(m->m_flags & M_PKTHDR)) {
  722                 printf("no pkthdr\n");
  723                 m_freem(m);
  724                 return (EINVAL);
  725         }
  726         if (m->m_len < (int)sizeof(a) && (m = m_pullup(m, sizeof(a))) == NULL)
  727                 return (ENOBUFS);
  728         bcopy((caddr_t)mtod(m, struct sscop_arg *), &a, sizeof(a));
  729         m_adj(m, sizeof(a));
  730 
  731         return (sscop_aasig(priv->sscop, a.sig, m, a.arg));
  732 }
  733 
  734 static void
  735 sscop_send_upper(struct sscop *sscop, void *p, enum sscop_aasig sig,
  736     struct SSCOP_MBUF_T *m, u_int arg)
  737 {
  738         node_p node = (node_p)p;
  739         struct priv *priv = NG_NODE_PRIVATE(node);
  740         int error;
  741         struct sscop_arg *a;
  742 
  743         if (sig == SSCOP_DATA_indication && priv->flow)
  744                 sscop_window(priv->sscop, 1);
  745 
  746         if (priv->upper == NULL) {
  747                 if (m != NULL)
  748                         m_freem(m);
  749                 priv->stats.aa_dropped++;
  750                 return;
  751         }
  752 
  753         priv->stats.aa_signals++;
  754         if (sig == SSCOP_DATA_indication)
  755                 priv->stats.data_delivered++;
  756 
  757         if (m == NULL) {
  758                 MGETHDR(m, M_NOWAIT, MT_DATA);
  759                 if (m == NULL)
  760                         return;
  761                 m->m_len = sizeof(struct sscop_arg);
  762                 m->m_pkthdr.len = m->m_len;
  763         } else {
  764                 M_PREPEND(m, sizeof(struct sscop_arg), M_NOWAIT);
  765                 if (m == NULL)
  766                         return;
  767         }
  768         a = mtod(m, struct sscop_arg *);
  769         a->sig = sig;
  770         a->arg = arg;
  771 
  772         NG_SEND_DATA_ONLY(error, priv->upper, m);
  773 }
  774 
  775 static int
  776 ng_sscop_rcvmanage(hook_p hook, item_p item)
  777 {
  778         struct priv *priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
  779         struct sscop_marg a;
  780         struct mbuf *m;
  781 
  782         if (!priv->enabled) {
  783                 NG_FREE_ITEM(item);
  784                 return (EINVAL);
  785         }
  786 
  787         NGI_GET_M(item, m);
  788         NG_FREE_ITEM(item);
  789 
  790         if (m->m_len < (int)sizeof(a) && (m = m_pullup(m, sizeof(a))) == NULL)
  791                 return (ENOBUFS);
  792         bcopy((caddr_t)mtod(m, struct sscop_arg *), &a, sizeof(a));
  793         m_adj(m, sizeof(a));
  794 
  795         return (sscop_maasig(priv->sscop, a.sig, m));
  796 }
  797 
  798 static void
  799 sscop_send_manage(struct sscop *sscop, void *p, enum sscop_maasig sig,
  800     struct SSCOP_MBUF_T *m, u_int err, u_int cnt)
  801 {
  802         node_p node = (node_p)p;
  803         struct priv *priv = NG_NODE_PRIVATE(node);
  804         int error;
  805         struct sscop_merr *e;
  806         struct sscop_marg *a;
  807 
  808         if (priv->manage == NULL) {
  809                 if (m != NULL)
  810                         m_freem(m);
  811                 priv->stats.maa_dropped++;
  812                 return;
  813         }
  814 
  815         if (sig == SSCOP_MERROR_indication) {
  816                 MGETHDR(m, M_NOWAIT, MT_DATA);
  817                 if (m == NULL)
  818                         return;
  819                 m->m_len = sizeof(*e);
  820                 m->m_pkthdr.len = m->m_len;
  821                 e = mtod(m, struct sscop_merr *);
  822                 e->sig = sig;
  823                 e->err = err;
  824                 e->cnt = cnt;
  825                 priv->stats.errors++;
  826         } else if (m == NULL) {
  827                 MGETHDR(m, M_NOWAIT, MT_DATA);
  828                 if (m == NULL)
  829                         return;
  830                 m->m_len = sizeof(*a);
  831                 m->m_pkthdr.len = m->m_len;
  832                 a = mtod(m, struct sscop_marg *);
  833                 a->sig = sig;
  834                 priv->stats.maa_signals++;
  835         } else {
  836                 M_PREPEND(m, sizeof(*a), M_NOWAIT);
  837                 if (m == NULL)
  838                         return;
  839                 a = mtod(m, struct sscop_marg *);
  840                 a->sig = sig;
  841                 priv->stats.maa_signals++;
  842         }
  843 
  844         NG_SEND_DATA_ONLY(error, priv->manage, m);
  845 }
  846 
  847 /************************************************************/
  848 /*
  849  * INITIALISATION
  850  */
  851 
  852 /*
  853  * Loading and unloading of node type
  854  */
  855 static int
  856 ng_sscop_mod_event(module_t mod, int event, void *data)
  857 {
  858         int error = 0;
  859 
  860         switch (event) {
  861           case MOD_LOAD:
  862                 break;
  863 
  864           case MOD_UNLOAD:
  865                 break;
  866 
  867           default:
  868                 error = EOPNOTSUPP;
  869                 break;
  870         }
  871         return (error);
  872 }

Cache object: 7ad8957aeaf14b1360f411e5cb2f65b1


[ 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.