File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / babeld / babel_interface.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Oct 9 09:22:28 2012 UTC (11 years, 9 months ago) by misho
Branches: quagga, MAIN
CVS tags: v0_99_22p0, v0_99_22, v0_99_21, HEAD
quagga

    1: /*  
    2:  *  This file is free software: you may copy, redistribute and/or modify it  
    3:  *  under the terms of the GNU General Public License as published by the  
    4:  *  Free Software Foundation, either version 2 of the License, or (at your  
    5:  *  option) any later version.  
    6:  *  
    7:  *  This file is distributed in the hope that it will be useful, but  
    8:  *  WITHOUT ANY WARRANTY; without even the implied warranty of  
    9:  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU  
   10:  *  General Public License for more details.  
   11:  *  
   12:  *  You should have received a copy of the GNU General Public License  
   13:  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.  
   14:  *  
   15:  * This file incorporates work covered by the following copyright and  
   16:  * permission notice:  
   17:  *  
   18: 
   19: Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek
   20: 
   21: Permission is hereby granted, free of charge, to any person obtaining a copy
   22: of this software and associated documentation files (the "Software"), to deal
   23: in the Software without restriction, including without limitation the rights
   24: to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   25: copies of the Software, and to permit persons to whom the Software is
   26: furnished to do so, subject to the following conditions:
   27: 
   28: The above copyright notice and this permission notice shall be included in
   29: all copies or substantial portions of the Software.
   30: 
   31: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   32: IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   33: FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
   34: AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   35: LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   36: OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   37: THE SOFTWARE.
   38: */
   39: 
   40: #include <zebra.h>
   41: #include "memory.h"
   42: #include "log.h"
   43: #include "command.h"
   44: #include "prefix.h"
   45: #include "vector.h"
   46: #include "distribute.h"
   47: 
   48: #include "babel_main.h"
   49: #include "util.h"
   50: #include "kernel.h"
   51: #include "babel_interface.h"
   52: #include "message.h"
   53: #include "route.h"
   54: #include "babel_zebra.h"
   55: #include "neighbour.h"
   56: #include "route.h"
   57: #include "xroute.h"
   58: 
   59: 
   60: #define IS_ENABLE(ifp) (babel_enable_if_lookup(ifp->name) >= 0)
   61: 
   62: static int babel_enable_if_lookup (const char *ifname);
   63: static int babel_enable_if_add (const char *ifname);
   64: static int babel_enable_if_delete (const char *ifname);
   65: static int interface_recalculate(struct interface *ifp);
   66: static int interface_reset(struct interface *ifp);
   67: static int babel_if_new_hook    (struct interface *ifp);
   68: static int babel_if_delete_hook (struct interface *ifp);
   69: static int interface_config_write (struct vty *vty);
   70: static babel_interface_nfo * babel_interface_allocate (void);
   71: static void babel_interface_free (babel_interface_nfo *bi);
   72: 
   73: 
   74: static vector babel_enable_if;                 /* enable interfaces (by cmd). */
   75: static struct cmd_node babel_interface_node =  /* babeld's interface node.    */
   76: {
   77:     INTERFACE_NODE,
   78:     "%s(config-if)# ",
   79:     1 /* VTYSH */
   80: };
   81: 
   82: 
   83: int
   84: babel_interface_up (int cmd, struct zclient *client, zebra_size_t length)
   85: {
   86:     struct stream *s = NULL;
   87:     struct interface *ifp = NULL;
   88: 
   89:     debugf(BABEL_DEBUG_IF, "receive a 'interface up'");
   90: 
   91:     s = zclient->ibuf;
   92:     ifp = zebra_interface_state_read(s); /* it updates iflist */
   93: 
   94:     if (ifp == NULL) {
   95:         return 0;
   96:     }
   97: 
   98:     interface_recalculate(ifp);
   99:     return 0;
  100: }
  101: 
  102: int
  103: babel_interface_down (int cmd, struct zclient *client, zebra_size_t length)
  104: {
  105:     struct stream *s = NULL;
  106:     struct interface *ifp = NULL;
  107: 
  108:     debugf(BABEL_DEBUG_IF, "receive a 'interface down'");
  109: 
  110:     s = zclient->ibuf;
  111:     ifp = zebra_interface_state_read(s); /* it updates iflist */
  112: 
  113:     if (ifp == NULL) {
  114:         return 0;
  115:     }
  116: 
  117:     interface_reset(ifp);
  118:     return 0;
  119: }
  120: 
  121: int
  122: babel_interface_add (int cmd, struct zclient *client, zebra_size_t length)
  123: {
  124:     struct interface *ifp = NULL;
  125: 
  126:     debugf(BABEL_DEBUG_IF, "receive a 'interface add'");
  127: 
  128:     /* read and add the interface in the iflist. */
  129:     ifp = zebra_interface_add_read (zclient->ibuf);
  130: 
  131:     if (ifp == NULL) {
  132:         return 0;
  133:     }
  134: 
  135:     interface_recalculate(ifp);
  136:     return 0;
  137: }
  138: 
  139: int
  140: babel_interface_delete (int cmd, struct zclient *client, zebra_size_t length)
  141: {
  142:     struct interface *ifp;
  143:     struct stream *s;
  144: 
  145:     debugf(BABEL_DEBUG_IF, "receive a 'interface delete'");
  146: 
  147:     s = zclient->ibuf;
  148:     ifp = zebra_interface_state_read(s); /* it updates iflist */
  149: 
  150:     if (ifp == NULL)
  151:         return 0;
  152: 
  153:     if (IS_ENABLE(ifp))
  154:         interface_reset(ifp);
  155: 
  156:     /* To support pseudo interface do not free interface structure.  */
  157:     /* if_delete(ifp); */
  158:     ifp->ifindex = IFINDEX_INTERNAL;
  159: 
  160:     return 0;
  161: }
  162: 
  163: int
  164: babel_interface_address_add (int cmd, struct zclient *client,
  165:                              zebra_size_t length)
  166: {
  167:     babel_interface_nfo *babel_ifp;
  168:     struct connected *ifc;
  169:     struct prefix *prefix;
  170: 
  171:     debugf(BABEL_DEBUG_IF, "receive a 'interface address add'");
  172: 
  173:     ifc = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_ADD,
  174:                                         zclient->ibuf);
  175: 
  176:     if (ifc == NULL)
  177:         return 0;
  178: 
  179:     prefix = ifc->address;
  180: 
  181:     if (prefix->family == AF_INET) {
  182:         flush_interface_routes(ifc->ifp, 0);
  183:         babel_ifp = babel_get_if_nfo(ifc->ifp);
  184:         if (babel_ifp->ipv4 == NULL) {
  185:             babel_ifp->ipv4 = malloc(4);
  186:             if (babel_ifp->ipv4 == NULL) {
  187:                 zlog_err("not einough memory");
  188:             } else {
  189:                 memcpy(babel_ifp->ipv4, &prefix->u.prefix4, 4);
  190:             }
  191:         }
  192:     }
  193: 
  194:     send_request(ifc->ifp, NULL, 0);
  195:     send_update(ifc->ifp, 0, NULL, 0);
  196: 
  197:     return 0;
  198: }
  199: 
  200: int
  201: babel_interface_address_delete (int cmd, struct zclient *client,
  202:                                 zebra_size_t length)
  203: {
  204:     babel_interface_nfo *babel_ifp;
  205:     struct connected *ifc;
  206:     struct prefix *prefix;
  207: 
  208:     debugf(BABEL_DEBUG_IF, "receive a 'interface address add'");
  209: 
  210:     ifc = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_ADD,
  211:                                         zclient->ibuf);
  212: 
  213:     if (ifc == NULL)
  214:         return 0;
  215: 
  216:     prefix = ifc->address;
  217: 
  218:     if (prefix->family == AF_INET) {
  219:         flush_interface_routes(ifc->ifp, 0);
  220:         babel_ifp = babel_get_if_nfo(ifc->ifp);
  221:         if (babel_ifp->ipv4 != NULL
  222:             && memcmp(babel_ifp->ipv4, &prefix->u.prefix4, 4) == 0) {
  223:             free(babel_ifp->ipv4);
  224:             babel_ifp->ipv4 = NULL;
  225:         }
  226:     }
  227: 
  228:     send_request(ifc->ifp, NULL, 0);
  229:     send_update(ifc->ifp, 0, NULL, 0);
  230: 
  231:     return 0;
  232: }
  233: 
  234: /* Lookup function. */
  235: static int
  236: babel_enable_if_lookup (const char *ifname)
  237: {
  238:     unsigned int i;
  239:     char *str;
  240: 
  241:     for (i = 0; i < vector_active (babel_enable_if); i++)
  242:         if ((str = vector_slot (babel_enable_if, i)) != NULL)
  243:             if (strcmp (str, ifname) == 0)
  244:                 return i;
  245:     return -1;
  246: }
  247: 
  248: /* Add interface to babel_enable_if. */
  249: static int
  250: babel_enable_if_add (const char *ifname)
  251: {
  252:     int ret;
  253:     struct interface *ifp = NULL;
  254: 
  255:     ret = babel_enable_if_lookup (ifname);
  256:     if (ret >= 0)
  257:         return -1;
  258: 
  259:     vector_set (babel_enable_if, strdup (ifname));
  260: 
  261:     ifp = if_lookup_by_name(ifname);
  262:     if (ifp != NULL)
  263:         interface_recalculate(ifp);
  264: 
  265:     return 1;
  266: }
  267: 
  268: /* Delete interface from babel_enable_if. */
  269: static int
  270: babel_enable_if_delete (const char *ifname)
  271: {
  272:     int babel_enable_if_index;
  273:     char *str;
  274:     struct interface *ifp = NULL;
  275: 
  276:     babel_enable_if_index = babel_enable_if_lookup (ifname);
  277:     if (babel_enable_if_index < 0)
  278:         return -1;
  279: 
  280:     str = vector_slot (babel_enable_if, babel_enable_if_index);
  281:     free (str);
  282:     vector_unset (babel_enable_if, babel_enable_if_index);
  283: 
  284:     ifp = if_lookup_by_name(ifname);
  285:     if (ifp != NULL)
  286:         interface_reset(ifp);
  287: 
  288:     return 1;
  289: }
  290: 
  291: /* [Babel Command] Babel enable on specified interface or matched network. */
  292: DEFUN (babel_network,
  293:        babel_network_cmd,
  294:        "network IF_OR_ADDR",
  295:        "Enable Babel protocol on specified interface or network.\n"
  296:        "Interface or address")
  297: {
  298:     int ret;
  299:     struct prefix p;
  300: 
  301:     ret = str2prefix (argv[0], &p);
  302: 
  303:     /* Given string is:               */
  304:     if (ret) /* an IPv4 or v6 network */
  305:         return CMD_ERR_NO_MATCH; /* not implemented yet */
  306:     else     /* an interface name     */
  307:         ret = babel_enable_if_add (argv[0]);
  308: 
  309:     if (ret < 0) {
  310:         vty_out (vty, "There is same network configuration %s%s", argv[0],
  311:                  VTY_NEWLINE);
  312:         return CMD_WARNING;
  313:     }
  314: 
  315:     return CMD_SUCCESS;
  316: }
  317: 
  318: /* [Babel Command] Babel enable on specified interface or matched network. */
  319: DEFUN (no_babel_network,
  320:        no_babel_network_cmd,
  321:        "no network IF_OR_ADDR",
  322:        NO_STR
  323:        "Disable Babel protocol on specified interface or network.\n"
  324:        "Interface or address")
  325: {
  326:     int ret;
  327:     struct prefix p;
  328: 
  329:     ret = str2prefix (argv[0], &p);
  330: 
  331:     /* Given string is:               */
  332:     if (ret) /* an IPv4 or v6 network */
  333:         return CMD_ERR_NO_MATCH; /* not implemented yet */
  334:     else     /* an interface name     */
  335:         ret = babel_enable_if_delete (argv[0]);
  336: 
  337:     if (ret < 0) {
  338:         vty_out (vty, "can't find network %s%s", argv[0],
  339:                  VTY_NEWLINE);
  340:         return CMD_WARNING;
  341:     }
  342: 
  343:     return CMD_SUCCESS;
  344: }
  345: 
  346: /* There are a number of interface parameters that must be changed when
  347:    an interface becomes wired/wireless.  In Quagga, they cannot be
  348:    configured separately. */
  349: 
  350: static void
  351: babel_set_wired_internal(babel_interface_nfo *babel_ifp, int wired)
  352: {
  353:     if(wired) {
  354:         babel_ifp->flags |= BABEL_IF_WIRED;
  355:         babel_ifp->cost = 96;
  356:         babel_ifp->flags &= ~BABEL_IF_LQ;
  357:     } else {
  358:         babel_ifp->flags &= ~BABEL_IF_WIRED;
  359:         babel_ifp->cost = 256;
  360:         babel_ifp->flags |= BABEL_IF_LQ;
  361:     }
  362: 
  363: }
  364: 
  365: /* [Interface Command] Tell the interface is wire. */
  366: DEFUN (babel_set_wired,
  367:        babel_set_wired_cmd,
  368:        "babel wired",
  369:        "Babel interface commands\n"
  370:        "Enable wired optimisations")
  371: {
  372:     struct interface *ifp;
  373:     babel_interface_nfo *babel_ifp;
  374: 
  375:     ifp = vty->index;
  376:     babel_ifp = babel_get_if_nfo(ifp);
  377: 
  378:     assert (babel_ifp != NULL);
  379:     babel_set_wired_internal(babel_ifp, 1);
  380:     return CMD_SUCCESS;
  381: }
  382: 
  383: /* [Interface Command] Tell the interface is wireless (default). */
  384: DEFUN (babel_set_wireless,
  385:        babel_set_wireless_cmd,
  386:        "babel wireless",
  387:        "Babel interface commands\n"
  388:        "Disable wired optimiations (assume wireless)")
  389: {
  390:     struct interface *ifp;
  391:     babel_interface_nfo *babel_ifp;
  392: 
  393:     ifp = vty->index;
  394:     babel_ifp = babel_get_if_nfo(ifp);
  395: 
  396:     assert (babel_ifp != NULL);
  397:     babel_set_wired_internal(babel_ifp, 0);
  398:     return CMD_SUCCESS;
  399: }
  400: 
  401: /* [Interface Command] Enable split horizon. */
  402: DEFUN (babel_split_horizon,
  403:        babel_split_horizon_cmd,
  404:        "babel split-horizon",
  405:        "Babel interface commands\n"
  406:        "Enable split horizon processing")
  407: {
  408:     struct interface *ifp;
  409:     babel_interface_nfo *babel_ifp;
  410: 
  411:     ifp = vty->index;
  412:     babel_ifp = babel_get_if_nfo(ifp);
  413: 
  414:     assert (babel_ifp != NULL);
  415:     babel_ifp->flags |= BABEL_IF_SPLIT_HORIZON;
  416:     return CMD_SUCCESS;
  417: }
  418: 
  419: /* [Interface Command] Disable split horizon (default). */
  420: DEFUN (no_babel_split_horizon,
  421:        no_babel_split_horizon_cmd,
  422:        "no babel split-horizon",
  423:        NO_STR
  424:        "Babel interface commands\n"
  425:        "Disable split horizon processing")
  426: {
  427:     struct interface *ifp;
  428:     babel_interface_nfo *babel_ifp;
  429: 
  430:     ifp = vty->index;
  431:     babel_ifp = babel_get_if_nfo(ifp);
  432: 
  433:     assert (babel_ifp != NULL);
  434:     babel_ifp->flags &= ~BABEL_IF_SPLIT_HORIZON;
  435:     return CMD_SUCCESS;
  436: }
  437: 
  438: /* [Interface Command]. */
  439: DEFUN (babel_set_hello_interval,
  440:        babel_set_hello_interval_cmd,
  441:        "babel hello-interval <20-655340>",
  442:        "Babel interface commands\n"
  443:        "Time between scheduled hellos\n"
  444:        "Milliseconds\n")
  445: {
  446:     struct interface *ifp;
  447:     babel_interface_nfo *babel_ifp;
  448:     int interval;
  449: 
  450:     VTY_GET_INTEGER_RANGE("milliseconds", interval, argv[0], 20, 10 * 0xFFFE);
  451: 
  452:     ifp = vty->index;
  453:     babel_ifp = babel_get_if_nfo(ifp);
  454:     assert (babel_ifp != NULL);
  455: 
  456:     babel_ifp->hello_interval = interval;
  457:     return CMD_SUCCESS;
  458: }
  459: 
  460: /* [Interface Command]. */
  461: DEFUN (babel_set_update_interval,
  462:        babel_set_update_interval_cmd,
  463:        "babel update-interval <20-655340>",
  464:        "Babel interface commands\n"
  465:        "Time between scheduled updates\n"
  466:        "Milliseconds\n")
  467: {
  468:     struct interface *ifp;
  469:     babel_interface_nfo *babel_ifp;
  470:     int interval;
  471: 
  472:     VTY_GET_INTEGER_RANGE("milliseconds", interval, argv[0], 20, 10 * 0xFFFE);
  473: 
  474:     ifp = vty->index;
  475:     babel_ifp = babel_get_if_nfo(ifp);
  476:     assert (babel_ifp != NULL);
  477: 
  478:     babel_ifp->update_interval = interval;
  479:     return CMD_SUCCESS;
  480: }
  481: 
  482: /* This should be no more than half the hello interval, so that hellos
  483:    aren't sent late.  The result is in milliseconds. */
  484: unsigned
  485: jitter(babel_interface_nfo *babel_ifp, int urgent)
  486: {
  487:     unsigned interval = babel_ifp->hello_interval;
  488:     if(urgent)
  489:         interval = MIN(interval, 100);
  490:     else
  491:         interval = MIN(interval, 4000);
  492:     return roughly(interval) / 4;
  493: }
  494: 
  495: unsigned
  496: update_jitter(babel_interface_nfo *babel_ifp, int urgent)
  497: {
  498:     unsigned interval = babel_ifp->hello_interval;
  499:     if(urgent)
  500:         interval = MIN(interval, 100);
  501:     else
  502:         interval = MIN(interval, 4000);
  503:     return roughly(interval);
  504: }
  505: 
  506: /* calculate babeld's specific datas of an interface (change when the interface
  507:  change) */
  508: static int
  509: interface_recalculate(struct interface *ifp)
  510: {
  511:     babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp);
  512:     unsigned char *tmp = NULL;
  513:     int mtu, rc;
  514:     struct ipv6_mreq mreq;
  515: 
  516:     if (!IS_ENABLE(ifp))
  517:         return -1;
  518: 
  519:     if (!if_is_operative(ifp) || !CHECK_FLAG(ifp->flags, IFF_RUNNING)) {
  520:         interface_reset(ifp);
  521:         return -1;
  522:     }
  523: 
  524:     babel_ifp->flags |= BABEL_IF_IS_UP;
  525: 
  526:     mtu = MIN(ifp->mtu, ifp->mtu6);
  527: 
  528:     /* We need to be able to fit at least two messages into a packet,
  529:      so MTUs below 116 require lower layer fragmentation. */
  530:     /* In IPv6, the minimum MTU is 1280, and every host must be able
  531:      to reassemble up to 1500 bytes, but I'd rather not rely on this. */
  532:     if(mtu < 128) {
  533:         debugf(BABEL_DEBUG_IF, "Suspiciously low MTU %d on interface %s (%d).",
  534:                mtu, ifp->name, ifp->ifindex);
  535:         mtu = 128;
  536:     }
  537: 
  538:     /* 40 for IPv6 header, 8 for UDP header, 12 for good luck. */
  539:     babel_ifp->bufsize = mtu - sizeof(packet_header) - 60;
  540:     tmp = babel_ifp->sendbuf;
  541:     babel_ifp->sendbuf = realloc(babel_ifp->sendbuf, babel_ifp->bufsize);
  542:     if(babel_ifp->sendbuf == NULL) {
  543:         zlog_err("Couldn't reallocate sendbuf.");
  544:         free(tmp);
  545:         babel_ifp->bufsize = 0;
  546:         return -1;
  547:     }
  548:     tmp = NULL;
  549: 
  550:     resize_receive_buffer(mtu);
  551: 
  552:     memset(&mreq, 0, sizeof(mreq));
  553:     memcpy(&mreq.ipv6mr_multiaddr, protocol_group, 16);
  554:     mreq.ipv6mr_interface = ifp->ifindex;
  555: 
  556:     rc = setsockopt(protocol_socket, IPPROTO_IPV6, IPV6_JOIN_GROUP,
  557:                     (char*)&mreq, sizeof(mreq));
  558:     if(rc < 0) {
  559:         zlog_err("setsockopt(IPV6_JOIN_GROUP) on interface '%s': %s",
  560:                  ifp->name, safe_strerror(errno));
  561:         /* This is probably due to a missing link-local address,
  562:          so down this interface, and wait until the main loop
  563:          tries to up it again. */
  564:         interface_reset(ifp);
  565:         return -1;
  566:     }
  567: 
  568:     set_timeout(&babel_ifp->hello_timeout, babel_ifp->hello_interval);
  569:     set_timeout(&babel_ifp->update_timeout, babel_ifp->update_interval);
  570:     send_hello(ifp);
  571:     send_request(ifp, NULL, 0);
  572: 
  573:     update_interface_metric(ifp);
  574: 
  575:     debugf(BABEL_DEBUG_COMMON,
  576:            "Upped interface %s (%s, cost=%d, channel=%d%s).",
  577:            ifp->name,
  578:            (babel_ifp->flags & BABEL_IF_WIRED) ? "wired" : "wireless",
  579:            babel_ifp->cost,
  580:            babel_ifp->channel,
  581:            babel_ifp->ipv4 ? ", IPv4" : "");
  582: 
  583:     if(rc > 0)
  584:         send_update(ifp, 0, NULL, 0);
  585: 
  586:     return 1;
  587: }
  588: 
  589: /* Reset the interface as it was new: it's not removed from the interface list,
  590:  and may be considered as a upped interface. */
  591: static int
  592: interface_reset(struct interface *ifp)
  593: {
  594:     int rc;
  595:     struct ipv6_mreq mreq;
  596:     babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp);
  597: 
  598:     if (!(babel_ifp->flags & BABEL_IF_IS_UP))
  599:         return 0;
  600: 
  601:     debugf(BABEL_DEBUG_IF, "interface reset: %s", ifp->name);
  602:     babel_ifp->flags &= ~BABEL_IF_IS_UP;
  603: 
  604:     flush_interface_routes(ifp, 0);
  605:     babel_ifp->buffered = 0;
  606:     babel_ifp->bufsize = 0;
  607:     free(babel_ifp->sendbuf);
  608:     babel_ifp->num_buffered_updates = 0;
  609:     babel_ifp->update_bufsize = 0;
  610:     if(babel_ifp->buffered_updates)
  611:         free(babel_ifp->buffered_updates);
  612:     babel_ifp->buffered_updates = NULL;
  613:     babel_ifp->sendbuf = NULL;
  614: 
  615:     if(ifp->ifindex > 0) {
  616:         memset(&mreq, 0, sizeof(mreq));
  617:         memcpy(&mreq.ipv6mr_multiaddr, protocol_group, 16);
  618:         mreq.ipv6mr_interface = ifp->ifindex;
  619:         rc = setsockopt(protocol_socket, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
  620:                         (char*)&mreq, sizeof(mreq));
  621:         if(rc < 0)
  622:             zlog_err("setsockopt(IPV6_LEAVE_GROUP) on interface '%s': %s",
  623:                      ifp->name, safe_strerror(errno));
  624:     }
  625: 
  626:     update_interface_metric(ifp);
  627: 
  628:     debugf(BABEL_DEBUG_COMMON,"Upped network %s (%s, cost=%d%s).",
  629:            ifp->name,
  630:            (babel_ifp->flags & BABEL_IF_WIRED) ? "wired" : "wireless",
  631:            babel_ifp->cost,
  632:            babel_ifp->ipv4 ? ", IPv4" : "");
  633: 
  634:     return 1;
  635: }
  636: 
  637: /* Send retraction to all, and reset all interfaces statistics. */
  638: void
  639: babel_interface_close_all(void)
  640: {
  641:     struct interface *ifp = NULL;
  642:     struct listnode *linklist_node = NULL;
  643: 
  644:     FOR_ALL_INTERFACES(ifp, linklist_node) {
  645:         if(!if_up(ifp))
  646:             continue;
  647:         send_wildcard_retraction(ifp);
  648:         /* Make sure that we expire quickly from our neighbours'
  649:          association caches. */
  650:         send_hello_noupdate(ifp, 10);
  651:         flushbuf(ifp);
  652:         usleep(roughly(1000));
  653:         gettime(&babel_now);
  654:     }
  655:     FOR_ALL_INTERFACES(ifp, linklist_node) {
  656:         if(!if_up(ifp))
  657:             continue;
  658:         /* Make sure they got it. */
  659:         send_wildcard_retraction(ifp);
  660:         send_hello_noupdate(ifp, 1);
  661:         flushbuf(ifp);
  662:         usleep(roughly(10000));
  663:         gettime(&babel_now);
  664:         interface_reset(ifp);
  665:     }
  666: }
  667: 
  668: /* return "true" if address is one of our ipv6 addresses */
  669: int
  670: is_interface_ll_address(struct interface *ifp, const unsigned char *address)
  671: {
  672:     struct connected *connected;
  673:     struct listnode *node;
  674: 
  675:     if(!if_up(ifp))
  676:         return 0;
  677: 
  678:     FOR_ALL_INTERFACES_ADDRESSES(ifp, connected, node) {
  679:         if(connected->address->family == AF_INET6 &&
  680:            memcmp(&connected->address->u.prefix6, address, 16) == 0)
  681:             return 1;
  682:     }
  683: 
  684:     return 0;
  685: }
  686: 
  687: static void
  688: show_babel_interface_sub (struct vty *vty, struct interface *ifp)
  689: {
  690:   int is_up;
  691:   babel_interface_nfo *babel_ifp;
  692: 
  693:   vty_out (vty, "%s is %s%s", ifp->name,
  694:     ((is_up = if_is_operative(ifp)) ? "up" : "down"), VTY_NEWLINE);
  695:   vty_out (vty, "  ifindex %u, MTU %u bytes %s%s",
  696:     ifp->ifindex, ifp->mtu, if_flag_dump(ifp->flags), VTY_NEWLINE);
  697: 
  698:   if (babel_enable_if_lookup (ifp->name) < 0)
  699:   {
  700:     vty_out (vty, "  Babel protocol is not enabled on this interface%s", VTY_NEWLINE);
  701:     return;
  702:   }
  703:   if (!is_up)
  704:   {
  705:     vty_out (vty, "  Babel protocol is enabled, but not running on this interface%s", VTY_NEWLINE);
  706:     return;
  707:   }
  708:   babel_ifp = babel_get_if_nfo (ifp);
  709:   vty_out (vty, "  Babel protocol is running on this interface%s", VTY_NEWLINE);
  710:   vty_out (vty, "  Operating mode is \"%s\"%s",
  711:            CHECK_FLAG (babel_ifp->flags, BABEL_IF_WIRED) ? "wired" : "wireless", VTY_NEWLINE);
  712:   vty_out (vty, "  Split horizon mode is %s%s",
  713:            CHECK_FLAG (babel_ifp->flags, BABEL_IF_SPLIT_HORIZON) ? "On" : "Off", VTY_NEWLINE);
  714:   vty_out (vty, "  Hello interval is %u ms%s", babel_ifp->hello_interval, VTY_NEWLINE);
  715:   vty_out (vty, "  Update interval is %u ms%s", babel_ifp->update_interval, VTY_NEWLINE);
  716: }
  717: 
  718: DEFUN (show_babel_interface,
  719:        show_babel_interface_cmd,
  720:        "show babel interface [INTERFACE]",
  721:        SHOW_STR
  722:        IP_STR
  723:        "Babel information\n"
  724:        "Interface information\n"
  725:        "Interface name\n")
  726: {
  727:   struct interface *ifp;
  728:   struct listnode *node;
  729: 
  730:   if (argc == 0)
  731:   {
  732:     for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
  733:       show_babel_interface_sub (vty, ifp);
  734:     return CMD_SUCCESS;
  735:   }
  736:   if ((ifp = if_lookup_by_name (argv[0])) == NULL)
  737:   {
  738:     vty_out (vty, "No such interface name%s", VTY_NEWLINE);
  739:     return CMD_WARNING;
  740:   }
  741:   show_babel_interface_sub (vty, ifp);
  742:   return CMD_SUCCESS;
  743: }
  744: 
  745: static void
  746: show_babel_neighbour_sub (struct vty *vty, struct neighbour *neigh)
  747: {
  748:     vty_out (vty,
  749:              "Neighbour %s dev %s reach %04x rxcost %d txcost %d %s.%s",
  750:              format_address(neigh->address),
  751:              neigh->ifp->name,
  752:              neigh->reach,
  753:              neighbour_rxcost(neigh),
  754:              neigh->txcost,
  755:              if_up(neigh->ifp) ? "" : " (down)",
  756:              VTY_NEWLINE);
  757: }
  758: 
  759: DEFUN (show_babel_neighbour,
  760:        show_babel_neighbour_cmd,
  761:        "show babel neighbour [INTERFACE]",
  762:        SHOW_STR
  763:        IP_STR
  764:        "Babel information\n"
  765:        "Print neighbours\n"
  766:        "Interface name\n")
  767: {
  768:     struct neighbour *neigh;
  769:     struct interface *ifp;
  770: 
  771:     if (argc == 0) {
  772:         FOR_ALL_NEIGHBOURS(neigh) {
  773:             show_babel_neighbour_sub(vty, neigh);
  774:         }
  775:         return CMD_SUCCESS;
  776:     }
  777:     if ((ifp = if_lookup_by_name (argv[0])) == NULL)
  778:     {
  779:         vty_out (vty, "No such interface name%s", VTY_NEWLINE);
  780:         return CMD_WARNING;
  781:     }
  782:     FOR_ALL_NEIGHBOURS(neigh) {
  783:         if(ifp->ifindex == neigh->ifp->ifindex) {
  784:             show_babel_neighbour_sub(vty, neigh);
  785:         }
  786:     }
  787:     return CMD_SUCCESS;
  788: }
  789: 
  790: static void
  791: show_babel_routes_sub (struct babel_route *route, void *closure)
  792: {
  793:     struct vty *vty = (struct vty*) closure;
  794:     const unsigned char *nexthop =
  795:         memcmp(route->nexthop, route->neigh->address, 16) == 0 ?
  796:         NULL : route->nexthop;
  797:     char channels[100];
  798: 
  799:     if(route->channels[0] == 0)
  800:         channels[0] = '\0';
  801:     else {
  802:         int k, j = 0;
  803:         snprintf(channels, 100, " chan (");
  804:         j = strlen(channels);
  805:         for(k = 0; k < DIVERSITY_HOPS; k++) {
  806:             if(route->channels[k] == 0)
  807:                 break;
  808:             if(k > 0)
  809:                 channels[j++] = ',';
  810:             snprintf(channels + j, 100 - j, "%d", route->channels[k]);
  811:             j = strlen(channels);
  812:         }
  813:         snprintf(channels + j, 100 - j, ")");
  814:         if(k == 0)
  815:             channels[0] = '\0';
  816:     }
  817: 
  818:     vty_out(vty,
  819:             "%s metric %d refmetric %d id %s seqno %d%s age %d "
  820:             "via %s neigh %s%s%s%s%s",
  821:             format_prefix(route->src->prefix, route->src->plen),
  822:             route_metric(route), route->refmetric,
  823:             format_eui64(route->src->id),
  824:             (int)route->seqno,
  825:             channels,
  826:             (int)(babel_now.tv_sec - route->time),
  827:             route->neigh->ifp->name,
  828:             format_address(route->neigh->address),
  829:             nexthop ? " nexthop " : "",
  830:             nexthop ? format_address(nexthop) : "",
  831:             route->installed ? " (installed)" :
  832:             route_feasible(route) ? " (feasible)" : "",
  833:             VTY_NEWLINE);
  834: }
  835: 
  836: static void
  837: show_babel_xroutes_sub (struct xroute *xroute, void *closure)
  838: {
  839:     struct vty *vty = (struct vty *) closure;
  840:     vty_out(vty, "%s metric %d (exported)%s",
  841:             format_prefix(xroute->prefix, xroute->plen),
  842:             xroute->metric,
  843:             VTY_NEWLINE);
  844: }
  845: 
  846: DEFUN (show_babel_database,
  847:        show_babel_database_cmd,
  848:        "show babel database",
  849:        SHOW_STR
  850:        IP_STR
  851:        "Babel information\n"
  852:        "Database information\n"
  853:        "No attributes\n")
  854: {
  855:     for_all_routes(show_babel_routes_sub, vty);
  856:     for_all_xroutes(show_babel_xroutes_sub, vty);
  857:     return CMD_SUCCESS;
  858: }
  859: 
  860: DEFUN (show_babel_parameters,
  861:        show_babel_parameters_cmd,
  862:        "show babel parameters",
  863:        SHOW_STR
  864:        IP_STR
  865:        "Babel information\n"
  866:        "Configuration information\n"
  867:        "No attributes\n")
  868: {
  869:     vty_out(vty, "    -- Babel running configuration --%s", VTY_NEWLINE);
  870:     show_babel_main_configuration(vty);
  871:     vty_out(vty, "    -- distribution lists --%s", VTY_NEWLINE);
  872:     config_show_distribute(vty);
  873: 
  874:     return CMD_SUCCESS;
  875: }
  876: 
  877: void
  878: babel_if_init ()
  879: {
  880:     /* initialize interface list */
  881:     if_init();
  882:     if_add_hook (IF_NEW_HOOK,    babel_if_new_hook);
  883:     if_add_hook (IF_DELETE_HOOK, babel_if_delete_hook);
  884: 
  885:     babel_enable_if = vector_init (1);
  886: 
  887:     /* install interface node and commands */
  888:     install_element (CONFIG_NODE, &interface_cmd);
  889:     install_element (CONFIG_NODE, &no_interface_cmd);
  890:     install_node (&babel_interface_node, interface_config_write);
  891:     install_default(INTERFACE_NODE);
  892:     install_element(INTERFACE_NODE, &interface_cmd);
  893:     install_element(INTERFACE_NODE, &no_interface_cmd);
  894: 
  895:     install_element(BABEL_NODE, &babel_network_cmd);
  896:     install_element(BABEL_NODE, &no_babel_network_cmd);
  897:     install_element(INTERFACE_NODE, &babel_split_horizon_cmd);
  898:     install_element(INTERFACE_NODE, &no_babel_split_horizon_cmd);
  899:     install_element(INTERFACE_NODE, &babel_set_wired_cmd);
  900:     install_element(INTERFACE_NODE, &babel_set_wireless_cmd);
  901:     install_element(INTERFACE_NODE, &babel_set_hello_interval_cmd);
  902:     install_element(INTERFACE_NODE, &babel_set_update_interval_cmd);
  903: 
  904:     /* "show babel ..." commands */
  905:     install_element(VIEW_NODE, &show_babel_interface_cmd);
  906:     install_element(ENABLE_NODE, &show_babel_interface_cmd);
  907:     install_element(VIEW_NODE, &show_babel_neighbour_cmd);
  908:     install_element(ENABLE_NODE, &show_babel_neighbour_cmd);
  909:     install_element(VIEW_NODE, &show_babel_database_cmd);
  910:     install_element(ENABLE_NODE, &show_babel_database_cmd);
  911:     install_element(VIEW_NODE, &show_babel_parameters_cmd);
  912:     install_element(ENABLE_NODE, &show_babel_parameters_cmd);
  913: }
  914: 
  915: /* hooks: functions called respectively when struct interface is
  916:  created or deleted. */
  917: static int
  918: babel_if_new_hook (struct interface *ifp)
  919: {
  920:     ifp->info = babel_interface_allocate();
  921:     return 0;
  922: }
  923: 
  924: static int
  925: babel_if_delete_hook (struct interface *ifp)
  926: {
  927:     babel_interface_free(ifp->info);
  928:     ifp->info = NULL;
  929:     return 0;
  930: }
  931: 
  932: /* Output an "interface" section for each of the known interfaces with
  933: babeld-specific statement lines where appropriate. */
  934: static int
  935: interface_config_write (struct vty *vty)
  936: {
  937:     struct listnode *node;
  938:     struct interface *ifp;
  939:     int write = 0;
  940: 
  941:     for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp)) {
  942:         vty_out (vty, "interface %s%s", ifp->name,
  943:                  VTY_NEWLINE);
  944:         if (ifp->desc)
  945:             vty_out (vty, " description %s%s", ifp->desc,
  946:                      VTY_NEWLINE);
  947:         if (IS_ENABLE (ifp))
  948:         {
  949:             babel_interface_nfo *babel_ifp = babel_get_if_nfo (ifp);
  950:             /* wireless/no split-horizon is the default */
  951:             if (CHECK_FLAG (babel_ifp->flags, BABEL_IF_WIRED))
  952:             {
  953:                 vty_out (vty, " babel wired%s", VTY_NEWLINE);
  954:                 write++;
  955:             }
  956:             if (CHECK_FLAG (babel_ifp->flags, BABEL_IF_SPLIT_HORIZON))
  957:             {
  958:                 vty_out (vty, " babel split-horizon%s", VTY_NEWLINE);
  959:                 write++;
  960:             }
  961:             if (babel_ifp->hello_interval != BABEL_DEFAULT_HELLO_INTERVAL)
  962:             {
  963:                 vty_out (vty, " babel hello-interval %u%s", babel_ifp->hello_interval, VTY_NEWLINE);
  964:                 write++;
  965:             }
  966:             if (babel_ifp->update_interval != BABEL_DEFAULT_UPDATE_INTERVAL)
  967:             {
  968:                 vty_out (vty, " babel update-interval %u%s", babel_ifp->update_interval, VTY_NEWLINE);
  969:                 write++;
  970:             }
  971:         }
  972:         vty_out (vty, "!%s", VTY_NEWLINE);
  973:         write++;
  974:     }
  975:     return write;
  976: }
  977: 
  978: /* Output a "network" statement line for each of the enabled interfaces. */
  979: int
  980: babel_enable_if_config_write (struct vty * vty)
  981: {
  982:     unsigned int i, lines = 0;
  983:     char *str;
  984: 
  985:     for (i = 0; i < vector_active (babel_enable_if); i++)
  986:         if ((str = vector_slot (babel_enable_if, i)) != NULL)
  987:         {
  988:             vty_out (vty, " network %s%s", str, VTY_NEWLINE);
  989:             lines++;
  990:         }
  991:     return lines;
  992: }
  993: 
  994: /* functions to allocate or free memory for a babel_interface_nfo, filling
  995:  needed fields */
  996: static babel_interface_nfo *
  997: babel_interface_allocate (void)
  998: {
  999:     babel_interface_nfo *babel_ifp;
 1000:     babel_ifp = XMALLOC(MTYPE_BABEL_IF, sizeof(babel_interface_nfo));
 1001:     if(babel_ifp == NULL)
 1002:         return NULL;
 1003: 
 1004:     /* Here are set the default values for an interface. */
 1005:     memset(babel_ifp, 0, sizeof(babel_interface_nfo));
 1006:     /* All flags are unset */
 1007:     babel_ifp->bucket_time = babel_now.tv_sec;
 1008:     babel_ifp->bucket = BUCKET_TOKENS_MAX;
 1009:     babel_ifp->hello_seqno = (random() & 0xFFFF);
 1010:     babel_ifp->hello_interval = BABEL_DEFAULT_HELLO_INTERVAL;
 1011:     babel_ifp->update_interval = BABEL_DEFAULT_UPDATE_INTERVAL;
 1012:     babel_ifp->channel = BABEL_IF_CHANNEL_INTERFERING;
 1013:     babel_set_wired_internal(babel_ifp, 0);
 1014: 
 1015:     return babel_ifp;
 1016: }
 1017: 
 1018: static void
 1019: babel_interface_free (babel_interface_nfo *babel_ifp)
 1020: {
 1021:     XFREE(MTYPE_BABEL_IF, babel_ifp);
 1022: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>