]> git.proxmox.com Git - mirror_frr.git/commitdiff
Merge branch 'master' into dev-master
authorMitesh Kanjariya <mitesh@cumulusnetworks.com>
Tue, 29 Aug 2017 01:19:03 +0000 (18:19 -0700)
committerGitHub <noreply@github.com>
Tue, 29 Aug 2017 01:19:03 +0000 (18:19 -0700)
176 files changed:
Makefile.am
babeld/babel_interface.c
babeld/babel_zebra.c
babeld/babeld.c
babeld/kernel.c
babeld/message.c
babeld/xroute.c
babeld/xroute.h
bgpd/bgp_attr.h
bgpd/bgp_debug.c
bgpd/bgp_main.c
bgpd/bgp_route.c
bgpd/bgp_route.h
bgpd/bgp_table.h
bgpd/bgp_vty.c
bgpd/bgp_zebra.c
bgpd/bgpd.c
bgpd/bgpd.h
bgpd/rfapi/rfapi_import.c
bgpd/rfapi/vnc_debug.c
bgpd/rfapi/vnc_zebra.c
common.am
configure.ac
doc/code/.gitignore [new file with mode: 0644]
doc/code/Makefile [new file with mode: 0644]
doc/code/conf.py [new file with mode: 0644]
doc/code/hooks.rst [new file with mode: 0644]
doc/code/index.rst [new file with mode: 0644]
doc/code/library.rst [new file with mode: 0644]
doc/code/memtypes.rst [new file with mode: 0644]
eigrpd/eigrp_dump.c
eigrpd/eigrp_fsm.c
eigrpd/eigrp_fsm.h
eigrpd/eigrp_hello.c
eigrpd/eigrp_interface.c
eigrpd/eigrp_main.c
eigrpd/eigrp_neighbor.c
eigrpd/eigrp_neighbor.h
eigrpd/eigrp_network.c
eigrpd/eigrp_network.h
eigrpd/eigrp_packet.c
eigrpd/eigrp_packet.h
eigrpd/eigrp_query.c
eigrpd/eigrp_reply.c
eigrpd/eigrp_siaquery.c
eigrpd/eigrp_siareply.c
eigrpd/eigrp_structs.h
eigrpd/eigrp_topology.c
eigrpd/eigrp_topology.h
eigrpd/eigrp_update.c
eigrpd/eigrp_vty.c
eigrpd/eigrp_zebra.c
eigrpd/eigrp_zebra.h
git-reindent-branch.py
isisd/isis_bpf.c
isisd/isis_circuit.c
isisd/isis_vty.c
isisd/isis_zebra.c
isisd/isisd.c
isisd/isisd.h
ldpd/control.h
ldpd/lde.h
ldpd/ldp_vty_cmds.c
ldpd/ldp_zebra.c
ldpd/ldpd.c
ldpd/ldpd.h
ldpd/ldpe.h
lib/command.c
lib/command_match.c
lib/compiler.h [new file with mode: 0644]
lib/freebsd-queue.h [new file with mode: 0644]
lib/frr_zmq.c [new file with mode: 0644]
lib/frr_zmq.h [new file with mode: 0644]
lib/grammar_sandbox.c
lib/hash.c
lib/hook.c
lib/hook.h
lib/if.c
lib/if.h
lib/imsg-buffer.c
lib/imsg.c
lib/libfrr.c
lib/libfrr.h
lib/log.c
lib/memory.c
lib/memory.h
lib/module.c
lib/mpls.h
lib/plist.c
lib/plist.h
lib/prefix.c
lib/prefix.h
lib/privs.c
lib/queue.h
lib/sigevent.c
lib/spf_backoff.c
lib/subdir.am
lib/table.c
lib/table.h
lib/termtable.c
lib/vty.h
lib/workqueue.c
lib/workqueue.h
lib/zclient.c
lib/zclient.h
nhrpd/nhrp_interface.c
nhrpd/nhrp_main.c
nhrpd/nhrp_nhs.c
nhrpd/nhrp_route.c
nhrpd/nhrp_vty.c
ospf6d/ospf6_abr.c
ospf6d/ospf6_area.c
ospf6d/ospf6_area.h
ospf6d/ospf6_interface.c
ospf6d/ospf6_main.c
ospf6d/ospf6_route.c
ospf6d/ospf6_route.h
ospf6d/ospf6_top.c
ospf6d/ospf6_zebra.c
ospf6d/ospf6d.c
ospf6d/ospf6d.h
ospfd/ospf_dump.c
ospfd/ospf_interface.c
ospfd/ospf_packet.c
ospfd/ospf_vty.c
ospfd/ospf_zebra.c
pimd/pim_cmd.c
pimd/pim_ifchannel.c
pimd/pim_ifchannel.h
pimd/pim_join.c
pimd/pim_upstream.c
python/clidef.py
python/clippy/__init__.py
redhat/frr.spec.in
ripd/rip_debug.c
ripd/rip_interface.c
ripd/rip_zebra.c
ripngd/ripng_debug.c
ripngd/ripng_interface.c
ripngd/ripng_zebra.c
tests/.gitignore
tests/Makefile.am
tests/isisd/test_fuzz_isis_tlv.c
tests/lib/cli/common_cli.c
tests/lib/cli/test_commands.py
tests/lib/test_zmq.c [new file with mode: 0644]
tests/lib/test_zmq.py [new file with mode: 0644]
tests/lib/test_zmq.refout [new file with mode: 0644]
tools/frr
tools/frr-reload.py
vtysh/vtysh.c
vtysh/vtysh_config.c
zebra/debug.c
zebra/interface.c
zebra/interface.h
zebra/irdp.h
zebra/irdp_interface.c
zebra/irdp_main.c
zebra/irdp_packet.c
zebra/kernel_socket.c
zebra/main.c
zebra/redistribute.c
zebra/rt_socket.c
zebra/rtadv.c
zebra/rtadv.h
zebra/subdir.am
zebra/zebra_fpm.c
zebra/zebra_mpls.c
zebra/zebra_mpls.h
zebra/zebra_mpls_openbsd.c
zebra/zebra_pw.c
zebra/zebra_rib.c
zebra/zebra_static.c
zebra/zebra_static.h
zebra/zebra_vty.c
zebra/zserv.c

index 494fcd4d5690b03560882d68366a17231a9faa89..f204f8a724b7b0f4e248a7a27dbcf7e096339aed 100644 (file)
@@ -5,7 +5,7 @@ include common.am
 
 AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir) -I$(top_builddir)/lib
 AM_CFLAGS = $(WERROR)
-DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\"
+DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\" -DCONFDATE=$(CONFDATE)
 LIBCAP = @LIBCAP@
 
 EXTRA_DIST =
@@ -25,6 +25,14 @@ pkginclude_HEADERS =
 nodist_pkginclude_HEADERS =
 dist_examples_DATA =
 
+## libtool, the self-made GNU scourge
+## ... this should fix relinking
+## ... and AUTOMAKE_DUMMY is needed to prevent automake from treating this
+##     as overriding the normal targets...
+$(AUTOMAKE_DUMMY)install-moduleLTLIBRARIES: install-libLTLIBRARIES
+$(AUTOMAKE_DUMMY)install-binPROGRAMS: install-libLTLIBRARIES
+$(AUTOMAKE_DUMMY)install-sbinPROGRAMS: install-libLTLIBRARIES
+
 include lib/subdir.am
 include zebra/subdir.am
 include qpb/subdir.am
index 1ae33b3a27af7a6b49f077ca8f913e29de7ca5d5..9fa32ee6fa6f8acf2b1e03d24e744e9f0b391f03 100644 (file)
@@ -1256,8 +1256,8 @@ void
 babel_if_init ()
 {
     /* initialize interface list */
-    if_add_hook (IF_NEW_HOOK,    babel_if_new_hook);
-    if_add_hook (IF_DELETE_HOOK, babel_if_delete_hook);
+    hook_register_prio(if_add, 0, babel_if_new_hook);
+    hook_register_prio(if_del, 0, babel_if_delete_hook);
 
     babel_enable_if = vector_init (1);
 
index 11b9c5956c24cb1666bc3ac990e544e037028403..337b7b3927163e40a52e998aa6484b302b9188d0 100644 (file)
@@ -37,7 +37,6 @@ void babelz_zebra_init(void);
 
 /* we must use a pointer because of zclient.c's functions (new, free). */
 struct zclient *zclient;
-static int zebra_config_write (struct vty *vty);
 
 /* Debug types */
 static struct {
@@ -55,118 +54,24 @@ static struct {
     {0, 0, NULL}
 };
 
-/* Zebra node structure. */
-struct cmd_node zebra_node =
-{
-    ZEBRA_NODE,
-    "%s(config-router)# ",
-    1 /* vtysh? yes */
-};
-
-
-/* Zebra route add and delete treatment (ipv6). */
+/* Zebra route add and delete treatment. */
 static int
-babel_zebra_read_ipv6 (int command, struct zclient *zclient,
-                      zebra_size_t length, vrf_id_t vrf)
+babel_zebra_read_route (int command, struct zclient *zclient,
+                       zebra_size_t length, vrf_id_t vrf)
 {
-    struct stream *s;
-    struct zapi_ipv6 api;
-    unsigned long ifindex = -1;
-    struct in6_addr nexthop;
-    struct prefix_ipv6 prefix;
-
-    s = zclient->ibuf;
-    ifindex = 0;
-    memset (&nexthop, 0, sizeof (struct in6_addr));
-    memset (&api, 0, sizeof(struct zapi_ipv6));
-    memset (&prefix, 0, sizeof (struct prefix_ipv6));
-
-    /* Type, flags, message. */
-    api.type = stream_getc (s);
-    api.instance = stream_getw (s);
-    api.flags = stream_getl (s);
-    api.message = stream_getc (s);
-
-    /* IPv6 prefix. */
-    prefix.family = AF_INET6;
-    prefix.prefixlen = stream_getc (s);
-    stream_get (&prefix.prefix, s, PSIZE (prefix.prefixlen));
-
-    /* Nexthop, ifindex, distance, metric. */
-    if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) {
-        api.nexthop_num = stream_getc (s);
-        stream_get (&nexthop, s, sizeof(nexthop));
-    }
-    if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) {
-        api.ifindex_num = stream_getc (s);
-        ifindex = stream_getl (s);
-    }
-    if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
-        api.distance = stream_getc (s);
-    else
-        api.distance = 0;
-    if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
-        api.metric = stream_getl (s);
-    else
-        api.metric = 0;
+    struct zapi_route api;
 
-    if (command == ZEBRA_REDISTRIBUTE_IPV6_ADD)
-        babel_ipv6_route_add(&api, &prefix, ifindex, &nexthop);
-    else
-        babel_ipv6_route_delete(&api, &prefix, ifindex);
+    if (zapi_route_decode(zclient->ibuf, &api) < 0)
+        return -1;
 
-    return 0;
-}
+    /* we completely ignore srcdest routes for now. */
+    if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
+        return 0;
 
-static int
-babel_zebra_read_ipv4 (int command, struct zclient *zclient,
-                      zebra_size_t length, vrf_id_t vrf)
-{
-    struct stream *s;
-    struct zapi_ipv4 api;
-    unsigned long ifindex = -1;
-    struct in_addr nexthop;
-    struct prefix_ipv4 prefix;
-
-    s = zclient->ibuf;
-    ifindex = 0;
-    memset (&nexthop, 0, sizeof (struct in_addr));
-    memset (&api, 0, sizeof(struct zapi_ipv4));
-    memset (&prefix, 0, sizeof (struct prefix_ipv4));
-
-    /* Type, flags, message. */
-    api.type = stream_getc (s);
-    api.instance = stream_getw (s);
-    api.flags = stream_getl (s);
-    api.message = stream_getc (s);
-
-    /* IPv6 prefix. */
-    prefix.family = AF_INET;
-    prefix.prefixlen = stream_getc (s);
-    stream_get (&prefix.prefix, s, PSIZE (prefix.prefixlen));
-
-    /* Nexthop, ifindex, distance, metric. */
-    if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) {
-        api.nexthop_num = stream_getc (s);
-        stream_get (&nexthop, s, sizeof(nexthop));
-    }
-    if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) {
-        api.ifindex_num = stream_getc (s);
-        ifindex = stream_getl (s);
-    }
-    if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
-        api.distance = stream_getc (s);
-    else
-        api.distance = 0;
-    if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
-        api.metric = stream_getl (s);
-    else
-        api.metric = 0;
-
-    if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD) {
-        babel_ipv4_route_add(&api, &prefix, ifindex, &nexthop);
+    if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD) {
+        babel_route_add(&api);
     } else {
-        babel_ipv4_route_delete(&api, &prefix, ifindex);
+        babel_route_delete(&api);
     }
 
     return 0;
@@ -310,6 +215,20 @@ debug_babel_config_write (struct vty * vty)
 #endif /* NO_DEBUG */
 }
 
+DEFUN_NOSH (show_debugging_babel,
+           show_debugging_babel_cmd,
+           "show debugging [babel]",
+           SHOW_STR
+           DEBUG_STR
+           "Babel")
+{
+       vty_out(vty, "BABEL debugging status\n");
+
+       debug_babel_config_write(vty);
+
+       return CMD_SUCCESS;
+}
+
 static void
 babel_zebra_connected (struct zclient *zclient)
 {
@@ -328,34 +247,16 @@ void babelz_zebra_init(void)
     zclient->interface_down = babel_interface_down;
     zclient->interface_address_add = babel_interface_address_add;
     zclient->interface_address_delete = babel_interface_address_delete;
-    zclient->redistribute_route_ipv4_add = babel_zebra_read_ipv4;
-    zclient->redistribute_route_ipv4_del = babel_zebra_read_ipv4;
-    zclient->redistribute_route_ipv6_add = babel_zebra_read_ipv6;
-    zclient->redistribute_route_ipv6_del = babel_zebra_read_ipv6;
+    zclient->redistribute_route_add = babel_zebra_read_route;
+    zclient->redistribute_route_del = babel_zebra_read_route;
 
-    install_node (&zebra_node, zebra_config_write);
     install_element(BABEL_NODE, &babel_redistribute_type_cmd);
     install_element(ENABLE_NODE, &debug_babel_cmd);
     install_element(ENABLE_NODE, &no_debug_babel_cmd);
     install_element(CONFIG_NODE, &debug_babel_cmd);
     install_element(CONFIG_NODE, &no_debug_babel_cmd);
-}
 
-static int
-zebra_config_write (struct vty *vty)
-{
-    if (! zclient->enable)
-    {
-        vty_out (vty, "no router zebra\n");
-        return 1;
-    }
-    else if (! vrf_bitmap_check (zclient->redist[AFI_IP][ZEBRA_ROUTE_BABEL], VRF_DEFAULT))
-    {
-        vty_out (vty, "router zebra\n");
-        vty_out (vty, " no redistribute babel\n");
-        return 1;
-    }
-    return 0;
+    install_element(VIEW_NODE, &show_debugging_babel_cmd);
 }
 
 void
index f995745e415c873a1e2a513f9e6ee214b05eb88f..207c37d9b1f44bf4319d623954b0218fcb295abd 100644 (file)
@@ -331,8 +331,8 @@ babel_main_loop(struct thread *thread)
         /* if there is no timeout, we must wait. */
         if(timeval_compare(&tv, &babel_now) > 0) {
             timeval_minus(&tv, &tv, &babel_now);
-            debugf(BABEL_DEBUG_TIMEOUT, "babel main loop : timeout: %ld msecs",
-                   tv.tv_sec * 1000 + tv.tv_usec / 1000);
+            debugf(BABEL_DEBUG_TIMEOUT, "babel main loop : timeout: %lld msecs",
+                   (long long)tv.tv_sec * 1000 + tv.tv_usec / 1000);
             /* it happens often to have less than 1 ms, it's bad. */
             timeval_add_msec(&tv, &tv, 300);
             babel_set_timer(&tv);
index 26860f3bae6ede6fa59ab44ad1b4acbe1b424e88..394d7b1e816e3af4192485da0961b4f0b2aef499 100644 (file)
@@ -51,13 +51,8 @@ THE SOFTWARE.
 
 
 static int
-kernel_route_v4(int add, const unsigned char *pref, unsigned short plen,
-                const unsigned char *gate, int ifindex,
-                unsigned int metric);
-static int
-kernel_route_v6(int add, const unsigned char *pref, unsigned short plen,
-                const unsigned char *gate, int ifindex,
-                unsigned int metric);
+zebra_route(int add, int familt, const unsigned char *pref, unsigned short plen,
+            const unsigned char *gate, int ifindex, unsigned int metric);
 
 int
 kernel_interface_operational(struct interface *interface)
@@ -84,7 +79,7 @@ kernel_route(int operation, const unsigned char *pref, unsigned short plen,
              unsigned int newmetric)
 {
     int rc;
-    int ipv4;
+    int family;
 
     /* Check that the protocol family is consistent. */
     if(plen >= 96 && v4mapped(pref)) {
@@ -92,46 +87,37 @@ kernel_route(int operation, const unsigned char *pref, unsigned short plen,
             errno = EINVAL;
             return -1;
         }
-        ipv4 = 1;
+        family = AF_INET;
     } else {
         if(v4mapped(gate)) {
             errno = EINVAL;
             return -1;
         }
-        ipv4 = 0;
+        family = AF_INET6;
     }
 
     switch (operation) {
         case ROUTE_ADD:
-            return ipv4 ?
-                   kernel_route_v4(1, pref, plen, gate, ifindex, metric):
-                   kernel_route_v6(1, pref, plen, gate, ifindex, metric);
+            return zebra_route(1, family, pref, plen, gate, ifindex, metric);
             break;
         case ROUTE_FLUSH:
-            return ipv4 ?
-                   kernel_route_v4(0, pref, plen, gate, ifindex, metric):
-                   kernel_route_v6(0, pref, plen, gate, ifindex, metric);
+            return zebra_route(0, family, pref, plen, gate, ifindex, metric);
             break;
         case ROUTE_MODIFY:
             if(newmetric == metric && memcmp(newgate, gate, 16) == 0 &&
                newifindex == ifindex)
                 return 0;
             debugf(BABEL_DEBUG_ROUTE, "Modify route: delete old; add new.");
-            rc = ipv4 ?
-                kernel_route_v4(0, pref, plen, gate, ifindex, metric):
-                kernel_route_v6(0, pref, plen, gate, ifindex, metric);
-
+            rc = zebra_route(0, family, pref, plen, gate, ifindex, metric);
             if (rc < 0)
                 return -1;
 
-            rc = ipv4 ?
-                kernel_route_v4(1, pref, plen, newgate, newifindex, newmetric):
-                kernel_route_v6(1, pref, plen, newgate, newifindex, newmetric);
-
+            rc = zebra_route(1, family, pref, plen, newgate, newifindex,
+                             newmetric);
             return rc;
             break;
         default:
-            zlog_err("this should never appens (false value - kernel_route)");
+            zlog_err("this should never happen (false value - kernel_route)");
             assert(0);
             exit(1);
             break;
@@ -139,110 +125,81 @@ kernel_route(int operation, const unsigned char *pref, unsigned short plen,
 }
 
 static int
-kernel_route_v4(int add,
-                const unsigned char *pref, unsigned short plen,
-                const unsigned char *gate, int ifindex, unsigned int metric)
+zebra_route(int add, int family, const unsigned char *pref, unsigned short plen,
+            const unsigned char *gate, int ifindex, unsigned int metric)
 {
     struct zapi_route api;               /* quagga's communication system */
     struct prefix quagga_prefix;         /* quagga's prefix */
-    struct in_addr babel_prefix_addr;    /* babeld's prefix addr */
-    struct nexthop nexthop;              /* next router to go */
-    struct nexthop *nexthop_pointer = &nexthop; /* it's an array! */
+    union g_addr babel_prefix_addr;      /* babeld's prefix addr */
+    struct zapi_nexthop *api_nh;         /* next router to go - no ECMP */
 
-    /* convert to be understandable by quagga */
-    /* convert given addresses */
-    uchar_to_inaddr(&babel_prefix_addr, pref);
-    uchar_to_inaddr(&nexthop.gate.ipv4, gate);
-
-    /* make prefix structure */
-    memset (&quagga_prefix, 0, sizeof(quagga_prefix));
-    quagga_prefix.family = AF_INET;
-    IPV4_ADDR_COPY (&quagga_prefix.u.prefix4, &babel_prefix_addr);
-    quagga_prefix.prefixlen = plen - 96; /* our plen is for v4mapped's addr */
-    apply_mask(&quagga_prefix);
-
-    memset(&api, 0, sizeof(api));
-    api.type  = ZEBRA_ROUTE_BABEL;
-    api.flags = 0;
-    api.message = 0;
-    api.instance = 0;
-    api.safi = SAFI_UNICAST;
-    api.vrf_id = VRF_DEFAULT;
-
-    SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
-    if(metric >= KERNEL_INFINITY) {
-        api.flags = ZEBRA_FLAG_REJECT;
-        api.nexthop_num = 0;
-    } else {
-        api.nexthop_num = 1;
-        api.nexthop = &nexthop_pointer;
-        nexthop.ifindex = ifindex;
-        if (IPV4_ADDR_SAME (&nexthop.gate.ipv4, &quagga_prefix.u.prefix4) &&
-                quagga_prefix.prefixlen == 32) {
-            nexthop.type = NEXTHOP_TYPE_IFINDEX;
-        } else {
-            nexthop.type = NEXTHOP_TYPE_IPV4_IFINDEX;
-        }
-        SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
-        api.metric = metric;
-    }
-
-    debugf(BABEL_DEBUG_ROUTE, "%s route (ipv4) to zebra",
-           add ? "adding" : "removing" );
-    return zapi_route (add ? ZEBRA_IPV4_ROUTE_ADD :
-                       ZEBRA_IPV4_ROUTE_DELETE,
-                       zclient, &quagga_prefix, NULL, &api);
-}
-
-static int
-kernel_route_v6(int add, const unsigned char *pref, unsigned short plen,
-                const unsigned char *gate, int ifindex, unsigned int metric)
-{
-    struct zapi_route api;              /* quagga's communication system */
-    struct prefix quagga_prefix;        /* quagga's prefix */
-    struct in6_addr babel_prefix_addr;  /* babeld's prefix addr */
-    struct nexthop nexthop;             /* next router to go */
-    struct nexthop *nexthop_pointer = &nexthop;
+    api_nh = &api.nexthops[0];
 
     /* convert to be understandable by quagga */
     /* convert given addresses */
-    uchar_to_in6addr(&babel_prefix_addr, pref);
-    uchar_to_in6addr(&nexthop.gate.ipv6, gate);
+    switch (family) {
+    case AF_INET:
+        uchar_to_inaddr(&babel_prefix_addr.ipv4, pref);
+        break;
+    case AF_INET6:
+        uchar_to_in6addr(&babel_prefix_addr.ipv6, pref);
+        break;
+    }
 
     /* make prefix structure */
     memset (&quagga_prefix, 0, sizeof(quagga_prefix));
-    quagga_prefix.family = AF_INET6;
-    IPV6_ADDR_COPY (&quagga_prefix.u.prefix6, &babel_prefix_addr);
-    quagga_prefix.prefixlen = plen;
+    quagga_prefix.family = family;
+    switch (family) {
+    case AF_INET:
+        IPV4_ADDR_COPY (&quagga_prefix.u.prefix4, &babel_prefix_addr.ipv4);
+        /* our plen is for v4mapped's addr */
+        quagga_prefix.prefixlen = plen - 96;
+        break;
+    case AF_INET6:
+        IPV6_ADDR_COPY (&quagga_prefix.u.prefix6, &babel_prefix_addr.ipv6);
+        quagga_prefix.prefixlen = plen;
+        break;
+    }
     apply_mask(&quagga_prefix);
 
     memset(&api, 0, sizeof(api));
     api.type  = ZEBRA_ROUTE_BABEL;
-    api.flags = 0;
-    api.message = 0;
-    api.instance = 0;
     api.safi = SAFI_UNICAST;
     api.vrf_id = VRF_DEFAULT;
+    api.prefix = quagga_prefix;
 
     if(metric >= KERNEL_INFINITY) {
         api.flags = ZEBRA_FLAG_REJECT;
-        api.nexthop_num = 0;
     } else {
         SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
         api.nexthop_num = 1;
-        api.nexthop = &nexthop_pointer;
-        nexthop.ifindex = ifindex;
-        /* difference to IPv4: always leave the linklocal as nexthop */
-        nexthop.type = NEXTHOP_TYPE_IPV6_IFINDEX;
+        api_nh->ifindex = ifindex;
+
+        switch (family) {
+        case AF_INET:
+            uchar_to_inaddr(&api_nh->gate.ipv4, gate);
+            if (IPV4_ADDR_SAME (&api_nh->gate.ipv4, &quagga_prefix.u.prefix4) &&
+                    quagga_prefix.prefixlen == 32) {
+                api_nh->type = NEXTHOP_TYPE_IFINDEX;
+            } else {
+                api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX;
+            }
+            break;
+        case AF_INET6:
+            uchar_to_in6addr(&api_nh->gate.ipv6, gate);
+            /* difference to IPv4: always leave the linklocal as nexthop */
+            api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
+            break;
+        }
         SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
         api.metric = metric;
     }
 
-    debugf(BABEL_DEBUG_ROUTE, "%s route (ipv6) to zebra",
-           add ? "adding" : "removing" );
-    return zapi_route (add ? ZEBRA_IPV6_ROUTE_ADD :
-                       ZEBRA_IPV6_ROUTE_DELETE,
-                       zclient, &quagga_prefix, NULL, &api);
+    debugf(BABEL_DEBUG_ROUTE, "%s route (%s) to zebra",
+           add ? "adding" : "removing",
+           (family == AF_INET) ? "ipv4" : "ipv6");
+    return zclient_route_send (add ? ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE,
+                               zclient, &api);
 }
 
 int
index 5990373b6932625b967202e065fa31e8dae85bf3..e31d5de5df64326c26dce6c2b293e52d96ab31f7 100644 (file)
@@ -391,7 +391,7 @@ parse_packet(const unsigned char *from, struct interface *ifp,
         } else if(type == MESSAGE_HELLO) {
             unsigned short seqno, interval;
             int changed;
-            unsigned int timestamp;
+            unsigned int timestamp = 0;
             DO_NTOHS(seqno, message + 4);
             DO_NTOHS(interval, message + 6);
             debugf(BABEL_DEBUG_COMMON,"Received hello %d (%d) from %s on %s.",
index 2e123564ea267dcc13fe5940411a06591d2bd341..88e9479e4b868f27440c2d7b5eff18085a28cc55 100644 (file)
@@ -43,63 +43,54 @@ static int numxroutes = 0, maxxroutes = 0;
 
 /* Add redistributed route to Babel table. */
 int
-babel_ipv4_route_add (struct zapi_ipv4 *api, struct prefix_ipv4 *prefix,
-                      unsigned int ifindex, struct in_addr *nexthop)
+babel_route_add (struct zapi_route *api)
 {
     unsigned char uchar_prefix[16];
 
-    inaddr_to_uchar(uchar_prefix, &prefix->prefix);
-    debugf(BABEL_DEBUG_ROUTE, "Adding new ipv4 route coming from Zebra.");
-    xroute_add_new_route(uchar_prefix, prefix->prefixlen + 96,
-                         api->metric, ifindex, 0, 1);
-    return 0;
-}
-
-/* Remove redistributed route from Babel table. */
-int
-babel_ipv4_route_delete (struct zapi_ipv4 *api, struct prefix_ipv4 *prefix,
-                         unsigned int ifindex)
-{
-    unsigned char uchar_prefix[16];
-    struct xroute *xroute = NULL;
-
-    inaddr_to_uchar(uchar_prefix, &prefix->prefix);
-    xroute = find_xroute(uchar_prefix, prefix->prefixlen + 96);
-    if (xroute != NULL) {
-        debugf(BABEL_DEBUG_ROUTE, "Removing ipv4 route (from zebra).");
-        flush_xroute(xroute);
+    switch (api->prefix.family) {
+    case AF_INET:
+        inaddr_to_uchar(uchar_prefix, &api->prefix.u.prefix4);
+        debugf(BABEL_DEBUG_ROUTE, "Adding new ipv4 route coming from Zebra.");
+        xroute_add_new_route(uchar_prefix, api->prefix.prefixlen + 96,
+                             api->metric, api->nexthops[0].ifindex, 0, 1);
+        break;
+    case AF_INET6:
+        in6addr_to_uchar(uchar_prefix, &api->prefix.u.prefix6);
+        debugf(BABEL_DEBUG_ROUTE, "Adding new ipv6 route coming from Zebra.");
+        xroute_add_new_route(uchar_prefix, api->prefix.prefixlen,
+                             api->metric, api->nexthops[0].ifindex, 0, 1);
+        break;
     }
-    return 0;
-}
 
-/* Add redistributed route to Babel table. */
-int
-babel_ipv6_route_add (struct zapi_ipv6 *api, struct prefix_ipv6 *prefix,
-                      unsigned int ifindex, struct in6_addr *nexthop)
-{
-    unsigned char uchar_prefix[16];
-
-    in6addr_to_uchar(uchar_prefix, &prefix->prefix);
-    debugf(BABEL_DEBUG_ROUTE, "Adding new route coming from Zebra.");
-    xroute_add_new_route(uchar_prefix, prefix->prefixlen, api->metric, ifindex,
-                         0, 1);
     return 0;
 }
 
 /* Remove redistributed route from Babel table. */
 int
-babel_ipv6_route_delete (struct zapi_ipv6 *api, struct prefix_ipv6 *prefix,
-                         unsigned int ifindex)
+babel_route_delete (struct zapi_route *api)
 {
     unsigned char uchar_prefix[16];
     struct xroute *xroute = NULL;
 
-    in6addr_to_uchar(uchar_prefix, &prefix->prefix);
-    xroute = find_xroute(uchar_prefix, prefix->prefixlen);
-    if (xroute != NULL) {
-        debugf(BABEL_DEBUG_ROUTE, "Removing route (from zebra).");
-        flush_xroute(xroute);
+    switch (api->prefix.family) {
+    case AF_INET:
+        inaddr_to_uchar(uchar_prefix, &api->prefix.u.prefix4);
+        xroute = find_xroute(uchar_prefix, api->prefix.prefixlen + 96);
+        if (xroute != NULL) {
+            debugf(BABEL_DEBUG_ROUTE, "Removing ipv4 route (from zebra).");
+            flush_xroute(xroute);
+        }
+        break;
+    case AF_INET6:
+        in6addr_to_uchar(uchar_prefix, &api->prefix.u.prefix6);
+        xroute = find_xroute(uchar_prefix, api->prefix.prefixlen);
+        if (xroute != NULL) {
+            debugf(BABEL_DEBUG_ROUTE, "Removing ipv6 route (from zebra).");
+            flush_xroute(xroute);
+        }
+        break;
     }
+
     return 0;
 }
 
index 27899e62a1a9055e142f5f1c6e4acc472815a336..59afccb5904f2de673e29b3a2bbc3c8a39237606 100644 (file)
@@ -36,14 +36,8 @@ struct xroute_stream;
 
 struct xroute *find_xroute(const unsigned char *prefix, unsigned char plen);
 void flush_xroute(struct xroute *xroute);
-int babel_ipv4_route_add (struct zapi_ipv4 *api, struct prefix_ipv4 *prefix,
-                          unsigned int ifindex, struct in_addr *nexthop);
-int babel_ipv4_route_delete (struct zapi_ipv4 *api, struct prefix_ipv4 *prefix,
-                             unsigned int ifindex);
-int babel_ipv6_route_add (struct zapi_ipv6 *api, struct prefix_ipv6 *prefix,
-                          unsigned int ifindex, struct in6_addr *nexthop);
-int babel_ipv6_route_delete (struct zapi_ipv6 *api, struct prefix_ipv6 *prefix,
-                             unsigned int ifindex);
+int babel_route_add (struct zapi_route *api);
+int babel_route_delete (struct zapi_route *api);
 int xroutes_estimate(void);
 struct xroute_stream *xroute_stream(void);
 struct xroute *xroute_stream_next(struct xroute_stream *stream);
index 324813c085dcea24220b38d0224957772ec0f6f1..4dd38459f81742dc3f32b69f3886d937abd7ab09 100644 (file)
@@ -72,7 +72,7 @@ struct bgp_attr_encap_subtlv {
        unsigned long refcnt;
        uint16_t type;
        uint16_t length;
-       uint8_t value[1]; /* will be extended */
+       uint8_t value[0]; /* will be extended */
 };
 
 #if ENABLE_BGP_VNC
index bcb3c5fc1860f1ae7761eea93dd7f217cbc373d5..c1c4f2b39cda7ffe1ed3e291543a427ac8f1eb50 100644 (file)
@@ -1615,12 +1615,12 @@ DEFUN (no_debug_bgp,
        return CMD_SUCCESS;
 }
 
-DEFUN (show_debugging_bgp,
-       show_debugging_bgp_cmd,
-       "show debugging bgp",
-       SHOW_STR
-       DEBUG_STR
-       BGP_STR)
+DEFUN_NOSH (show_debugging_bgp,
+           show_debugging_bgp_cmd,
+           "show debugging [bgp]",
+           SHOW_STR
+           DEBUG_STR
+           BGP_STR)
 {
        vty_out(vty, "BGP debugging status:\n");
 
index 25a562ed68f9c944a4d25e3db77dd770e83210e8..fa8c45b004a849e6e804fe7cd14ed53a2ac81518 100644 (file)
@@ -140,11 +140,8 @@ __attribute__((__noreturn__)) void sigint(void)
 {
        zlog_notice("Terminating on signal");
 
-       if (!retain_mode) {
+       if (!retain_mode)
                bgp_terminate();
-               if (bgpd_privs.user) /* NULL if skip_runas flag set */
-                       zprivs_terminate(&bgpd_privs);
-       }
 
        bgp_exit(0);
 
@@ -172,13 +169,12 @@ static __attribute__((__noreturn__)) void bgp_exit(int status)
        /* it only makes sense for this to be called on a clean exit */
        assert(status == 0);
 
+       frr_early_fini();
+
        bfd_gbl_exit();
 
        bgp_close();
 
-       if (retain_mode)
-               if_add_hook(IF_DELETE_HOOK, NULL);
-
        /* reverse bgp_master_init */
        for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
                bgp_delete(bgp);
@@ -214,24 +210,15 @@ static __attribute__((__noreturn__)) void bgp_exit(int status)
        community_list_terminate(bgp_clist);
 
        bgp_vrf_terminate();
-       cmd_terminate();
-       vty_terminate();
 #if ENABLE_BGP_VNC
        vnc_zebra_destroy();
 #endif
        bgp_zebra_destroy();
 
-       /* reverse bgp_master_init */
-       if (bm->master)
-               thread_master_free(bm->master);
-
-       closezlog();
-
        list_delete(bm->bgp);
        memset(bm, 0, sizeof(*bm));
 
-       if (bgp_debug_count())
-               log_memstats_stderr("bgpd");
+       frr_fini();
        exit(status);
 }
 
index 36063af7cda06e2e8ab161c893e33dcf2fb61599..b18ed9c71f2bf725777d116bfbb9e30ce297c3f1 100644 (file)
@@ -20,6 +20,7 @@
  */
 
 #include <zebra.h>
+#include <math.h>
 
 #include "prefix.h"
 #include "linklist.h"
@@ -2001,18 +2002,15 @@ int bgp_zebra_has_route_changed(struct bgp_node *rn, struct bgp_info *selected)
 
 struct bgp_process_queue {
        struct bgp *bgp;
-       struct bgp_node *rn;
-       afi_t afi;
-       safi_t safi;
+       STAILQ_HEAD(, bgp_node)pqueue;
+#define BGP_PROCESS_QUEUE_EOIU_MARKER          (1 << 0)
+       unsigned int flags;
+       unsigned int queued;
 };
 
-static wq_item_status bgp_process_main(struct work_queue *wq, void *data)
+static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
+                                afi_t afi, safi_t safi)
 {
-       struct bgp_process_queue *pq = data;
-       struct bgp *bgp = pq->bgp;
-       struct bgp_node *rn = pq->rn;
-       afi_t afi = pq->afi;
-       safi_t safi = pq->safi;
        struct prefix *p = &rn->p;
        struct bgp_info *new_select;
        struct bgp_info *old_select;
@@ -2033,7 +2031,7 @@ static wq_item_status bgp_process_main(struct work_queue *wq, void *data)
                bgp->main_peers_update_hold = 0;
 
                bgp_start_routeadv(bgp);
-               return WQ_SUCCESS;
+               return;
        }
 
        /* Best path selection. */
@@ -2045,11 +2043,9 @@ static wq_item_status bgp_process_main(struct work_queue *wq, void *data)
        /* Do we need to allocate or free labels?
         * Right now, since we only deal with per-prefix labels, it is not
         * necessary to do this upon changes to best path except if the label
-        * index changes.
-        * NOTE: This is only relevant for the default instance.
+        * index changes
         */
-       if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
-           && safi == SAFI_UNICAST) {
+       if (bgp->allocate_mpls_labels[afi][safi]) {
                if (new_select) {
                        if (!old_select
                            || bgp_label_index_differs(new_select, old_select)
@@ -2070,8 +2066,11 @@ static wq_item_status bgp_process_main(struct work_queue *wq, void *data)
                                } else
                                        bgp_register_for_label(rn, new_select);
                        }
-               } else if (CHECK_FLAG(rn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
+               } else if (CHECK_FLAG(rn->flags, BGP_NODE_REGISTERED_FOR_LABEL)) {
                        bgp_unregister_for_label(rn);
+               }
+       } else if (CHECK_FLAG(rn->flags, BGP_NODE_REGISTERED_FOR_LABEL)) {
+               bgp_unregister_for_label(rn);
        }
 
        /* If best route remains the same and this is not due to user-initiated
@@ -2115,7 +2114,7 @@ static wq_item_status bgp_process_main(struct work_queue *wq, void *data)
                }
 
                UNSET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED);
-               return WQ_SUCCESS;
+               return;
        }
 
        /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
@@ -2193,21 +2192,42 @@ static wq_item_status bgp_process_main(struct work_queue *wq, void *data)
                bgp_info_reap(rn, old_select);
 
        UNSET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED);
-       return WQ_SUCCESS;
+       return;
 }
 
-static void bgp_processq_del(struct work_queue *wq, void *data)
+static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
 {
-       struct bgp_process_queue *pq = data;
+       struct bgp_process_queue *pqnode = data;
+       struct bgp *bgp = pqnode->bgp;
        struct bgp_table *table;
+       struct bgp_node *rn, *nrn;
+
+       /* eoiu marker */
+       if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
+               bgp_process_main_one(bgp, NULL, 0, 0);
+
+               return WQ_SUCCESS;
+       }
+
+       STAILQ_FOREACH_SAFE(rn, &pqnode->pqueue, pq, nrn) {
+               table = bgp_node_table(rn);
+
+               bgp_process_main_one(bgp, rn, table->afi, table->safi);
 
-       bgp_unlock(pq->bgp);
-       if (pq->rn) {
-               table = bgp_node_table(pq->rn);
-               bgp_unlock_node(pq->rn);
+               bgp_unlock_node(rn);
                bgp_table_unlock(table);
        }
-       XFREE(MTYPE_BGP_PROCESS_QUEUE, pq);
+
+       return WQ_SUCCESS;
+}
+
+static void bgp_processq_del(struct work_queue *wq, void *data)
+{
+       struct bgp_process_queue *pqnode = data;
+
+       bgp_unlock(pqnode->bgp);
+
+       XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
 }
 
 void bgp_process_queue_init(void)
@@ -2222,7 +2242,7 @@ void bgp_process_queue_init(void)
                }
        }
 
-       bm->process_main_queue->spec.workfunc = &bgp_process_main;
+       bm->process_main_queue->spec.workfunc = &bgp_process_wq;
        bm->process_main_queue->spec.del_item_data = &bgp_processq_del;
        bm->process_main_queue->spec.max_retries = 0;
        bm->process_main_queue->spec.hold = 50;
@@ -2230,31 +2250,56 @@ void bgp_process_queue_init(void)
        bm->process_main_queue->spec.yield = 50 * 1000L;
 }
 
+static struct bgp_process_queue *bgp_process_queue_work(struct work_queue *wq,
+                                                       struct bgp *bgp)
+{
+       struct bgp_process_queue *pqnode;
+
+       pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE, sizeof(struct bgp_process_queue));
+
+       /* unlocked in bgp_processq_del */
+       pqnode->bgp = bgp_lock(bgp);
+       STAILQ_INIT(&pqnode->pqueue);
+
+       work_queue_add(wq, pqnode);
+
+       return pqnode;
+}
+
 void bgp_process(struct bgp *bgp, struct bgp_node *rn, afi_t afi, safi_t safi)
 {
+#define ARBITRARY_PROCESS_QLEN         10000
+       struct work_queue *wq = bm->process_main_queue;
        struct bgp_process_queue *pqnode;
 
        /* already scheduled for processing? */
        if (CHECK_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED))
                return;
 
-       if (bm->process_main_queue == NULL)
+       if (wq == NULL)
                return;
 
-       pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
-                        sizeof(struct bgp_process_queue));
-       if (!pqnode)
-               return;
+       /* Add route nodes to an existing work queue item until reaching the
+          limit only if is from the same BGP view and it's not an EOIU marker */
+       if (work_queue_item_count(wq)) {
+               struct work_queue_item *item = work_queue_last_item(wq);
+               pqnode = item->data;
 
-       /* all unlocked in bgp_processq_del */
+               if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER) ||
+                   pqnode->bgp != bgp || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
+                       pqnode = bgp_process_queue_work(wq, bgp);
+       } else
+               pqnode = bgp_process_queue_work(wq, bgp);
+
+       /* all unlocked in bgp_process_wq */
        bgp_table_lock(bgp_node_table(rn));
-       pqnode->rn = bgp_lock_node(rn);
-       pqnode->bgp = bgp;
-       bgp_lock(bgp);
-       pqnode->afi = afi;
-       pqnode->safi = safi;
-       work_queue_add(bm->process_main_queue, pqnode);
+
        SET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED);
+       bgp_lock_node(rn);
+
+       STAILQ_INSERT_TAIL(&pqnode->pqueue, rn, pq);
+       pqnode->queued++;
+
        return;
 }
 
@@ -2265,15 +2310,9 @@ void bgp_add_eoiu_mark(struct bgp *bgp)
        if (bm->process_main_queue == NULL)
                return;
 
-       pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
-                        sizeof(struct bgp_process_queue));
-       if (!pqnode)
-               return;
+       pqnode = bgp_process_queue_work(bm->process_main_queue, bgp);
 
-       pqnode->rn = NULL;
-       pqnode->bgp = bgp;
-       bgp_lock(bgp);
-       work_queue_add(bm->process_main_queue, pqnode);
+       SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
 }
 
 static int bgp_maximum_prefix_restart_timer(struct thread *thread)
@@ -6050,8 +6089,7 @@ DEFUN (no_ipv6_aggregate_address,
 
 /* Redistribute route treatment. */
 void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
-                         const struct in_addr *nexthop,
-                         const struct in6_addr *nexthop6, unsigned int ifindex,
+                         const union g_addr *nexthop, unsigned int ifindex,
                          u_int32_t metric, u_char type, u_short instance,
                          route_tag_t tag)
 {
@@ -6067,14 +6105,17 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
 
        /* Make default attribute. */
        bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
-       if (nexthop)
-               attr.nexthop = *nexthop;
-       attr.nh_ifindex = ifindex;
-
-       if (nexthop6) {
-               attr.mp_nexthop_global = *nexthop6;
-               attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
+       if (nexthop) {
+               switch (p->family) {
+               case AF_INET:
+                       attr.nexthop = nexthop->ipv4;
+                       break;
+               case AF_INET6:
+                       attr.mp_nexthop_global = nexthop->ipv6;
+                       attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
+               }
        }
+       attr.nh_ifindex = ifindex;
 
        attr.med = metric;
        attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
@@ -8002,7 +8043,8 @@ static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
 static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
                                  const char *prefix, afi_t afi, safi_t safi,
                                  enum bgp_show_type type);
-static int bgp_show_regexp(struct vty *vty, const char *regstr, afi_t afi,
+static int bgp_show_regexp(struct vty *vty, struct bgp *bgp,
+                          const char *regstr, afi_t afi,
                           safi_t safi, enum bgp_show_type type);
 static int bgp_show_community(struct vty *vty, struct bgp *bgp, int argc,
                              struct cmd_token **argv, int exact, afi_t afi,
@@ -8820,32 +8862,28 @@ DEFUN (show_ip_bgp_large_community,
 static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
                           safi_t safi);
 
-/* BGP route print out function. */
+
+/* BGP route print out function without JSON */
 DEFUN (show_ip_bgp,
        show_ip_bgp_cmd,
        "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
-          [<\
-             cidr-only\
-             |dampening <flap-statistics|dampened-paths|parameters>\
-             |route-map WORD\
-             |prefix-list WORD\
-             |filter-list WORD\
-             |statistics\
-             |community [<AA:NN|local-AS|no-advertise|no-export> [exact-match]]\
-             |community-list <(1-500)|WORD> [exact-match]\
-             |A.B.C.D/M longer-prefixes\
-             |X:X::X:X/M longer-prefixes>\
-          ] [json]",
+          <dampening <parameters>\
+           |route-map WORD\
+           |prefix-list WORD\
+           |filter-list WORD\
+           |statistics\
+           |community <AA:NN|local-AS|no-advertise|no-export> [exact-match]\
+           |community-list <(1-500)|WORD> [exact-match]\
+           |A.B.C.D/M longer-prefixes\
+           |X:X::X:X/M longer-prefixes\
+         >",
        SHOW_STR
        IP_STR
        BGP_STR
        BGP_INSTANCE_HELP_STR
        BGP_AFI_HELP_STR
        BGP_SAFI_WITH_LABEL_HELP_STR
-       "Display only routes with non-natural netmasks\n"
        "Display detailed information about dampening\n"
-       "Display flap statistics of routes\n"
-       "Display paths suppressed due to dampening\n"
        "Display detail of configured dampening parameters\n"
        "Display routes matching the route-map\n"
        "A route-map to match on\n"
@@ -8867,13 +8905,11 @@ DEFUN (show_ip_bgp,
        "IPv4 prefix\n"
        "Display route and more specific routes\n"
        "IPv6 prefix\n"
-       "Display route and more specific routes\n"
-       JSON_STR)
+       "Display route and more specific routes\n")
 {
        afi_t afi = AFI_IP6;
        safi_t safi = SAFI_UNICAST;
        int exact_match = 0;
-       enum bgp_show_type sh_type = bgp_show_type_normal;
        struct bgp *bgp = NULL;
        int idx = 0;
 
@@ -8882,23 +8918,8 @@ DEFUN (show_ip_bgp,
        if (!idx)
                return CMD_WARNING;
 
-       int uj = use_json(argc, argv);
-       if (uj)
-               argc--;
-
-       if (argv_find(argv, argc, "cidr-only", &idx))
-               return bgp_show(vty, bgp, afi, safi, bgp_show_type_cidr_only,
-                               NULL, uj);
-
        if (argv_find(argv, argc, "dampening", &idx)) {
-               if (argv_find(argv, argc, "dampened-paths", &idx))
-                       return bgp_show(vty, bgp, afi, safi,
-                                       bgp_show_type_dampend_paths, NULL, uj);
-               else if (argv_find(argv, argc, "flap-statistics", &idx))
-                       return bgp_show(vty, bgp, afi, safi,
-                                       bgp_show_type_flap_statistics, NULL,
-                                       uj);
-               else if (argv_find(argv, argc, "parameters", &idx))
+               if (argv_find(argv, argc, "parameters", &idx))
                        return bgp_show_dampening_parameters(vty, afi, safi);
        }
 
@@ -8927,10 +8948,6 @@ DEFUN (show_ip_bgp,
                        return bgp_show_community(vty, bgp, argc, argv,
                                                  exact_match, afi, safi);
                }
-               /* show all communities */
-               else
-                       return bgp_show(vty, bgp, afi, safi,
-                                       bgp_show_type_community_all, NULL, uj);
        }
 
        if (argv_find(argv, argc, "community-list", &idx)) {
@@ -8947,6 +8964,66 @@ DEFUN (show_ip_bgp,
                                              safi,
                                              bgp_show_type_prefix_longer);
 
+       return CMD_WARNING;
+}
+
+/* BGP route print out function with JSON */
+DEFUN (show_ip_bgp_json,
+       show_ip_bgp_json_cmd,
+       "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
+          [<\
+             cidr-only\
+             |dampening <flap-statistics|dampened-paths>\
+             |community \
+          >] [json]",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       BGP_INSTANCE_HELP_STR
+       BGP_AFI_HELP_STR
+       BGP_SAFI_WITH_LABEL_HELP_STR
+       "Display only routes with non-natural netmasks\n"
+       "Display detailed information about dampening\n"
+       "Display flap statistics of routes\n"
+       "Display paths suppressed due to dampening\n"
+       "Display routes matching the communities\n"
+       JSON_STR)
+{
+       afi_t afi = AFI_IP6;
+       safi_t safi = SAFI_UNICAST;
+       enum bgp_show_type sh_type = bgp_show_type_normal;
+       struct bgp *bgp = NULL;
+       int idx = 0;
+
+       bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
+                                           &bgp);
+       if (!idx)
+               return CMD_WARNING;
+
+       int uj = use_json(argc, argv);
+       if (uj)
+               argc--;
+
+       if (argv_find(argv, argc, "cidr-only", &idx))
+               return bgp_show(vty, bgp, afi, safi, bgp_show_type_cidr_only,
+                               NULL, uj);
+
+       if (argv_find(argv, argc, "dampening", &idx)) {
+               if (argv_find(argv, argc, "dampened-paths", &idx))
+                       return bgp_show(vty, bgp, afi, safi,
+                                       bgp_show_type_dampend_paths, NULL, uj);
+               else if (argv_find(argv, argc, "flap-statistics", &idx))
+                       return bgp_show(vty, bgp, afi, safi,
+                                       bgp_show_type_flap_statistics, NULL,
+                                       uj);
+       }
+
+       if (argv_find(argv, argc, "community", &idx)) {
+               /* show all communities */
+               return bgp_show(vty, bgp, afi, safi,
+                               bgp_show_type_community_all, NULL, uj);
+       }
+
        if (safi == SAFI_MPLS_VPN)
                return bgp_show_mpls_vpn(vty, afi, NULL, bgp_show_type_normal,
                                         NULL, 0, uj);
@@ -9056,7 +9133,7 @@ DEFUN (show_ip_bgp_regexp,
        idx++;
 
        char *regstr = argv_concat(argv, argc, idx);
-       int rc = bgp_show_regexp(vty, (const char *)regstr, afi, safi,
+       int rc = bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
                                 bgp_show_type_regexp);
        XFREE(MTYPE_TMP, regstr);
        return rc;
@@ -9091,7 +9168,8 @@ DEFUN (show_ip_bgp_instance_all,
        return CMD_SUCCESS;
 }
 
-static int bgp_show_regexp(struct vty *vty, const char *regstr, afi_t afi,
+static int bgp_show_regexp(struct vty *vty, struct bgp *bgp,
+                          const char *regstr, afi_t afi,
                           safi_t safi, enum bgp_show_type type)
 {
        regex_t *regex;
@@ -9103,7 +9181,7 @@ static int bgp_show_regexp(struct vty *vty, const char *regstr, afi_t afi,
                return CMD_WARNING;
        }
 
-       rc = bgp_show(vty, NULL, afi, safi, type, regex, 0);
+       rc = bgp_show(vty, bgp, afi, safi, type, regex, 0);
        bgp_regex_free(regex);
        return rc;
 }
@@ -9332,6 +9410,7 @@ static const char *table_stats_strs[] = {
 struct bgp_table_stats {
        struct bgp_table *table;
        unsigned long long counts[BGP_STATS_MAX];
+       double total_space;
 };
 
 #if 0
@@ -9400,8 +9479,8 @@ static int bgp_table_stats_walker(struct thread *t)
                        ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
                        /* announced address space */
                        if (space)
-                               ts->counts[BGP_STATS_SPACE] +=
-                                       1 << (space - rn->p.prefixlen);
+                               ts->total_space += pow(2.0,
+                                                      space - rn->p.prefixlen);
                } else if (prn->info)
                        ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
 
@@ -9511,31 +9590,26 @@ static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
                        break;
                case BGP_STATS_SPACE:
                        vty_out(vty, "%-30s: ", table_stats_strs[i]);
-                       vty_out(vty, "%12llu\n", ts.counts[i]);
-                       if (ts.counts[BGP_STATS_MAXBITLEN] < 9)
-                               break;
-                       vty_out(vty, "%30s: ", "%% announced ");
-                       vty_out(vty, "%12.2f\n",
-                               100 * (float)ts.counts[BGP_STATS_SPACE]
-                                       / (float)((uint64_t)1UL
-                                                 << ts.counts
-                                                            [BGP_STATS_MAXBITLEN]));
-                       vty_out(vty, "%30s: ", "/8 equivalent ");
-                       vty_out(vty, "%12.2f\n",
-                               (float)ts.counts[BGP_STATS_SPACE]
-                                       / (float)(1UL
-                                                 << (ts.counts
-                                                             [BGP_STATS_MAXBITLEN]
-                                                     - 8)));
-                       if (ts.counts[BGP_STATS_MAXBITLEN] < 25)
-                               break;
-                       vty_out(vty, "%30s: ", "/24 equivalent ");
-                       vty_out(vty, "%12.2f",
-                               (float)ts.counts[BGP_STATS_SPACE]
-                                       / (float)(1UL
-                                                 << (ts.counts
-                                                             [BGP_STATS_MAXBITLEN]
-                                                     - 24)));
+                       vty_out(vty, "%12g\n", ts.total_space);
+
+                       if (afi == AFI_IP6) {
+                               vty_out(vty, "%30s: ", "/32 equivalent ");
+                               vty_out(vty, "%12g\n",
+                                       ts.total_space * pow(2.0, -128+32));
+                               vty_out(vty, "%30s: ", "/48 equivalent ");
+                               vty_out(vty, "%12g\n",
+                                       ts.total_space * pow(2.0, -128+48));
+                       } else {
+                               vty_out(vty, "%30s: ", "% announced ");
+                               vty_out(vty, "%12.2f\n",
+                                       ts.total_space * 100. * pow(2.0, -32));
+                               vty_out(vty, "%30s: ", "/8 equivalent ");
+                               vty_out(vty, "%12.2f\n",
+                                       ts.total_space * pow(2.0, -32+8));
+                               vty_out(vty, "%30s: ", "/24 equivalent ");
+                               vty_out(vty, "%12.2f\n",
+                                       ts.total_space * pow(2.0, -32+24));
+                       }
                        break;
                default:
                        vty_out(vty, "%-30s: ", table_stats_strs[i]);
@@ -11265,6 +11339,7 @@ void bgp_route_init(void)
        /* IPv4 labeled-unicast configuration.  */
        install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
        install_element(VIEW_NODE, &show_ip_bgp_cmd);
+       install_element(VIEW_NODE, &show_ip_bgp_json_cmd);
        install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
        install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
 
index 93d79e5059a95bf98b28746a299625ca0f490acd..1767494ac1f06d934d056e36e2670259c2a6fa7b 100644 (file)
@@ -22,6 +22,7 @@
 #define _QUAGGA_BGP_ROUTE_H
 
 #include "queue.h"
+#include "nexthop.h"
 #include "bgp_table.h"
 
 struct bgp_nexthop_cache;
@@ -328,8 +329,7 @@ extern int bgp_nlri_parse_ip(struct peer *, struct attr *, struct bgp_nlri *);
 extern int bgp_maximum_prefix_overflow(struct peer *, afi_t, safi_t, int);
 
 extern void bgp_redistribute_add(struct bgp *, struct prefix *,
-                                const struct in_addr *,
-                                const struct in6_addr *, unsigned int ifindex,
+                                const union g_addr *, unsigned int ifindex,
                                 u_int32_t, u_char, u_short, route_tag_t);
 extern void bgp_redistribute_delete(struct bgp *, struct prefix *, u_char,
                                    u_short);
index 0d5706f7cb60fc34cf7e4c741aea52797d9fa7bc..a4f3b604c24c9effb4eda5a327bbde952add81be 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "mpls.h"
 #include "table.h"
+#include "queue.h"
 
 struct bgp_table {
        /* afi/safi of this table */
@@ -52,6 +53,8 @@ struct bgp_node {
 
        struct bgp_node *prn;
 
+       STAILQ_ENTRY(bgp_node) pq;
+
        mpls_label_t local_label;
 
        uint64_t version;
index c333d4df2cd913632e7c72373d8c07de34d0c11c..761c58641532ffeeee6e62c613e47b2842c109fe 100644 (file)
@@ -6145,6 +6145,8 @@ DEFUN (clear_ip_bgp_all,
        IP_STR
        BGP_STR
        BGP_INSTANCE_HELP_STR
+       BGP_AFI_HELP_STR
+       BGP_SAFI_WITH_LABEL_HELP_STR
        "Clear all peers\n"
        "BGP neighbor address to clear\n"
        "BGP IPv6 neighbor to clear\n"
@@ -6153,8 +6155,6 @@ DEFUN (clear_ip_bgp_all,
        "Clear all external peers\n"
        "Clear all members of peer-group\n"
        "BGP peer-group name\n"
-       BGP_AFI_HELP_STR
-       BGP_SAFI_WITH_LABEL_HELP_STR
        BGP_SOFT_STR
        BGP_SOFT_IN_STR
        BGP_SOFT_OUT_STR
@@ -7071,26 +7071,6 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
        return CMD_SUCCESS;
 }
 
-/*
- * Return if we have a peer configured to use this afi/safi
- */
-static int bgp_show_summary_afi_safi_peer_exists(struct bgp *bgp, int afi,
-                                                int safi)
-{
-       struct listnode *node;
-       struct peer *peer;
-
-       for (ALL_LIST_ELEMENTS_RO(bgp->peer, node, peer)) {
-               if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
-                       continue;
-
-               if (peer->afc[afi][safi])
-                       return 1;
-       }
-
-       return 0;
-}
-
 static void bgp_show_summary_afi_safi(struct vty *vty, struct bgp *bgp, int afi,
                                      int safi, u_char use_json,
                                      json_object *json)
@@ -7109,8 +7089,7 @@ static void bgp_show_summary_afi_safi(struct vty *vty, struct bgp *bgp, int afi,
                if (safi_wildcard)
                        safi = 1; /* SAFI_UNICAST */
                while (safi < SAFI_MAX) {
-                       if (bgp_show_summary_afi_safi_peer_exists(bgp, afi,
-                                                                 safi)) {
+                       if (bgp_afi_safi_peer_exists(bgp, afi, safi)) {
                                json_output = true;
                                if (is_wildcard) {
                                        /*
index 2fc75ea5a23c4f9075ba541fbac71a7be4ea7a40..9a092404d58297b539508a0c0e9452c09b9fa5f8 100644 (file)
 /* All information about zebra. */
 struct zclient *zclient = NULL;
 
-/* Growable buffer for nexthops sent to zebra */
-struct stream *bgp_nexthop_buf = NULL;
-struct stream *bgp_ifindices_buf = NULL;
-struct stream *bgp_label_buf = NULL;
-
 /* These array buffers are used in making a copy of the attributes for
    route-map apply. Arrays are being used here to minimize mallocs and
    frees for the temporary copy of the attributes.
@@ -559,75 +554,36 @@ static int bgp_interface_vrf_update(int command, struct zclient *zclient,
 }
 
 /* Zebra route add and delete treatment. */
-static int zebra_read_ipv4(int command, struct zclient *zclient,
-                          zebra_size_t length, vrf_id_t vrf_id)
+static int zebra_read_route(int command, struct zclient *zclient,
+                           zebra_size_t length, vrf_id_t vrf_id)
 {
-       struct stream *s;
-       struct zapi_ipv4 api;
-       struct in_addr nexthop;
-       struct prefix_ipv4 p;
+       struct zapi_route api;
+       union g_addr nexthop;
        unsigned int ifindex;
-       int i;
+       int add, i;
        struct bgp *bgp;
 
        bgp = bgp_lookup_by_vrf_id(vrf_id);
        if (!bgp)
                return 0;
 
-       s = zclient->ibuf;
-       nexthop.s_addr = 0;
-
-       /* Type, flags, message. */
-       api.type = stream_getc(s);
-       api.instance = stream_getw(s);
-       api.flags = stream_getl(s);
-       api.message = stream_getc(s);
-
-       /* IPv4 prefix. */
-       memset(&p, 0, sizeof(struct prefix_ipv4));
-       p.family = AF_INET;
-       p.prefixlen = MIN(IPV4_MAX_PREFIXLEN, stream_getc(s));
-       stream_get(&p.prefix, s, PSIZE(p.prefixlen));
-
-       /* Nexthop, ifindex, distance, metric. */
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) {
-               api.nexthop_num = stream_getc(s);
-               nexthop.s_addr = stream_get_ipv4(s);
-       }
-
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) {
-               api.ifindex_num = stream_getc(s);
-               ifindex = stream_getl(s); /* ifindex, unused */
-       } else {
-               ifindex = 0;
-       }
-
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE))
-               api.distance = stream_getc(s);
+       if (zapi_route_decode(zclient->ibuf, &api) < 0)
+               return -1;
 
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC))
-               api.metric = stream_getl(s);
-       else
-               api.metric = 0;
+       /* we completely ignore srcdest routes for now. */
+       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
+               return 0;
 
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG))
-               api.tag = stream_getl(s);
-       else
-               api.tag = 0;
+       /* ignore link-local address. */
+       if (api.prefix.family == AF_INET6
+           && IN6_IS_ADDR_LINKLOCAL(&api.prefix.u.prefix6))
+               return 0;
 
-       if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD) {
-               if (bgp_debug_zebra((struct prefix *)&p)) {
-                       char buf[2][INET_ADDRSTRLEN];
-                       zlog_debug(
-                               "Rx IPv4 route add VRF %u %s[%d] %s/%d nexthop %s metric %u tag %" ROUTE_TAG_PRI,
-                               vrf_id, zebra_route_string(api.type),
-                               api.instance, inet_ntop(AF_INET, &p.prefix,
-                                                       buf[0], sizeof(buf[0])),
-                               p.prefixlen, inet_ntop(AF_INET, &nexthop,
-                                                      buf[1], sizeof(buf[1])),
-                               api.metric, api.tag);
-               }
+       nexthop = api.nexthops[0].gate;
+       ifindex = api.nexthops[0].ifindex;
 
+       add = (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD);
+       if (add) {
                /*
                 * The ADD message is actually an UPDATE and there is no
                 * explicit DEL
@@ -639,156 +595,30 @@ static int zebra_read_ipv4(int command, struct zclient *zclient,
                 */
                for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
                        if (i != api.type)
-                               bgp_redistribute_delete(bgp,
-                                                       (struct prefix *)&p, i,
+                               bgp_redistribute_delete(bgp, &api.prefix, i,
                                                        api.instance);
                }
 
                /* Now perform the add/update. */
-               bgp_redistribute_add(bgp, (struct prefix *)&p, &nexthop, NULL,
-                                    ifindex, api.metric, api.type,
-                                    api.instance, api.tag);
-       } else if (command == ZEBRA_REDISTRIBUTE_IPV4_DEL) {
-               if (bgp_debug_zebra((struct prefix *)&p)) {
-                       char buf[2][INET_ADDRSTRLEN];
-                       zlog_debug(
-                               "Rx IPv4 route delete VRF %u %s[%d] %s/%d "
-                               "nexthop %s metric %u tag %" ROUTE_TAG_PRI,
-                               vrf_id, zebra_route_string(api.type),
-                               api.instance, inet_ntop(AF_INET, &p.prefix,
-                                                       buf[0], sizeof(buf[0])),
-                               p.prefixlen, inet_ntop(AF_INET, &nexthop,
-                                                      buf[1], sizeof(buf[1])),
-                               api.metric, api.tag);
-               }
-               bgp_redistribute_delete(bgp, (struct prefix *)&p, api.type,
-                                       api.instance);
-       }
-
-       return 0;
-}
-
-/* Zebra route add and delete treatment. */
-static int zebra_read_ipv6(int command, struct zclient *zclient,
-                          zebra_size_t length, vrf_id_t vrf_id)
-{
-       struct stream *s;
-       struct zapi_ipv6 api;
-       struct in6_addr nexthop;
-       struct prefix_ipv6 p, src_p;
-       unsigned int ifindex;
-       int i;
-       struct bgp *bgp;
-
-       bgp = bgp_lookup_by_vrf_id(vrf_id);
-       if (!bgp)
-               return 0;
-
-       s = zclient->ibuf;
-       memset(&nexthop, 0, sizeof(struct in6_addr));
-
-       /* Type, flags, message. */
-       api.type = stream_getc(s);
-       api.instance = stream_getw(s);
-       api.flags = stream_getl(s);
-       api.message = stream_getc(s);
-
-       /* IPv6 prefix. */
-       memset(&p, 0, sizeof(struct prefix_ipv6));
-       p.family = AF_INET6;
-       p.prefixlen = MIN(IPV6_MAX_PREFIXLEN, stream_getc(s));
-       stream_get(&p.prefix, s, PSIZE(p.prefixlen));
-
-       memset(&src_p, 0, sizeof(struct prefix_ipv6));
-       src_p.family = AF_INET6;
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) {
-               src_p.prefixlen = stream_getc(s);
-               stream_get(&src_p.prefix, s, PSIZE(src_p.prefixlen));
-       }
-
-       if (src_p.prefixlen)
-               /* we completely ignore srcdest routes for now. */
-               return 0;
-
-       /* Nexthop, ifindex, distance, metric. */
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) {
-               api.nexthop_num = stream_getc(s);
-               stream_get(&nexthop, s, 16);
-       }
-
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) {
-               api.ifindex_num = stream_getc(s);
-               ifindex = stream_getl(s); /* ifindex, unused */
+               bgp_redistribute_add(bgp, &api.prefix, &nexthop, ifindex,
+                                    api.metric, api.type, api.instance,
+                                    api.tag);
        } else {
-               ifindex = 0;
+               bgp_redistribute_delete(bgp, &api.prefix, api.type,
+                                       api.instance);
        }
 
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE))
-               api.distance = stream_getc(s);
-       else
-               api.distance = 0;
-
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC))
-               api.metric = stream_getl(s);
-       else
-               api.metric = 0;
-
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG))
-               api.tag = stream_getl(s);
-       else
-               api.tag = 0;
-
-       /* Simply ignore link-local address. */
-       if (IN6_IS_ADDR_LINKLOCAL(&p.prefix))
-               return 0;
-
-       if (command == ZEBRA_REDISTRIBUTE_IPV6_ADD) {
-               if (bgp_debug_zebra((struct prefix *)&p)) {
-                       char buf[2][INET6_ADDRSTRLEN];
-                       zlog_debug(
-                               "Rx IPv6 route add VRF %u %s[%d] %s/%d nexthop %s metric %u tag %" ROUTE_TAG_PRI,
-                               vrf_id, zebra_route_string(api.type),
-                               api.instance, inet_ntop(AF_INET6, &p.prefix,
-                                                       buf[0], sizeof(buf[0])),
-                               p.prefixlen, inet_ntop(AF_INET, &nexthop,
-                                                      buf[1], sizeof(buf[1])),
-                               api.metric, api.tag);
-               }
-
-               /*
-                * The ADD message is actually an UPDATE and there is no
-                * explicit DEL
-                * for a prior redistributed route, if any. So, perform an
-                * implicit
-                * DEL processing for the same redistributed route from any
-                * other
-                * source type.
-                */
-               for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
-                       if (i != api.type)
-                               bgp_redistribute_delete(bgp,
-                                                       (struct prefix *)&p, i,
-                                                       api.instance);
-               }
-
-               bgp_redistribute_add(bgp, (struct prefix *)&p, NULL, &nexthop,
-                                    ifindex, api.metric, api.type,
-                                    api.instance, api.tag);
-       } else if (command == ZEBRA_REDISTRIBUTE_IPV6_DEL) {
-               if (bgp_debug_zebra((struct prefix *)&p)) {
-                       char buf[2][INET6_ADDRSTRLEN];
-                       zlog_debug(
-                               "Rx IPv6 route delete VRF %u %s[%d] %s/%d "
-                               "nexthop %s metric %u tag %" ROUTE_TAG_PRI,
-                               vrf_id, zebra_route_string(api.type),
-                               api.instance, inet_ntop(AF_INET6, &p.prefix,
-                                                       buf[0], sizeof(buf[0])),
-                               p.prefixlen, inet_ntop(AF_INET6, &nexthop,
-                                                      buf[1], sizeof(buf[1])),
-                               api.metric, api.tag);
-               }
-               bgp_redistribute_delete(bgp, (struct prefix *)&p, api.type,
-                                       api.instance);
+       if (bgp_debug_zebra(&api.prefix)) {
+               char buf[2][PREFIX_STRLEN];
+
+               prefix2str(&api.prefix, buf[0], sizeof(buf[0]));
+               inet_ntop(api.prefix.family, &nexthop, buf[1], sizeof(buf[1]));
+               zlog_debug(
+                       "Rx route %s VRF %u %s[%d] %s "
+                       "nexthop %s metric %u tag %" ROUTE_TAG_PRI,
+                       (add) ? "add" : "delete", vrf_id,
+                       zebra_route_string(api.type), api.instance, buf[0],
+                       buf[1], api.metric, api.tag);
        }
 
        return 0;
@@ -1153,7 +983,11 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
                        struct bgp_info *info, struct bgp *bgp, afi_t afi,
                        safi_t safi)
 {
-       u_int32_t flags;
+       struct zapi_route api;
+       struct zapi_nexthop *api_nh;
+       int nh_family;
+       int valid_nh_count = 0;
+       int has_valid_label = 0;
        u_char distance;
        struct peer *peer;
        struct bgp_info *mpinfo;
@@ -1169,18 +1003,17 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
        if (!bgp_install_info_to_zebra(bgp))
                return;
 
-       if ((p->family == AF_INET
-            && !vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_BGP],
-                                 bgp->vrf_id))
-           || (p->family == AF_INET6
-               && !vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_BGP],
-                                    bgp->vrf_id)))
-               return;
-
        if (bgp->main_zebra_update_hold)
                return;
 
-       flags = 0;
+       /* Make Zebra API structure. */
+       memset(&api, 0, sizeof(api));
+       api.vrf_id = bgp->vrf_id;
+       api.type = ZEBRA_ROUTE_BGP;
+       api.safi = safi;
+       api.prefix = *p;
+       SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
+
        peer = info->peer;
 
        tag = info->attr->tag;
@@ -1189,40 +1022,39 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
         * in
         * the RIB */
        if (info->sub_type == BGP_ROUTE_AGGREGATE)
-               SET_FLAG(flags, ZEBRA_FLAG_BLACKHOLE);
+               SET_FLAG(api.flags, ZEBRA_FLAG_BLACKHOLE);
 
        if (peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED
            || info->sub_type == BGP_ROUTE_AGGREGATE) {
-               SET_FLAG(flags, ZEBRA_FLAG_IBGP);
-               SET_FLAG(flags, ZEBRA_FLAG_INTERNAL);
+               SET_FLAG(api.flags, ZEBRA_FLAG_IBGP);
+               SET_FLAG(api.flags, ZEBRA_FLAG_INTERNAL);
        }
 
        if ((peer->sort == BGP_PEER_EBGP && peer->ttl != 1)
            || CHECK_FLAG(peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK)
            || bgp_flag_check(bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
 
-               SET_FLAG(flags, ZEBRA_FLAG_INTERNAL);
-
-       if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(info->attr)) {
-               struct zapi_ipv4 api;
-               struct in_addr *nexthop;
-               char buf[2][INET_ADDRSTRLEN];
-               int valid_nh_count = 0;
-               int has_valid_label = 0;
+               SET_FLAG(api.flags, ZEBRA_FLAG_INTERNAL);
 
-               /* resize nexthop buffer size if necessary */
-               stream_reset(bgp_nexthop_buf);
-               nexthop = NULL;
+       /* Get nexthop address-family */
+       if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(info->attr))
+               nh_family = AF_INET;
+       else if (p->family == AF_INET6
+                || (p->family == AF_INET
+                    && BGP_ATTR_NEXTHOP_AFI_IP6(info->attr)))
+               nh_family = AF_INET6;
+       else
+               return;
 
-               stream_reset(bgp_label_buf);
+       if (bgp->table_map[afi][safi].name)
+               BGP_INFO_ATTR_BUF_INIT();
 
-               if (bgp->table_map[afi][safi].name)
-                       BGP_INFO_ATTR_BUF_INIT();
+       /* Metric is currently based on the best-path only */
+       metric = info->attr->med;
+       for (mpinfo = info; mpinfo; mpinfo = bgp_info_mpath_next(mpinfo)) {
+               if (nh_family == AF_INET) {
+                       struct in_addr *nexthop;
 
-               /* Metric is currently based on the best-path only */
-               metric = info->attr->med;
-               for (mpinfo = info; mpinfo;
-                    mpinfo = bgp_info_mpath_next(mpinfo)) {
                        nexthop = NULL;
 
                        if (bgp->table_map[afi][safi].name) {
@@ -1234,8 +1066,6 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
                                            bgp->table_map[afi][safi].map, p,
                                            info_cp)) {
                                        if (mpinfo == info) {
-                                               /* Metric is currently based on
-                                                * the best-path only */
                                                metric = info_cp->attr->med;
                                                tag = info_cp->attr->tag;
                                        }
@@ -1248,118 +1078,13 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
                        if (nexthop == NULL)
                                continue;
 
-                       stream_put(bgp_nexthop_buf, &nexthop,
-                                  sizeof(struct in_addr *));
-                       if (mpinfo->extra
-                           && bgp_is_valid_label(&mpinfo->extra->label)) {
-                               has_valid_label = 1;
-                               label = label_pton(&mpinfo->extra->label);
-                               stream_put(bgp_label_buf, &label,
-                                          sizeof(mpls_label_t));
-                       }
-                       valid_nh_count++;
-               }
-
-               api.vrf_id = bgp->vrf_id;
-               api.flags = flags;
-               api.type = ZEBRA_ROUTE_BGP;
-               api.instance = 0;
-               api.message = 0;
-               api.safi = safi;
-               SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
-
-               if (has_valid_label)
-                       SET_FLAG(api.message, ZAPI_MESSAGE_LABEL);
-
-               /* Note that this currently only applies to Null0 routes for
-                * aggregates.
-                * ZEBRA_FLAG_BLACKHOLE signals zapi_ipv4_route to encode a
-                * special
-                * BLACKHOLE nexthop. We want to set api.nexthop_num to zero
-                * since we
-                * do not want to also encode the 0.0.0.0 nexthop for the
-                * aggregate route.
-                */
-               if (CHECK_FLAG(flags, ZEBRA_FLAG_BLACKHOLE))
-                       api.nexthop_num = 0;
-               else
-                       api.nexthop_num = valid_nh_count;
-
-               api.nexthop = (struct in_addr **)STREAM_DATA(bgp_nexthop_buf);
-               if (has_valid_label) {
-                       api.label_num = valid_nh_count;
-                       api.label = (unsigned int *)STREAM_DATA(bgp_label_buf);
+                       api_nh = &api.nexthops[valid_nh_count];
+                       api_nh->gate.ipv4 = *nexthop;
+                       api_nh->type = NEXTHOP_TYPE_IPV4;
                } else {
-                       api.label_num = 0;
-                       api.label = NULL;
-               }
-               api.ifindex_num = 0;
-               SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
-               api.metric = metric;
-               api.tag = 0;
-
-               if (tag) {
-                       SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
-                       api.tag = tag;
-               }
-
-               distance = bgp_distance_apply(p, info, afi, safi, bgp);
-               if (distance) {
-                       SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE);
-                       api.distance = distance;
-               }
-
-               if (bgp_debug_zebra(p)) {
-                       int i;
-                       char label_buf[20];
-                       zlog_debug(
-                               "Tx IPv4 route %s VRF %u %s/%d metric %u tag %" ROUTE_TAG_PRI
-                               " count %d",
-                               (valid_nh_count ? "add" : "delete"),
-                               bgp->vrf_id, inet_ntop(AF_INET, &p->u.prefix4,
-                                                      buf[0], sizeof(buf[0])),
-                               p->prefixlen, api.metric, api.tag,
-                               api.nexthop_num);
-                       for (i = 0; i < api.nexthop_num; i++) {
-                               label_buf[0] = '\0';
-                               if (has_valid_label)
-                                       sprintf(label_buf, "label %u",
-                                               api.label[i]);
-                               zlog_debug("  nhop [%d]: %s %s", i + 1,
-                                          inet_ntop(AF_INET, api.nexthop[i],
-                                                    buf[1], sizeof(buf[1])),
-                                          label_buf);
-                       }
-               }
-
-               zapi_ipv4_route(valid_nh_count ? ZEBRA_IPV4_ROUTE_ADD
-                                              : ZEBRA_IPV4_ROUTE_DELETE,
-                               zclient, (struct prefix_ipv4 *)p, &api);
-       }
+                       ifindex_t ifindex;
+                       struct in6_addr *nexthop;
 
-       /* We have to think about a IPv6 link-local address curse. */
-       if (p->family == AF_INET6
-           || (p->family == AF_INET && BGP_ATTR_NEXTHOP_AFI_IP6(info->attr))) {
-               ifindex_t ifindex;
-               struct in6_addr *nexthop;
-               struct zapi_ipv6 api;
-               int valid_nh_count = 0;
-               char buf[2][INET6_ADDRSTRLEN];
-               int has_valid_label = 0;
-
-               stream_reset(bgp_nexthop_buf);
-               stream_reset(bgp_ifindices_buf);
-               stream_reset(bgp_label_buf);
-
-               ifindex = 0;
-               nexthop = NULL;
-
-               if (bgp->table_map[afi][safi].name)
-                       BGP_INFO_ATTR_BUF_INIT();
-
-               metric = info->attr->med;
-               for (mpinfo = info; mpinfo;
-                    mpinfo = bgp_info_mpath_next(mpinfo)) {
                        ifindex = 0;
                        nexthop = NULL;
 
@@ -1407,147 +1132,72 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
                        if (ifindex == 0)
                                continue;
 
-                       stream_put(bgp_nexthop_buf, &nexthop,
-                                  sizeof(struct in6_addr *));
-                       stream_put(bgp_ifindices_buf, &ifindex,
-                                  sizeof(unsigned int));
-
-                       if (mpinfo->extra
-                           && bgp_is_valid_label(&mpinfo->extra->label)) {
-                               has_valid_label = 1;
-                               label = label_pton(&mpinfo->extra->label);
-                               stream_put(bgp_label_buf, &label,
-                                          sizeof(mpls_label_t));
-                       }
-                       valid_nh_count++;
+                       api_nh = &api.nexthops[valid_nh_count];
+                       api_nh->gate.ipv6 = *nexthop;
+                       api_nh->ifindex = ifindex;
+                       api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
                }
 
-               /* Make Zebra API structure. */
-               api.vrf_id = bgp->vrf_id;
-               api.flags = flags;
-               api.type = ZEBRA_ROUTE_BGP;
-               api.instance = 0;
-               api.message = 0;
-               api.safi = safi;
-               SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
-
-               if (has_valid_label)
-                       SET_FLAG(api.message, ZAPI_MESSAGE_LABEL);
-
-               /* Note that this currently only applies to Null0 routes for
-                * aggregates.
-                * ZEBRA_FLAG_BLACKHOLE signals zapi_ipv6_route to encode a
-                * special
-                * BLACKHOLE nexthop. We want to set api.nexthop_num to zero
-                * since we
-                * do not want to also encode the :: nexthop for the aggregate
-                * route.
-                */
-               if (CHECK_FLAG(flags, ZEBRA_FLAG_BLACKHOLE))
-                       api.nexthop_num = 0;
-               else
-                       api.nexthop_num = valid_nh_count;
-
-               api.nexthop = (struct in6_addr **)STREAM_DATA(bgp_nexthop_buf);
-               SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX);
-               api.ifindex_num = valid_nh_count;
-               api.ifindex = (ifindex_t *)STREAM_DATA(bgp_ifindices_buf);
-               if (has_valid_label) {
-                       api.label_num = valid_nh_count;
-                       api.label = (unsigned int *)STREAM_DATA(bgp_label_buf);
-               } else {
-                       api.label_num = 0;
-                       api.label = NULL;
-               }
-               SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
-               api.metric = metric;
-               api.tag = 0;
+               if (mpinfo->extra
+                   && bgp_is_valid_label(&mpinfo->extra->label)) {
+                       has_valid_label = 1;
+                       label = label_pton(&mpinfo->extra->label);
 
-               if (tag) {
-                       SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
-                       api.tag = tag;
+                       api_nh->label_num = 1;
+                       api_nh->labels[0] = label;
                }
+               valid_nh_count++;
+       }
 
-               distance = bgp_distance_apply(p, info, afi, safi, bgp);
-               if (distance) {
-                       SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE);
-                       api.distance = distance;
-               }
+       if (has_valid_label)
+               SET_FLAG(api.message, ZAPI_MESSAGE_LABEL);
 
-               if (p->family == AF_INET) {
-                       if (bgp_debug_zebra(p)) {
-                               int i;
-                               char label_buf[20];
-                               zlog_debug(
-                                       "Tx IPv4 route %s VRF %u %s/%d metric %u tag %" ROUTE_TAG_PRI,
-                                       valid_nh_count ? "add" : "delete",
-                                       bgp->vrf_id,
-                                       inet_ntop(AF_INET, &p->u.prefix4,
-                                                 buf[0], sizeof(buf[0])),
-                                       p->prefixlen, api.metric, api.tag);
-                               for (i = 0; i < api.nexthop_num; i++) {
-                                       label_buf[0] = '\0';
-                                       if (has_valid_label)
-                                               sprintf(label_buf, "label %u",
-                                                       api.label[i]);
-                                       zlog_debug(
-                                               "  nhop [%d]: %s if %s %s",
-                                               i + 1,
-                                               inet_ntop(AF_INET6,
-                                                         api.nexthop[i],
-                                                         buf[1],
-                                                         sizeof(buf[1])),
-                                               ifindex2ifname(api.ifindex[i],
-                                                              bgp->vrf_id),
-                                               label_buf);
-                               }
-                       }
+       if (!CHECK_FLAG(api.flags, ZEBRA_FLAG_BLACKHOLE))
+               api.nexthop_num = valid_nh_count;
 
-                       if (valid_nh_count)
-                               zapi_ipv4_route_ipv6_nexthop(
-                                       ZEBRA_IPV4_ROUTE_IPV6_NEXTHOP_ADD,
-                                       zclient, (struct prefix_ipv4 *)p,
-                                       (struct zapi_ipv6 *)&api);
-                       else
-                               zapi_ipv4_route(ZEBRA_IPV4_ROUTE_DELETE,
-                                               zclient,
-                                               (struct prefix_ipv4 *)p,
-                                               (struct zapi_ipv4 *)&api);
-               } else {
-                       if (bgp_debug_zebra(p)) {
-                               int i;
-                               char label_buf[20];
-                               zlog_debug(
-                                       "Tx IPv6 route %s VRF %u %s/%d metric %u tag %" ROUTE_TAG_PRI,
-                                       valid_nh_count ? "add" : "delete",
-                                       bgp->vrf_id,
-                                       inet_ntop(AF_INET6, &p->u.prefix6,
-                                                 buf[0], sizeof(buf[0])),
-                                       p->prefixlen, api.metric, api.tag);
-                               for (i = 0; i < api.nexthop_num; i++) {
-                                       label_buf[0] = '\0';
-                                       if (has_valid_label)
-                                               sprintf(label_buf, "label %u",
-                                                       api.label[i]);
-                                       zlog_debug(
-                                               "  nhop [%d]: %s if %s %s",
-                                               i + 1,
-                                               inet_ntop(AF_INET6,
-                                                         api.nexthop[i],
-                                                         buf[1],
-                                                         sizeof(buf[1])),
-                                               ifindex2ifname(api.ifindex[i],
-                                                              bgp->vrf_id),
-                                               label_buf);
-                               }
-                       }
+       SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
+       api.metric = metric;
+
+       if (tag) {
+               SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
+               api.tag = tag;
+       }
+
+       distance = bgp_distance_apply(p, info, afi, safi, bgp);
+       if (distance) {
+               SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE);
+               api.distance = distance;
+       }
 
-                       zapi_ipv6_route(
-                               valid_nh_count ? ZEBRA_IPV6_ROUTE_ADD
-                                              : ZEBRA_IPV6_ROUTE_DELETE,
-                               zclient, (struct prefix_ipv6 *)p, NULL, &api);
+       if (bgp_debug_zebra(p)) {
+               char prefix_buf[PREFIX_STRLEN];
+               char nh_buf[INET6_ADDRSTRLEN];
+               char label_buf[20];
+               int i;
+
+               prefix2str(&api.prefix, prefix_buf, sizeof(prefix_buf));
+               zlog_debug("Tx route %s VRF %u %s metric %u tag %" ROUTE_TAG_PRI
+                          " count %d",
+                          valid_nh_count ? "add" : "delete", bgp->vrf_id,
+                          prefix_buf, api.metric, api.tag, api.nexthop_num);
+               for (i = 0; i < api.nexthop_num; i++) {
+                       api_nh = &api.nexthops[i];
+
+                       inet_ntop(nh_family, &api_nh->gate, nh_buf,
+                                 sizeof(nh_buf));
+
+                       label_buf[0] = '\0';
+                       if (has_valid_label)
+                               sprintf(label_buf, "label %u",
+                                       api_nh->labels[0]);
+                       zlog_debug("  nhop [%d]: %s %s", i + 1, nh_buf,
+                                  label_buf);
                }
        }
+
+       zclient_route_send(valid_nh_count ? ZEBRA_ROUTE_ADD
+                                         : ZEBRA_ROUTE_DELETE,
+                          zclient, &api);
 }
 
 /* Announce all routes of a table to zebra */
@@ -1578,7 +1228,7 @@ void bgp_zebra_announce_table(struct bgp *bgp, afi_t afi, safi_t safi)
 
 void bgp_zebra_withdraw(struct prefix *p, struct bgp_info *info, safi_t safi)
 {
-       u_int32_t flags;
+       struct zapi_route api;
        struct peer *peer;
 
        peer = info->peer;
@@ -1590,101 +1240,30 @@ void bgp_zebra_withdraw(struct prefix *p, struct bgp_info *info, safi_t safi)
        if (!bgp_install_info_to_zebra(peer->bgp))
                return;
 
-       if ((p->family == AF_INET
-            && !vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_BGP],
-                                 peer->bgp->vrf_id))
-           || (p->family == AF_INET6
-               && !vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_BGP],
-                                    peer->bgp->vrf_id)))
-               return;
-
-       flags = 0;
+       memset(&api, 0, sizeof(api));
+       api.vrf_id = peer->bgp->vrf_id;
+       api.type = ZEBRA_ROUTE_BGP;
+       api.safi = safi;
+       api.prefix = *p;
 
        if (peer->sort == BGP_PEER_IBGP) {
-               SET_FLAG(flags, ZEBRA_FLAG_INTERNAL);
-               SET_FLAG(flags, ZEBRA_FLAG_IBGP);
+               SET_FLAG(api.flags, ZEBRA_FLAG_INTERNAL);
+               SET_FLAG(api.flags, ZEBRA_FLAG_IBGP);
        }
 
        if ((peer->sort == BGP_PEER_EBGP && peer->ttl != 1)
            || CHECK_FLAG(peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK)
            || bgp_flag_check(peer->bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
-               SET_FLAG(flags, ZEBRA_FLAG_INTERNAL);
-
-       if (p->family == AF_INET) {
-               struct zapi_ipv4 api;
-
-               api.vrf_id = peer->bgp->vrf_id;
-               api.flags = flags;
-
-               api.type = ZEBRA_ROUTE_BGP;
-               api.instance = 0;
-               api.message = 0;
-               api.safi = safi;
-               SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
-               api.nexthop_num = 0;
-               api.nexthop = NULL;
-               api.label_num = 0;
-               api.label = NULL;
-               api.ifindex_num = 0;
-               SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
-               api.metric = info->attr->med;
-               api.tag = 0;
-
-               if (info->attr->tag != 0) {
-                       SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
-                       api.tag = info->attr->tag;
-               }
+               SET_FLAG(api.flags, ZEBRA_FLAG_INTERNAL);
 
-               if (bgp_debug_zebra(p)) {
-                       char buf[2][INET_ADDRSTRLEN];
-                       zlog_debug(
-                               "Tx IPv4 route delete VRF %u %s/%d metric %u tag %" ROUTE_TAG_PRI,
-                               peer->bgp->vrf_id,
-                               inet_ntop(AF_INET, &p->u.prefix4, buf[0],
-                                         sizeof(buf[0])),
-                               p->prefixlen, api.metric, api.tag);
-               }
+       if (bgp_debug_zebra(p)) {
+               char buf[PREFIX_STRLEN];
 
-               zapi_ipv4_route(ZEBRA_IPV4_ROUTE_DELETE, zclient,
-                               (struct prefix_ipv4 *)p, &api);
+               prefix2str(&api.prefix, buf, sizeof(buf));
+               zlog_debug("Tx route delete VRF %u %s", peer->bgp->vrf_id, buf);
        }
-       /* We have to think about a IPv6 link-local address curse. */
-       if (p->family == AF_INET6) {
-               struct zapi_ipv6 api;
-
-               api.vrf_id = peer->bgp->vrf_id;
-               api.flags = flags;
-               api.type = ZEBRA_ROUTE_BGP;
-               api.instance = 0;
-               api.message = 0;
-               api.safi = safi;
-               SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
-               api.nexthop_num = 0;
-               api.nexthop = NULL;
-               api.ifindex_num = 0;
-               api.label_num = 0;
-               SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
-               api.metric = info->attr->med;
-               api.tag = 0;
-
-               if (info->attr->tag != 0) {
-                       SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
-                       api.tag = info->attr->tag;
-               }
-
-               if (bgp_debug_zebra(p)) {
-                       char buf[2][INET6_ADDRSTRLEN];
-                       zlog_debug(
-                               "Tx IPv6 route delete VRF %u %s/%d metric %u tag %" ROUTE_TAG_PRI,
-                               peer->bgp->vrf_id,
-                               inet_ntop(AF_INET6, &p->u.prefix6, buf[0],
-                                         sizeof(buf[0])),
-                               p->prefixlen, api.metric, api.tag);
-               }
 
-               zapi_ipv6_route(ZEBRA_IPV6_ROUTE_DELETE, zclient,
-                               (struct prefix_ipv6 *)p, NULL, &api);
-       }
+       zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
 }
 
 struct bgp_redist *bgp_redist_lookup(struct bgp *bgp, afi_t afi, u_char type,
@@ -2198,12 +1777,10 @@ void bgp_zebra_init(struct thread_master *master)
        zclient->interface_nbr_address_delete =
                bgp_interface_nbr_address_delete;
        zclient->interface_vrf_update = bgp_interface_vrf_update;
-       zclient->redistribute_route_ipv4_add = zebra_read_ipv4;
-       zclient->redistribute_route_ipv4_del = zebra_read_ipv4;
+       zclient->redistribute_route_add = zebra_read_route;
+       zclient->redistribute_route_del = zebra_read_route;
        zclient->interface_up = bgp_interface_up;
        zclient->interface_down = bgp_interface_down;
-       zclient->redistribute_route_ipv6_add = zebra_read_ipv6;
-       zclient->redistribute_route_ipv6_del = zebra_read_ipv6;
        zclient->nexthop_update = bgp_read_nexthop_update;
        zclient->import_check_update = bgp_read_import_check_update;
        zclient->fec_update = bgp_read_fec_update;
@@ -2211,22 +1788,10 @@ void bgp_zebra_init(struct thread_master *master)
        zclient->local_vni_del = bgp_zebra_process_local_vni;
        zclient->local_macip_add = bgp_zebra_process_local_macip;
        zclient->local_macip_del = bgp_zebra_process_local_macip;
-
-       bgp_nexthop_buf = stream_new(multipath_num * sizeof(struct in6_addr));
-       bgp_ifindices_buf = stream_new(multipath_num * sizeof(unsigned int));
-       bgp_label_buf = stream_new(multipath_num * sizeof(unsigned int));
 }
 
 void bgp_zebra_destroy(void)
 {
-
-       if (bgp_nexthop_buf)
-               stream_free(bgp_nexthop_buf);
-       if (bgp_ifindices_buf)
-               stream_free(bgp_ifindices_buf);
-       if (bgp_label_buf)
-               stream_free(bgp_label_buf);
-
        if (zclient == NULL)
                return;
        zclient_stop(zclient);
index b6a48c9928d42969ee0c92d1c2ba9d7099052f0c..3fc3fe85f34bf569e3dfa2c275ab6b466e71c37d 100644 (file)
@@ -1116,9 +1116,8 @@ struct peer *peer_new(struct bgp *bgp)
        peer->status = Idle;
        peer->ostatus = Idle;
        peer->cur_event = peer->last_event = peer->last_major_event = 0;
-       peer->bgp = bgp;
+       peer->bgp = bgp_lock(bgp);
        peer = peer_lock(peer); /* initial reference */
-       bgp_lock(bgp);
        peer->password = NULL;
 
        /* Set default flags.  */
@@ -1392,6 +1391,32 @@ void bgp_peer_conf_if_to_su_update(struct peer *peer)
        hash_get(peer->bgp->peerhash, peer, hash_alloc_intern);
 }
 
+static void bgp_recalculate_afi_safi_bestpaths(struct bgp *bgp, afi_t afi,
+                                              safi_t safi)
+{
+       struct bgp_node *rn, *nrn;
+
+       for (rn = bgp_table_top(bgp->rib[afi][safi]); rn;
+            rn = bgp_route_next(rn)) {
+               if (rn->info != NULL) {
+                       /* Special handling for 2-level routing
+                        * tables. */
+                       if (safi == SAFI_MPLS_VPN
+                           || safi == SAFI_ENCAP
+                           || safi == SAFI_EVPN) {
+                               for (nrn = bgp_table_top((
+                                            struct bgp_table
+                                                    *)(rn->info));
+                                    nrn;
+                                    nrn = bgp_route_next(nrn))
+                                       bgp_process(bgp, nrn,
+                                                   afi, safi);
+                       } else
+                               bgp_process(bgp, rn, afi, safi);
+               }
+       }
+}
+
 /* Force a bestpath recalculation for all prefixes.  This is used
  * when 'bgp bestpath' commands are entered.
  */
@@ -1399,29 +1424,10 @@ void bgp_recalculate_all_bestpaths(struct bgp *bgp)
 {
        afi_t afi;
        safi_t safi;
-       struct bgp_node *rn, *nrn;
 
        for (afi = AFI_IP; afi < AFI_MAX; afi++) {
                for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
-                       for (rn = bgp_table_top(bgp->rib[afi][safi]); rn;
-                            rn = bgp_route_next(rn)) {
-                               if (rn->info != NULL) {
-                                       /* Special handling for 2-level routing
-                                        * tables. */
-                                       if (safi == SAFI_MPLS_VPN
-                                           || safi == SAFI_ENCAP
-                                           || safi == SAFI_EVPN) {
-                                               for (nrn = bgp_table_top((
-                                                            struct bgp_table
-                                                                    *)(rn->info));
-                                                    nrn;
-                                                    nrn = bgp_route_next(nrn))
-                                                       bgp_process(bgp, nrn,
-                                                                   afi, safi);
-                                       } else
-                                               bgp_process(bgp, rn, afi, safi);
-                               }
-                       }
+                       bgp_recalculate_afi_safi_bestpaths(bgp, afi, safi);
                }
        }
 }
@@ -1501,6 +1507,25 @@ struct peer *peer_create_accept(struct bgp *bgp)
        return peer;
 }
 
+/*
+ * Return true if we have a peer configured to use this afi/safi
+ */
+int bgp_afi_safi_peer_exists(struct bgp *bgp, afi_t afi, safi_t safi)
+{
+       struct listnode *node;
+       struct peer *peer;
+
+       for (ALL_LIST_ELEMENTS_RO(bgp->peer, node, peer)) {
+               if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
+                       continue;
+
+               if (peer->afc[afi][safi])
+                       return 1;
+       }
+
+       return 0;
+}
+
 /* Change peer's AS number.  */
 void peer_as_change(struct peer *peer, as_t as, int as_specified)
 {
@@ -1715,11 +1740,14 @@ int peer_activate(struct peer *peer, afi_t afi, safi_t safi)
        struct peer_group *group;
        struct listnode *node, *nnode;
        struct peer *tmp_peer;
+       struct bgp *bgp;
 
        /* Nothing to do if we've already activated this peer */
        if (peer->afc[afi][safi])
                return ret;
 
+       bgp = peer->bgp;
+
        /* This is a peer-group so activate all of the members of the
         * peer-group as well */
        if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
@@ -1742,6 +1770,17 @@ int peer_activate(struct peer *peer, afi_t afi, safi_t safi)
                ret |= non_peergroup_activate_af(peer, afi, safi);
        }
 
+       /* If this is the first peer to be activated for this afi/labeled-unicast
+        * recalc bestpaths to trigger label allocation */
+       if (safi == SAFI_LABELED_UNICAST && !bgp->allocate_mpls_labels[afi][SAFI_UNICAST]) {
+
+               if (BGP_DEBUG(zebra, ZEBRA))
+                       zlog_info("peer(s) are now active for labeled-unicast, allocate MPLS labels");
+
+               bgp->allocate_mpls_labels[afi][SAFI_UNICAST] = 1;
+               bgp_recalculate_afi_safi_bestpaths(bgp, afi, SAFI_UNICAST);
+       }
+
        return ret;
 }
 
@@ -1799,6 +1838,7 @@ int peer_deactivate(struct peer *peer, afi_t afi, safi_t safi)
        struct peer_group *group;
        struct peer *tmp_peer;
        struct listnode *node, *nnode;
+       struct bgp *bgp;
 
        /* Nothing to do if we've already de-activated this peer */
        if (!peer->afc[afi][safi])
@@ -1822,6 +1862,20 @@ int peer_deactivate(struct peer *peer, afi_t afi, safi_t safi)
                ret |= non_peergroup_deactivate_af(peer, afi, safi);
        }
 
+       bgp = peer->bgp;
+
+       /* If this is the last peer to be deactivated for this afi/labeled-unicast
+        * recalc bestpaths to trigger label deallocation */
+       if (safi == SAFI_LABELED_UNICAST &&
+           bgp->allocate_mpls_labels[afi][SAFI_UNICAST] &&
+           !bgp_afi_safi_peer_exists(bgp, afi, safi)) {
+
+               if (BGP_DEBUG(zebra, ZEBRA))
+                       zlog_info("peer(s) are no longer active for labeled-unicast, deallocate MPLS labels");
+
+               bgp->allocate_mpls_labels[afi][SAFI_UNICAST] = 0;
+               bgp_recalculate_afi_safi_bestpaths(bgp, afi, SAFI_UNICAST);
+       }
        return ret;
 }
 
@@ -3107,6 +3161,8 @@ int bgp_delete(struct bgp *bgp)
         * routes to be processed still referencing the struct bgp.
         */
        listnode_delete(bm->bgp, bgp);
+       if (list_isempty(bm->bgp))
+               bgp_close();
 
        /* Deregister from Zebra, if needed */
        if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp))
@@ -3125,21 +3181,7 @@ int bgp_delete(struct bgp *bgp)
        return 0;
 }
 
-static void bgp_free(struct bgp *);
-
-void bgp_lock(struct bgp *bgp)
-{
-       ++bgp->lock;
-}
-
-void bgp_unlock(struct bgp *bgp)
-{
-       assert(bgp->lock > 0);
-       if (--bgp->lock == 0)
-               bgp_free(bgp);
-}
-
-static void bgp_free(struct bgp *bgp)
+void bgp_free(struct bgp *bgp)
 {
        afi_t afi;
        safi_t safi;
index 344b850fb4a32e1c8a0583bac1ed39d0a8ef2aae..0d7092c98cb9353868a898ecf69eda6fa1b33855 100644 (file)
@@ -337,6 +337,9 @@ struct bgp {
        /* BGP redistribute configuration. */
        struct list *redist[AFI_MAX][ZEBRA_ROUTE_MAX];
 
+       /* Allocate MPLS labels */
+       u_char allocate_mpls_labels[AFI_MAX][SAFI_MAX];
+
        /* timer to re-evaluate neighbor default-originate route-maps */
        struct thread *t_rmap_def_originate_eval;
 #define RMAP_DEFAULT_ORIGINATE_EVAL_TIMER 5
@@ -1256,9 +1259,6 @@ extern int bgp_flag_set(struct bgp *, int);
 extern int bgp_flag_unset(struct bgp *, int);
 extern int bgp_flag_check(struct bgp *, int);
 
-extern void bgp_lock(struct bgp *);
-extern void bgp_unlock(struct bgp *);
-
 extern void bgp_router_id_zebra_bump(vrf_id_t, const struct prefix *);
 extern int bgp_router_id_static_set(struct bgp *, struct in_addr);
 
@@ -1287,6 +1287,7 @@ extern int bgp_listen_limit_unset(struct bgp *);
 
 extern int bgp_update_delay_active(struct bgp *);
 extern int bgp_update_delay_configured(struct bgp *);
+extern int bgp_afi_safi_peer_exists(struct bgp *bgp, afi_t afi, safi_t safi);
 extern void peer_as_change(struct peer *, as_t, int);
 extern int peer_remote_as(struct bgp *, union sockunion *, const char *, as_t *,
                          int, afi_t, safi_t);
@@ -1399,6 +1400,20 @@ extern struct peer_af *peer_af_find(struct peer *, afi_t, safi_t);
 extern int peer_af_delete(struct peer *, afi_t, safi_t);
 
 extern void bgp_close(void);
+extern void bgp_free(struct bgp *);
+
+static inline struct bgp *bgp_lock(struct bgp *bgp)
+{
+       bgp->lock++;
+       return bgp;
+}
+
+static inline void bgp_unlock(struct bgp *bgp)
+{
+       assert(bgp->lock > 0);
+       if (--bgp->lock == 0)
+               bgp_free(bgp);
+}
 
 static inline int afindex(afi_t afi, safi_t safi)
 {
@@ -1544,10 +1559,8 @@ static inline struct vrf *bgp_vrf_lookup_by_instance_type(struct bgp *bgp)
 static inline void bgp_vrf_link(struct bgp *bgp, struct vrf *vrf)
 {
        bgp->vrf_id = vrf->vrf_id;
-       if (vrf->info != (void *)bgp) {
-               bgp_lock(bgp);
-               vrf->info = (void *)bgp;
-       }
+       if (vrf->info != (void *)bgp)
+               vrf->info = (void *)bgp_lock(bgp);
 }
 
 /* Unlink BGP instance from VRF. */
index 7e0ed9150bb8f04b2a4d75d3c8d0fe30d677677e..d63975a22bff02105ede300fb0d467b0dbfd905f 100644 (file)
@@ -1224,8 +1224,8 @@ static int rfapiVpnBiSamePtUn(struct bgp_info *bi1, struct bgp_info *bi2)
 
        switch (pfx_un1.family) {
        case AF_INET:
-               if (!IPV4_ADDR_SAME(&pfx_un1.u.prefix4.s_addr,
-                                   &pfx_un2.u.prefix4.s_addr))
+               if (!IPV4_ADDR_SAME(&pfx_un1.u.prefix4,
+                                   &pfx_un2.u.prefix4))
                        return 0;
                break;
        case AF_INET6:
index d4ff9451c373edc536c9a53f73ce22cc8a625f58..3e9b5ed6b97aff27ac3089897499ce3d8ae6c39b 100644 (file)
@@ -142,13 +142,13 @@ DEFUN (no_debug_bgp_vnc_all,
  *     show/save
  ***********************************************************************/
 
-DEFUN (show_debugging_bgp_vnc,
-       show_debugging_bgp_vnc_cmd,
-       "show debugging bgp vnc",
-       SHOW_STR
-       DEBUG_STR
-       BGP_STR
-       VNC_STR)
+DEFUN_NOSH (show_debugging_bgp_vnc,
+           show_debugging_bgp_vnc_cmd,
+           "show debugging bgp vnc",
+           SHOW_STR
+           DEBUG_STR
+           BGP_STR
+           VNC_STR)
 {
        size_t i;
 
index 3075d4109fb0ece805e73fa14aed883676e73278..d472e06fa5abdfa7c89fdad0c0dbb1cf97aa7958 100644 (file)
@@ -57,8 +57,8 @@ static struct zclient *zclient_vnc = NULL;
 /*
  * Routes coming from zebra get added to VNC here
  */
-static void vnc_redistribute_add(struct prefix *p, struct in_addr *nexthop,
-                                u_int32_t metric, uint8_t type)
+static void vnc_redistribute_add(struct prefix *p, u_int32_t metric,
+                                uint8_t type)
 {
        struct bgp *bgp = bgp_get_default();
        struct prefix_rd prd;
@@ -329,156 +329,33 @@ static void vnc_redistribute_withdraw(struct bgp *bgp, afi_t afi, uint8_t type)
  *
  * Assumes 1 nexthop
  */
-static int vnc_zebra_read_ipv4(int command, struct zclient *zclient,
-                              zebra_size_t length, vrf_id_t vrf_id)
+static int vnc_zebra_read_route(int command, struct zclient *zclient,
+                               zebra_size_t length, vrf_id_t vrf_id)
 {
-       struct stream *s;
-       struct zapi_ipv4 api;
-       struct in_addr nexthop;
-       struct prefix_ipv4 p;
-
-       s = zclient->ibuf;
-       nexthop.s_addr = 0;
-
-       /* Type, flags, message. */
-       api.type = stream_getc(s);
-       api.flags = stream_getc(s);
-       api.message = stream_getc(s);
-
-       /* IPv4 prefix. */
-       memset(&p, 0, sizeof(struct prefix_ipv4));
-       p.family = AF_INET;
-       p.prefixlen = stream_getc(s);
-       stream_get(&p.prefix, s, PSIZE(p.prefixlen));
-
-       /* Nexthop, ifindex, distance, metric. */
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) {
-               api.nexthop_num = stream_getc(s);
-               nexthop.s_addr = stream_get_ipv4(s);
-       }
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) {
-               api.ifindex_num = stream_getc(s);
-               stream_getl(s);
-       }
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE))
-               api.distance = stream_getc(s);
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC))
-               api.metric = stream_getl(s);
-       else
-               api.metric = 0;
-
-       if (command == ZEBRA_IPV4_ROUTE_ADD) {
-               if (BGP_DEBUG(zebra, ZEBRA)) {
-                       char buf[2][INET_ADDRSTRLEN];
-                       vnc_zlog_debug_verbose(
-                               "%s: Zebra rcvd: IPv4 route add %s %s/%d nexthop %s metric %u",
-                               __func__, zebra_route_string(api.type),
-                               inet_ntop(AF_INET, &p.prefix, buf[0],
-                                         sizeof(buf[0])),
-                               p.prefixlen, inet_ntop(AF_INET, &nexthop,
-                                                      buf[1], sizeof(buf[1])),
-                               api.metric);
-               }
-               vnc_redistribute_add((struct prefix *)&p, &nexthop, api.metric,
-                                    api.type);
-       } else {
-               if (BGP_DEBUG(zebra, ZEBRA)) {
-                       char buf[2][INET_ADDRSTRLEN];
-                       vnc_zlog_debug_verbose(
-                               "%s: Zebra rcvd: IPv4 route delete %s %s/%d "
-                               "nexthop %s metric %u",
-                               __func__, zebra_route_string(api.type),
-                               inet_ntop(AF_INET, &p.prefix, buf[0],
-                                         sizeof(buf[0])),
-                               p.prefixlen, inet_ntop(AF_INET, &nexthop,
-                                                      buf[1], sizeof(buf[1])),
-                               api.metric);
-               }
-               vnc_redistribute_delete((struct prefix *)&p, api.type);
-       }
+       struct zapi_route api;
+       int add;
 
-       return 0;
-}
+       if (zapi_route_decode(zclient->ibuf, &api) < 0)
+               return -1;
 
-/* Zebra route add and delete treatment. */
-static int vnc_zebra_read_ipv6(int command, struct zclient *zclient,
-                              zebra_size_t length, vrf_id_t vrf_id)
-{
-       struct stream *s;
-       struct zapi_ipv6 api;
-       struct in6_addr nexthop;
-       struct prefix_ipv6 p, src_p;
-
-       s = zclient->ibuf;
-       memset(&nexthop, 0, sizeof(struct in6_addr));
-
-       /* Type, flags, message. */
-       api.type = stream_getc(s);
-       api.flags = stream_getc(s);
-       api.message = stream_getc(s);
-
-       /* IPv6 prefix. */
-       memset(&p, 0, sizeof(struct prefix_ipv6));
-       p.family = AF_INET6;
-       p.prefixlen = stream_getc(s);
-       stream_get(&p.prefix, s, PSIZE(p.prefixlen));
-
-       memset(&src_p, 0, sizeof(struct prefix_ipv6));
-       src_p.family = AF_INET6;
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) {
-               src_p.prefixlen = stream_getc(s);
-               stream_get(&src_p.prefix, s, PSIZE(src_p.prefixlen));
-       }
-
-       if (src_p.prefixlen)
-               /* we completely ignore srcdest routes for now. */
+       /* we completely ignore srcdest routes for now. */
+       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
                return 0;
 
-       /* Nexthop, ifindex, distance, metric. */
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) {
-               api.nexthop_num = stream_getc(s);
-               stream_get(&nexthop, s, 16);
-       }
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) {
-               api.ifindex_num = stream_getc(s);
-               stream_getl(s);
-       }
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE))
-               api.distance = stream_getc(s);
-       else
-               api.distance = 0;
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC))
-               api.metric = stream_getl(s);
+       add = (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD);
+       if (add)
+               vnc_redistribute_add(&api.prefix, api.metric, api.type);
        else
-               api.metric = 0;
+               vnc_redistribute_delete(&api.prefix, api.type);
 
-       /* Simply ignore link-local address. */
-       if (IN6_IS_ADDR_LINKLOCAL(&p.prefix))
-               return 0;
+       if (BGP_DEBUG(zebra, ZEBRA)) {
+               char buf[PREFIX_STRLEN];
 
-       if (command == ZEBRA_IPV6_ROUTE_ADD) {
-               if (BGP_DEBUG(zebra, ZEBRA)) {
-                       char buf[INET6_ADDRSTRLEN];
-                       vnc_zlog_debug_verbose(
-                               "Zebra rcvd: IPv6 route add %s %s/%d metric %u",
-                               zebra_route_string(api.type),
-                               inet_ntop(AF_INET6, &p.prefix, buf,
-                                         sizeof(buf)),
-                               p.prefixlen, api.metric);
-               }
-               vnc_redistribute_add((struct prefix *)&p, NULL, api.metric,
-                                    api.type);
-       } else {
-               if (BGP_DEBUG(zebra, ZEBRA)) {
-                       char buf[INET6_ADDRSTRLEN];
-                       vnc_zlog_debug_verbose(
-                               "Zebra rcvd: IPv6 route delete %s %s/%d metric %u",
-                               zebra_route_string(api.type),
-                               inet_ntop(AF_INET6, &p.prefix, buf,
-                                         sizeof(buf)),
-                               p.prefixlen, api.metric);
-               }
-               vnc_redistribute_delete((struct prefix *)&p, api.type);
+               prefix2str(&api.prefix, buf, sizeof(buf));
+               vnc_zlog_debug_verbose(
+                       "%s: Zebra rcvd: route delete %s %s metric %u",
+                       __func__, zebra_route_string(api.type), buf,
+                       api.metric);
        }
 
        return 0;
@@ -494,83 +371,57 @@ static int vnc_zebra_read_ipv6(int command, struct zclient *zclient,
 static void vnc_zebra_route_msg(struct prefix *p, int nhp_count, void *nhp_ary,
                                int add) /* 1 = add, 0 = del */
 {
+       struct zapi_route api;
+       struct zapi_nexthop *api_nh;
+       int i;
+
        if (!nhp_count) {
                vnc_zlog_debug_verbose("%s: empty nexthop list, skipping",
                                       __func__);
                return;
        }
 
-       if (p->family == AF_INET) {
+       memset(&api, 0, sizeof(api));
+       api.vrf_id = VRF_DEFAULT;
+       api.type = ZEBRA_ROUTE_VNC;
+       api.safi = SAFI_UNICAST;
+       api.prefix = *p;
 
-               struct zapi_ipv4 api;
+       /* Nexthops */
+       SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
+       api.nexthop_num = nhp_count;
+       for (i = 0; i < nhp_count; i++) {
+               struct in_addr *nhp_ary4;
+               struct in6_addr *nhp_ary6;
 
-               api.flags = 0;
-               api.vrf_id = VRF_DEFAULT;
-               api.type = ZEBRA_ROUTE_VNC;
-               api.message = 0;
-               SET_FLAG(api.message,
-                        ZAPI_MESSAGE_NEXTHOP); /* TBD what's it mean? */
-               api.nexthop_num = nhp_count;
-               api.nexthop = nhp_ary;
-               api.ifindex_num = 0;
-               api.instance = 0;
-               api.safi = SAFI_UNICAST;
-
-               if (BGP_DEBUG(zebra, ZEBRA)) {
-
-                       char buf[INET_ADDRSTRLEN];
-                       vnc_zlog_debug_verbose(
-                               "%s: Zebra send: IPv4 route %s %s/%d, nhp_count=%d",
-                               __func__, (add ? "add" : "del"),
-                               inet_ntop(AF_INET, &p->u.prefix4, buf,
-                                         sizeof(buf)),
-                               p->prefixlen, nhp_count);
+               api_nh = &api.nexthops[i];
+               switch (p->family) {
+               case AF_INET:
+                       nhp_ary4 = nhp_ary;
+                       memcpy(&api_nh->gate.ipv4, &nhp_ary4[i],
+                              sizeof(api_nh->gate.ipv4));
+                       api_nh->type = NEXTHOP_TYPE_IPV4;
+                       break;
+               case AF_INET6:
+                       nhp_ary6 = nhp_ary;
+                       memcpy(&api_nh->gate.ipv6, &nhp_ary6[i],
+                              sizeof(api_nh->gate.ipv6));
+                       api_nh->type = NEXTHOP_TYPE_IPV6;
+                       break;
                }
+       }
 
-               zapi_ipv4_route((add ? ZEBRA_IPV4_NEXTHOP_ADD
-                                    : ZEBRA_IPV4_NEXTHOP_DELETE),
-                               zclient_vnc, (struct prefix_ipv4 *)p, &api);
-
-       } else if (p->family == AF_INET6) {
-
-               struct zapi_ipv6 api;
-               ifindex_t ifindex = 0;
-
-               /* Make Zebra API structure. */
-               api.flags = 0;
-               api.vrf_id = VRF_DEFAULT;
-               api.type = ZEBRA_ROUTE_VNC;
-               api.message = 0;
-               SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); /* TBD means? */
-               api.nexthop_num = nhp_count;
-               api.nexthop = nhp_ary;
-               SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX);
-               api.ifindex_num = 1;
-               api.ifindex = &ifindex;
-               api.instance = 0;
-               api.safi = SAFI_UNICAST;
-
-               if (BGP_DEBUG(zebra, ZEBRA)) {
+       if (BGP_DEBUG(zebra, ZEBRA)) {
+               char buf[PREFIX_STRLEN];
 
-                       char buf[INET6_ADDRSTRLEN];
-                       vnc_zlog_debug_verbose(
-                               "%s: Zebra send: IPv6 route %s %s/%d nhp_count=%d",
-                               __func__, (add ? "add" : "del"),
-                               inet_ntop(AF_INET6, &p->u.prefix6, buf,
-                                         sizeof(buf)),
-                               p->prefixlen, nhp_count);
-               }
-
-               zapi_ipv6_route((add ? ZEBRA_IPV6_NEXTHOP_ADD
-                                    : ZEBRA_IPV6_NEXTHOP_DELETE),
-                               zclient_vnc, (struct prefix_ipv6 *)p, NULL,
-                               &api);
-       } else {
+               prefix2str(&api.prefix, buf, sizeof(buf));
                vnc_zlog_debug_verbose(
-                       "%s: unknown prefix address family, skipping",
-                       __func__);
-               return;
+                       "%s: Zebra send: route %s %s, nhp_count=%d", __func__,
+                       (add ? "add" : "del"), buf, nhp_count);
        }
+
+       zclient_route_send((add ? ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE),
+                          zclient_vnc, &api);
 }
 
 
@@ -1042,10 +893,8 @@ void vnc_zebra_init(struct thread_master *master)
        zclient_vnc = zclient_new(master);
        zclient_init(zclient_vnc, ZEBRA_ROUTE_VNC, 0);
 
-       zclient_vnc->redistribute_route_ipv4_add = vnc_zebra_read_ipv4;
-       zclient_vnc->redistribute_route_ipv4_del = vnc_zebra_read_ipv4;
-       zclient_vnc->redistribute_route_ipv6_add = vnc_zebra_read_ipv6;
-       zclient_vnc->redistribute_route_ipv6_del = vnc_zebra_read_ipv6;
+       zclient_vnc->redistribute_route_add = vnc_zebra_read_route;
+       zclient_vnc->redistribute_route_del = vnc_zebra_read_route;
 }
 
 void vnc_zebra_destroy(void)
index b115a871b9797d05b518a35f6a24b489ec07221e..c0094b1b88bbe6d7bcc36ce81eed9f4c758d64c4 100644 (file)
--- a/common.am
+++ b/common.am
@@ -13,8 +13,7 @@ CLIPPY_DEPS = $(HOSTTOOLS)lib/clippy $(top_srcdir)/python/clidef.py
 SUFFIXES = _clippy.c .proto .pb-c.c .pb-c.h .pb.h
 .c_clippy.c:
        @{ test -x $(top_builddir)/$(HOSTTOOLS)lib/clippy || $(MAKE) -C $(top_builddir)/$(HOSTTOOLS) lib/clippy; }
-       $(AM_V_CLIPPY)$(top_builddir)/$(HOSTTOOLS)lib/clippy $(top_srcdir)/python/clidef.py $< > $@.tmp
-       @{ test -f $@ && diff $@.tmp $@ >/dev/null 2>/dev/null; } && rm $@.tmp || mv $@.tmp $@
+       $(AM_V_CLIPPY)$(top_builddir)/$(HOSTTOOLS)lib/clippy $(top_srcdir)/python/clidef.py -o $@ $<
 
 ## automake's "ylwrap" is a great piece of GNU software... not. 
 .l.c:
index 574992342fd1f0ce45fd9d0f71fa3bb2f2eedcda..f6f38b47cf1d865ff37ae4d59fcd4c9427e4962d 100755 (executable)
@@ -195,6 +195,7 @@ fi
 
 dnl always want these CFLAGS
 AC_C_FLAG([-fno-omit-frame-pointer])
+AC_C_FLAG([-funwind-tables])
 AC_C_FLAG([-Wall])
 AC_C_FLAG([-Wextra])
 AC_C_FLAG([-Wmissing-prototypes])
@@ -320,6 +321,8 @@ AC_ARG_WITH(rfp-path,
   AS_HELP_STRING([--with-rfp-path[=DIR]],[path to replaced stub RFP used with BGP VNC]))
 AC_ARG_ENABLE(snmp,
   AS_HELP_STRING([--enable-snmp=ARG], [enable SNMP support (smux or agentx)]))
+AC_ARG_ENABLE(zeromq,
+  AS_HELP_STRING([--enable-zeromq], [enable ZeroMQ handler (libfrrzmq)]))
 AC_ARG_WITH(libpam,
   AS_HELP_STRING([--with-libpam], [use libpam for PAM support in vtysh]))
 AC_ARG_ENABLE(ospfapi,
@@ -344,7 +347,7 @@ AC_ARG_ENABLE(shell_access,
 AC_ARG_ENABLE(rtadv,
   AS_HELP_STRING([--disable-rtadv], [disable IPV6 router advertisement feature]))
 AC_ARG_ENABLE(irdp,
-  AS_HELP_STRING([--enable-irdp], [enable IRDP server support in zebra]))
+  AS_HELP_STRING([--disable-irdp], [enable IRDP server support in zebra (default if supported)]))
 AC_ARG_ENABLE(capabilities,
   AS_HELP_STRING([--disable-capabilities], [disable using POSIX capabilities]))
 AC_ARG_ENABLE(rusage,
@@ -570,10 +573,6 @@ else
   AC_MSG_RESULT(no)
 fi
 
-if test "${enable_irdp}" = "yes"; then
-  AC_DEFINE(HAVE_IRDP,, IRDP )
-fi
-
 if test x"${enable_user}" = x"no"; then
   enable_user=""
 else
@@ -1370,7 +1369,7 @@ fi
 dnl ------------------
 dnl check Net-SNMP library
 dnl ------------------
-if test "${enable_snmp}" != ""; then
+if test "${enable_snmp}" != "" -a "${enable_snmp}" != "no"; then
    AC_PATH_TOOL([NETSNMP_CONFIG], [net-snmp-config], [no])
    if test x"$NETSNMP_CONFIG" = x"no"; then
       AC_MSG_ERROR([--enable-snmp given but unable to find net-snmp-config])
@@ -1479,17 +1478,27 @@ AC_CHECK_MEMBERS([struct sockaddr.sa_len,
 dnl ---------------------------
 dnl IRDP/pktinfo/icmphdr checks
 dnl ---------------------------
-AC_CHECK_TYPES([struct in_pktinfo], 
- [AC_CHECK_TYPES([struct icmphdr],
-   [if test "${enable_irdp}" != "no"; then
-      AC_DEFINE(HAVE_IRDP,, IRDP)
-    fi],
-   [if test "${enable_irdp}" = "yes"; then
-      AC_MSG_ERROR(['IRDP requires in_pktinfo at the moment!'])
-    fi], [FRR_INCLUDES])],
- [if test "${enable_irdp}" = "yes"; then
-    AC_MSG_ERROR(['IRDP requires in_pktinfo at the moment!'])
-  fi], [FRR_INCLUDES])
+
+AC_CHECK_TYPES([struct in_pktinfo], [
+  AC_CHECK_TYPES([struct icmphdr], [
+    IRDP=true
+  ], [
+    IRDP=false
+  ], [FRR_INCLUDES])
+], [
+  IRDP=false
+], [FRR_INCLUDES])
+
+case "${enable_irdp}" in
+yes)
+  $IRDP || AC_MSG_ERROR(['IRDP requires in_pktinfo at the moment!'])
+  ;;
+no)
+  IRDP=false
+  ;;
+esac
+
+AM_CONDITIONAL(IRDP, $IRDP)
 
 dnl -----------------------
 dnl checking for IP_PKTINFO
@@ -1708,6 +1717,21 @@ AC_CHECK_HEADER([malloc.h],
   )
  ], [], FRR_INCLUDES)
 
+dnl ------
+dnl ZeroMQ
+dnl ------
+if test "x$enable_zeromq" != "xno"; then
+  PKG_CHECK_MODULES(ZEROMQ, [libzmq >= 4.0.0], [
+    AC_DEFINE(HAVE_ZEROMQ, 1, [Enable ZeroMQ support])
+    ZEROMQ=true
+  ], [
+    if test "x$enable_zeromq" = "xyes"; then
+      AC_MSG_ERROR([configuration specifies --enable-zeromq but libzmq was not found])
+    fi
+  ])
+fi
+AM_CONDITIONAL([ZEROMQ], test "x$ZEROMQ" = "xtrue")
+
 dnl ----------
 dnl configure date
 dnl ----------
diff --git a/doc/code/.gitignore b/doc/code/.gitignore
new file mode 100644 (file)
index 0000000..0505537
--- /dev/null
@@ -0,0 +1,3 @@
+/_templates
+/_build
+!/Makefile
diff --git a/doc/code/Makefile b/doc/code/Makefile
new file mode 100644 (file)
index 0000000..056b78e
--- /dev/null
@@ -0,0 +1,216 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS    =
+SPHINXBUILD   = sphinx-build
+PAPER         =
+BUILDDIR      = _build
+
+# User-friendly check for sphinx-build
+ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
+$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
+endif
+
+# Internal variables.
+PAPEROPT_a4     = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+# the i18n builder cannot share the environment and doctrees with the others
+I18NSPHINXOPTS  = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+.PHONY: help
+help:
+       @echo "Please use \`make <target>' where <target> is one of"
+       @echo "  html       to make standalone HTML files"
+       @echo "  dirhtml    to make HTML files named index.html in directories"
+       @echo "  singlehtml to make a single large HTML file"
+       @echo "  pickle     to make pickle files"
+       @echo "  json       to make JSON files"
+       @echo "  htmlhelp   to make HTML files and a HTML help project"
+       @echo "  qthelp     to make HTML files and a qthelp project"
+       @echo "  applehelp  to make an Apple Help Book"
+       @echo "  devhelp    to make HTML files and a Devhelp project"
+       @echo "  epub       to make an epub"
+       @echo "  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+       @echo "  latexpdf   to make LaTeX files and run them through pdflatex"
+       @echo "  latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
+       @echo "  text       to make text files"
+       @echo "  man        to make manual pages"
+       @echo "  texinfo    to make Texinfo files"
+       @echo "  info       to make Texinfo files and run them through makeinfo"
+       @echo "  gettext    to make PO message catalogs"
+       @echo "  changes    to make an overview of all changed/added/deprecated items"
+       @echo "  xml        to make Docutils-native XML files"
+       @echo "  pseudoxml  to make pseudoxml-XML files for display purposes"
+       @echo "  linkcheck  to check all external links for integrity"
+       @echo "  doctest    to run all doctests embedded in the documentation (if enabled)"
+       @echo "  coverage   to run coverage check of the documentation (if enabled)"
+
+.PHONY: clean
+clean:
+       rm -rf $(BUILDDIR)/*
+
+.PHONY: html
+html:
+       $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+       @echo
+       @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+.PHONY: dirhtml
+dirhtml:
+       $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
+       @echo
+       @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
+
+.PHONY: singlehtml
+singlehtml:
+       $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
+       @echo
+       @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
+
+.PHONY: pickle
+pickle:
+       $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
+       @echo
+       @echo "Build finished; now you can process the pickle files."
+
+.PHONY: json
+json:
+       $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
+       @echo
+       @echo "Build finished; now you can process the JSON files."
+
+.PHONY: htmlhelp
+htmlhelp:
+       $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
+       @echo
+       @echo "Build finished; now you can run HTML Help Workshop with the" \
+             ".hhp project file in $(BUILDDIR)/htmlhelp."
+
+.PHONY: qthelp
+qthelp:
+       $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
+       @echo
+       @echo "Build finished; now you can run "qcollectiongenerator" with the" \
+             ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
+       @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/FRR.qhcp"
+       @echo "To view the help file:"
+       @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/FRR.qhc"
+
+.PHONY: applehelp
+applehelp:
+       $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp
+       @echo
+       @echo "Build finished. The help book is in $(BUILDDIR)/applehelp."
+       @echo "N.B. You won't be able to view it unless you put it in" \
+             "~/Library/Documentation/Help or install it in your application" \
+             "bundle."
+
+.PHONY: devhelp
+devhelp:
+       $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
+       @echo
+       @echo "Build finished."
+       @echo "To view the help file:"
+       @echo "# mkdir -p $$HOME/.local/share/devhelp/FRR"
+       @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/FRR"
+       @echo "# devhelp"
+
+.PHONY: epub
+epub:
+       $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
+       @echo
+       @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
+
+.PHONY: latex
+latex:
+       $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+       @echo
+       @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
+       @echo "Run \`make' in that directory to run these through (pdf)latex" \
+             "(use \`make latexpdf' here to do that automatically)."
+
+.PHONY: latexpdf
+latexpdf:
+       $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+       @echo "Running LaTeX files through pdflatex..."
+       $(MAKE) -C $(BUILDDIR)/latex all-pdf
+       @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+.PHONY: latexpdfja
+latexpdfja:
+       $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+       @echo "Running LaTeX files through platex and dvipdfmx..."
+       $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
+       @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+.PHONY: text
+text:
+       $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
+       @echo
+       @echo "Build finished. The text files are in $(BUILDDIR)/text."
+
+.PHONY: man
+man:
+       $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
+       @echo
+       @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
+
+.PHONY: texinfo
+texinfo:
+       $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+       @echo
+       @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
+       @echo "Run \`make' in that directory to run these through makeinfo" \
+             "(use \`make info' here to do that automatically)."
+
+.PHONY: info
+info:
+       $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+       @echo "Running Texinfo files through makeinfo..."
+       make -C $(BUILDDIR)/texinfo info
+       @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
+
+.PHONY: gettext
+gettext:
+       $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
+       @echo
+       @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
+
+.PHONY: changes
+changes:
+       $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
+       @echo
+       @echo "The overview file is in $(BUILDDIR)/changes."
+
+.PHONY: linkcheck
+linkcheck:
+       $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
+       @echo
+       @echo "Link check complete; look for any errors in the above output " \
+             "or in $(BUILDDIR)/linkcheck/output.txt."
+
+.PHONY: doctest
+doctest:
+       $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
+       @echo "Testing of doctests in the sources finished, look at the " \
+             "results in $(BUILDDIR)/doctest/output.txt."
+
+.PHONY: coverage
+coverage:
+       $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage
+       @echo "Testing of coverage in the sources finished, look at the " \
+             "results in $(BUILDDIR)/coverage/python.txt."
+
+.PHONY: xml
+xml:
+       $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
+       @echo
+       @echo "Build finished. The XML files are in $(BUILDDIR)/xml."
+
+.PHONY: pseudoxml
+pseudoxml:
+       $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
+       @echo
+       @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
diff --git a/doc/code/conf.py b/doc/code/conf.py
new file mode 100644 (file)
index 0000000..38be7f2
--- /dev/null
@@ -0,0 +1,293 @@
+# -*- coding: utf-8 -*-
+#
+# FRR documentation build configuration file, created by
+# sphinx-quickstart on Tue Jan 31 16:00:52 2017.
+#
+# This file is execfile()d with the current directory set to its
+# containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys
+import os
+import re
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#sys.path.insert(0, os.path.abspath('.'))
+
+# -- General configuration ------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be
+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
+# ones.
+extensions = ['sphinx.ext.todo']
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix(es) of source filenames.
+# You can specify multiple suffix as a list of string:
+# source_suffix = ['.rst', '.md']
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = u'FRR'
+copyright = u'2017, FRR'
+author = u'FRR'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+
+# The short X.Y version.
+version = u'?.?'
+# The full version, including alpha/beta/rc tags.
+release = u'?.?-?'
+
+val = re.compile('^S\["([^"]+)"\]="(.*)"$')
+with open('../../config.status', 'r') as cfgstatus:
+    for ln in cfgstatus.readlines():
+        m = val.match(ln)
+        if m is None: continue
+        if m.group(1) == 'PACKAGE_VERSION':
+            release = m.group(2)
+            version = release.split('-')[0]
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#
+# This is also used if you do content translation via gettext catalogs.
+# Usually you set "language" from the command line for these cases.
+language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = ['_build']
+
+# The reST default role (used for this markup: `text`) to use for all
+# documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+# If true, keep warnings as "system message" paragraphs in the built documents.
+#keep_warnings = False
+
+# If true, `todo` and `todoList` produce output, else they produce nothing.
+todo_include_todos = True
+
+
+# -- Options for HTML output ----------------------------------------------
+
+# The theme to use for HTML and HTML Help pages.  See the documentation for
+# a list of builtin themes.
+html_theme = 'sphinx_rtd_theme'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further.  For a list of options available for each theme, see the
+# documentation.
+#html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+#html_theme_path = []
+
+# The name for this set of Sphinx documents.  If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# A shorter title for the navigation bar.  Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# Add any extra paths that contain custom files (such as robots.txt or
+# .htaccess) here, relative to this directory. These files are copied
+# directly to the root of the documentation.
+#html_extra_path = []
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_domain_indices = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+#html_show_sourcelink = True
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+#html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+#html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it.  The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# This is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = None
+
+# Language to be used for generating the HTML full-text search index.
+# Sphinx supports the following languages:
+#   'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja'
+#   'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr'
+#html_search_language = 'en'
+
+# A dictionary with options for the search language support, empty by default.
+# Now only 'ja' uses this config value
+#html_search_options = {'type': 'default'}
+
+# The name of a javascript file (relative to the configuration directory) that
+# implements a search results scorer. If empty, the default will be used.
+#html_search_scorer = 'scorer.js'
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'FRRdoc'
+
+# -- Options for LaTeX output ---------------------------------------------
+
+latex_elements = {
+# The paper size ('letterpaper' or 'a4paper').
+#'papersize': 'letterpaper',
+
+# The font size ('10pt', '11pt' or '12pt').
+#'pointsize': '10pt',
+
+# Additional stuff for the LaTeX preamble.
+#'preamble': '',
+
+# Latex figure (float) alignment
+#'figure_align': 'htbp',
+}
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title,
+#  author, documentclass [howto, manual, or own class]).
+latex_documents = [
+    (master_doc, 'FRR.tex', u'FRR Documentation',
+     u'FRR', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# If true, show page references after internal links.
+#latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+#latex_show_urls = False
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_domain_indices = True
+
+
+# -- Options for manual page output ---------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+    (master_doc, 'frr', u'FRR Documentation',
+     [author], 1)
+]
+
+# If true, show URL addresses after external links.
+#man_show_urls = False
+
+
+# -- Options for Texinfo output -------------------------------------------
+
+# Grouping the document tree into Texinfo files. List of tuples
+# (source start file, target name, title, author,
+#  dir menu entry, description, category)
+texinfo_documents = [
+    (master_doc, 'FRR', u'FRR Documentation',
+     author, 'FRR', 'One line description of project.',
+     'Miscellaneous'),
+]
+
+# Documents to append as an appendix to all manuals.
+#texinfo_appendices = []
+
+# If false, no module index is generated.
+#texinfo_domain_indices = True
+
+# How to display URL addresses: 'footnote', 'no', or 'inline'.
+#texinfo_show_urls = 'footnote'
+
+# If true, do not generate a @detailmenu in the "Top" node's menu.
+#texinfo_no_detailmenu = False
diff --git a/doc/code/hooks.rst b/doc/code/hooks.rst
new file mode 100644 (file)
index 0000000..0afa297
--- /dev/null
@@ -0,0 +1,171 @@
+.. highlight:: c
+
+Hooks
+=====
+
+Libfrr provides type-safe subscribable hook points where other pieces of
+code can add one or more callback functions.  "type-safe" in this case
+applies to the function pointers used for subscriptions.  The
+implementations checks (at compile-time) wheter a callback to be added has
+the appropriate function signature (parameters) for the hook.
+
+Example:
+
+.. code-block:: c
+     :caption: mydaemon.h
+
+     #include "hook.h"
+     DECLARE_HOOK(some_update_event, (struct eventinfo *info), (info))
+
+.. code-block:: c
+     :caption: mydaemon.c
+
+     #include "mydaemon.h"
+     DEFINE_HOOK(some_update_event, (struct eventinfo *info), (info))
+     ...
+     hook_call(some_update_event, info);
+
+.. code-block:: c
+     :caption: mymodule.c
+
+     #include "mydaemon.h"
+     static int event_handler(struct eventinfo *info);
+     ...
+     hook_register(some_update_event, event_handler);
+
+Do not use parameter names starting with "hook", these can collide with
+names used by the hook code itself.
+
+
+Return values
+-------------
+
+Callbacks to be placed on hooks always return "int" for now;  hook_call will
+sum up the return values from each called function.  (The default is 0 if no
+callbacks are registered.)
+
+There are no pre-defined semantics for the value, in most cases it is
+ignored.  For success/failure indication, 0 should be success, and
+handlers should make sure to only return 0 or 1 (not -1 or other values).
+
+There is no built-in way to abort executing a chain after a failure of one
+of the callbacks.  If this is needed, the hook can use an extra
+``bool *aborted`` argument.
+
+
+Priorities
+----------
+
+Hooks support a "priority" value for ordering registered calls
+relative to each other.  The priority is a signed integer where lower
+values are called earlier.  There are also "Koohs", which is hooks with
+reverse priority ordering (for cleanup/deinit hooks, so you can use the
+same priority value).
+
+Recommended priority value ranges are:
+
+======================== ===================================================
+Range                    Usage
+------------------------ ---------------------------------------------------
+ -999 ...     0 ...  999 main executable / daemon, or library
+
+-1999 ... -1000          modules registering calls that should run before
+                         the daemon's bits
+
+1000 ... 1999            modules' calls that should run after daemon's
+                         (includes default value: 1000)
+======================== ===================================================
+
+Note: the default value is 1000, based on the following 2 expectations:
+
+- most hook_register() usage will be in loadable modules
+- usage of hook_register() in the daemon itself may need relative ordering
+  to itself, making an explicit value the expected case
+
+The priority value is passed as extra argument on hook_register_prio() /
+hook_register_arg_prio().  Whether a hook runs in reverse is determined
+solely by the code defining / calling the hook.  (DECLARE_KOOH is actually
+the same thing as DECLARE_HOOK, it's just there to make it obvious.)
+
+
+Definition
+----------
+
+.. c:macro:: DECLARE_HOOK(name, arglist, passlist)
+.. c:macro:: DECLARE_KOOH(name, arglist, passlist)
+
+   :param name: Name of the hook to be defined
+   :param arglist: Function definition style parameter list in braces.
+   :param passlist: List of the same parameters without their types.
+
+   Note:  the second and third macro args must be the hook function's
+   parameter list, with the same names for each parameter.  The second
+   macro arg is with types (used for defining things), the third arg is
+   just the names (used for passing along parameters).
+
+   This macro must be placed in a header file;  this header file must be
+   included to register a callback on the hook.
+
+   Examples:
+
+   .. code-block:: c
+
+      DECLARE_HOOK(foo, (), ())
+      DECLARE_HOOK(bar, (int arg), (arg))
+      DECLARE_HOOK(baz, (const void *x, in_addr_t y), (x, y))
+
+.. c:macro:: DEFINE_HOOK(name, arglist, passlist)
+
+   Implements an hook.  Each ``DECLARE_HOOK`` must have be accompanied by
+   exactly one ``DEFINE_HOOK``, which needs to be placed in a source file.
+   **The hook can only be called from this source file.**  This is intentional
+   to avoid overloading and/or misusing hooks for distinct purposes.
+
+   The compiled source file will include a global symbol with the name of the
+   hook prefixed by `_hook_`.  Trying to register a callback for a hook that
+   doesn't exist will therefore result in a linker error, or a module
+   load-time error for dynamic modules.
+
+.. c:macro:: DEFINE_KOOH(name, arglist, passlist)
+
+   Same as ``DEFINE_HOOK``, but the sense of priorities / order of callbacks
+   is reversed.  This should be used for cleanup hooks.
+
+.. c:function:: int hook_call(name, ...)
+
+   Calls the specified named hook.  Parameters to the hook are passed right
+   after the hook name, e.g.:
+
+   .. code-block:: c
+
+      hook_call(foo);
+      hook_call(bar, 0);
+      hook_call(baz, NULL, INADDR_ANY);
+
+   Returns the sum of return values from all callbacks.  The ``DEFINE_HOOK``
+   statement for the hook must be placed in the file before any ``hook_call``
+   use of the hook.
+
+
+Callback registration
+---------------------
+
+.. c:function:: void hook_register(name, int (*callback)(...))
+.. c:function:: void hook_register_prio(name, int priority, int (*callback)(...))
+.. c:function:: void hook_register_arg(name, int (*callback)(void *arg, ...), void *arg)
+.. c:function:: void hook_register_arg_prio(name, int priority, int (*callback)(void *arg, ...), void *arg)
+
+   Register a callback with an hook.  If the caller needs to pass an extra
+   argument to the callback, the _arg variant can be used and the extra
+   parameter will be passed as first argument to the callback.  There is no
+   typechecking for this argument.
+
+   The priority value is used as described above.  The variants without a
+   priority parameter use 1000 as priority value.
+
+.. c:function:: void hook_unregister(name, int (*callback)(...))
+.. c:function:: void hook_unregister_arg(name, int (*callback)(void *arg, ...), void *arg)
+
+   Removes a previously registered callback from a hook.  Note that there
+   is no _prio variant of these calls.  The priority value is only used during
+   registration.
diff --git a/doc/code/index.rst b/doc/code/index.rst
new file mode 100644 (file)
index 0000000..79647d0
--- /dev/null
@@ -0,0 +1,18 @@
+Welcome to FRR's documentation!
+===============================
+
+Contents:
+
+.. toctree::
+   :maxdepth: 2
+
+   library
+
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
+
diff --git a/doc/code/library.rst b/doc/code/library.rst
new file mode 100644 (file)
index 0000000..dd46021
--- /dev/null
@@ -0,0 +1,10 @@
+libfrr library facilities
+=========================
+
+.. toctree::
+   :maxdepth: 2
+
+   memtypes
+   hooks
+
+
diff --git a/doc/code/memtypes.rst b/doc/code/memtypes.rst
new file mode 100644 (file)
index 0000000..62d211e
--- /dev/null
@@ -0,0 +1,117 @@
+.. highlight:: c
+
+Memtypes
+========
+
+FRR includes wrappers arround ``malloc()`` and ``free()`` that count the number
+of objects currently allocated, for each of a defined ``MTYPE``.
+
+To this extent, there are `memory groups` and `memory types`.  Each memory
+type must belong to a memory group, this is used just to provide some basic
+structure.
+
+Example:
+
+.. code-block:: c
+     :caption: mydaemon.h
+
+     DECLARE_MGROUP(MYDAEMON)
+     DECLARE_MTYPE(MYNEIGHBOR)
+
+.. code-block:: c
+     :caption: mydaemon.c
+
+     DEFINE_MGROUP(      MYDAEMON, "My daemon's memory")
+     DEFINE_MTYPE(       MYDAEMON, MYNEIGHBOR,     "Neighbor entry")
+     DEFINE_MTYPE_STATIC(MYDAEMON, MYNEIGHBORNAME, "Neighbor name")
+
+     struct neigh *neighbor_new(const char *name)
+     {
+        struct neigh *n = XMALLOC(MYNEIGHBOR, sizeof(*n));
+        n->name = XSTRDUP(MYNEIGHBORNAME, name);
+        return n;
+     }
+
+     void neighbor_free(struct neigh *n)
+     {
+        XFREE(MYNEIGHBORNAME, n->name);
+        XFREE(MYNEIGHBOR, n);
+     }
+
+
+Definition
+----------
+
+.. c:macro:: DECLARE_MGROUP(name)
+
+   This macro forward-declares a memory group and should be placed in a
+   ``.h`` file.  It expands to an ``extern struct memgroup`` statement.
+
+.. c:macro:: DEFINE_MGROUP(mname, description)
+
+   Defines/implements a memory group.  Must be placed into exactly one ``.c``
+   file (multiple inclusion will result in a link-time symbol conflict).
+
+   Contains additional logic (constructor and destructor) to register the
+   memory group in a global list.
+
+.. c:macro:: DECLARE_MTYPE(name)
+
+   Forward-declares a memory type and makes ``MTYPE_name`` available for use.
+   Note that the ``MTYPE_`` prefix must not be included in the name, it is
+   automatically prefixed.
+
+   ``MTYPE_name`` is created as a `static const` symbol, i.e. a compile-time
+   constant.  It refers to an ``extern struct memtype _mt_name``, where `name`
+   is replaced with the actual name.
+
+.. c:macro:: DEFINE_MTYPE(group, name, description)
+
+   Define/implement a memory type, must be placed into exactly one ``.c``
+   file (multiple inclusion will result in a link-time symbol conflict).
+
+   Like ``DEFINE_MGROUP``, this contains actual code to register the MTYPE
+   under its group.
+
+.. c:macro:: DEFINE_MTYPE_STATIC(group, name, description)
+
+   Same as ``DEFINE_MTYPE``, but the ``DEFINE_MTYPE_STATIC`` variant places
+   the C ``static`` keyword on the definition, restricting the MTYPE's
+   availability to the current source file.  This should be appropriate in
+   >80% of cases.
+
+   .. todo::
+   
+      Daemons currently have ``daemon_memory.[ch]`` files listing all of
+      their MTYPEs.  This is not how it should be, most of these types
+      should be moved into the appropriate files where they are used.
+      Only a few MTYPEs should remain non-static after that.
+
+
+Usage
+-----
+
+.. c:function:: void *XMALLOC(struct memtype *mtype, size_t size)
+
+.. c:function:: void *XCALLOC(struct memtype *mtype, size_t size)
+
+.. c:function:: void *XSTRDUP(struct memtype *mtype, size_t size)
+
+   Allocation wrappers for malloc/calloc/realloc/strdup, taking an extra
+   mtype parameter.
+
+.. c:function:: void *XREALLOC(struct memtype *mtype, void *ptr, size_t size)
+
+   Wrapper around realloc() with MTYPE tracking.  Note that ``ptr`` may
+   be NULL, in which case the function does the same as XMALLOC (regardless
+   of whether the system realloc() supports this.)
+
+.. c:function:: void XFREE(struct memtype *mtype, void *ptr)
+
+   Wrapper around free(), again taking an extra mtype parameter.  This is
+   actually a macro, with the following additional properties:
+
+   - the macro contains ``ptr = NULL``
+   - if ptr is NULL, no operation is performed (as is guaranteed by system
+     implementations.)  Do not surround XFREE with ``if (ptr != NULL)``
+     checks.
index aca6e5981601ab50f7aa83253403c1b8def48d88..74515c98cb6a23d3556a0b30bdc71e627bcb1fb3 100644 (file)
@@ -158,7 +158,7 @@ const char *eigrp_topology_ip_string(struct eigrp_prefix_entry *tn)
        static char buf[EIGRP_IF_STRING_MAXLEN] = "";
        u_int32_t ifaddr;
 
-       ifaddr = ntohl(tn->destination_ipv4->prefix.s_addr);
+       ifaddr = ntohl(tn->destination->u.prefix4.s_addr);
        snprintf(buf, EIGRP_IF_STRING_MAXLEN, "%u.%u.%u.%u",
                 (ifaddr >> 24) & 0xff, (ifaddr >> 16) & 0xff,
                 (ifaddr >> 8) & 0xff, ifaddr & 0xff);
@@ -289,11 +289,12 @@ void show_ip_eigrp_topology_header(struct vty *vty, struct eigrp *eigrp)
 void show_ip_eigrp_prefix_entry(struct vty *vty, struct eigrp_prefix_entry *tn)
 {
        struct list *successors = eigrp_topology_get_successor(tn);
+       char buffer[PREFIX_STRLEN];
 
        vty_out(vty, "%-3c", (tn->state > 0) ? 'A' : 'P');
 
-       vty_out(vty, "%s/%u, ", inet_ntoa(tn->destination_ipv4->prefix),
-               tn->destination_ipv4->prefixlen);
+       vty_out(vty, "%s, ",
+               prefix2str(tn->destination, buffer, PREFIX_STRLEN));
        vty_out(vty, "%u successors, ", successors->count);
        vty_out(vty, "FD is %u, serno: %" PRIu64 " \n", tn->fdistance,
                tn->serno);
@@ -323,12 +324,12 @@ void show_ip_eigrp_neighbor_entry(struct vty *vty, struct eigrp *eigrp,
 }
 
 
-DEFUN (show_debugging_eigrp,
-       show_debugging_eigrp_cmd,
-       "show debugging eigrp",
-       SHOW_STR
-       DEBUG_STR
-       EIGRP_STR)
+DEFUN_NOSH (show_debugging_eigrp,
+           show_debugging_eigrp_cmd,
+           "show debugging [eigrp]",
+           SHOW_STR
+           DEBUG_STR
+           EIGRP_STR)
 {
        int i;
 
index 8e2a26447eca0b97b84f26a766b3f3c4c84a7ddc..47cd112cf5da88fae402514d34fa6f45137eb09e 100644 (file)
@@ -178,7 +178,7 @@ struct {
  * Return number of occurred event (arrow in diagram).
  *
  */
-int eigrp_get_fsm_event(struct eigrp_fsm_action_message *msg)
+static int eigrp_get_fsm_event(struct eigrp_fsm_action_message *msg)
 {
        // Loading base information from message
        // struct eigrp *eigrp = msg->eigrp;
@@ -204,8 +204,7 @@ int eigrp_get_fsm_event(struct eigrp_fsm_action_message *msg)
        switch (actual_state) {
        case EIGRP_FSM_STATE_PASSIVE: {
                struct eigrp_neighbor_entry *head =
-                       (struct eigrp_neighbor_entry *)
-                               entry->prefix->entries->head->data;
+                       listnode_head(prefix->entries);
 
                if (head->reported_distance < prefix->fdistance) {
                        return EIGRP_FSM_KEEP_STATE;
@@ -226,8 +225,7 @@ int eigrp_get_fsm_event(struct eigrp_fsm_action_message *msg)
        case EIGRP_FSM_STATE_ACTIVE_0: {
                if (msg->packet_type == EIGRP_OPC_REPLY) {
                        struct eigrp_neighbor_entry *head =
-                               (struct eigrp_neighbor_entry *)
-                               entry->prefix->entries->head->data;
+                               listnode_head(prefix->entries);
 
                        listnode_delete(prefix->rij, entry->adv_router);
                        if (prefix->rij->count)
@@ -279,8 +277,7 @@ int eigrp_get_fsm_event(struct eigrp_fsm_action_message *msg)
        case EIGRP_FSM_STATE_ACTIVE_2: {
                if (msg->packet_type == EIGRP_OPC_REPLY) {
                        struct eigrp_neighbor_entry *head =
-                               (struct eigrp_neighbor_entry *)
-                               prefix->entries->head->data;
+                               listnode_head(prefix->entries);
 
                        listnode_delete(prefix->rij, entry->adv_router);
                        if (prefix->rij->count) {
@@ -331,9 +328,10 @@ int eigrp_get_fsm_event(struct eigrp_fsm_action_message *msg)
  * Function made to execute in separate thread.
  * Load argument from thread and execute proper NSM function
  */
-int eigrp_fsm_event(struct eigrp_fsm_action_message *msg, int event)
+int eigrp_fsm_event(struct eigrp_fsm_action_message *msg)
 {
-       zlog_info("EIGRP AS: %d State: %d  Event: %d Network: %s\n",
+       int event = eigrp_get_fsm_event(msg);
+       zlog_info("EIGRP AS: %d State: %d  Event: %d Network: %s",
                  msg->eigrp->AS, msg->prefix->state, event,
                  eigrp_topology_ip_string(msg->prefix));
        (*(NSM[msg->prefix->state][event].func))(msg);
@@ -350,16 +348,15 @@ int eigrp_fsm_event_nq_fcn(struct eigrp_fsm_action_message *msg)
        struct eigrp *eigrp = msg->eigrp;
        struct eigrp_prefix_entry *prefix = msg->prefix;
        struct list *successors = eigrp_topology_get_successor(prefix);
+       struct eigrp_neighbor_entry *ne;
 
        assert(successors); // If this is NULL we have shit the bed, fun huh?
 
+       ne = listnode_head(successors);
        prefix->state = EIGRP_FSM_STATE_ACTIVE_1;
        prefix->rdistance = prefix->distance = prefix->fdistance =
-               ((struct eigrp_neighbor_entry *)successors->head->data)
-                       ->distance;
-       prefix->reported_metric =
-               ((struct eigrp_neighbor_entry *)successors->head->data)
-                       ->total_metric;
+               ne->distance;
+       prefix->reported_metric = ne->total_metric;
 
        if (eigrp_nbr_count_get()) {
                prefix->req_action |= EIGRP_FSM_NEED_QUERY;
@@ -379,16 +376,15 @@ int eigrp_fsm_event_q_fcn(struct eigrp_fsm_action_message *msg)
        struct eigrp *eigrp = msg->eigrp;
        struct eigrp_prefix_entry *prefix = msg->prefix;
        struct list *successors = eigrp_topology_get_successor(prefix);
+       struct eigrp_neighbor_entry *ne;
 
        assert(successors); // If this is NULL somebody poked us in the eye.
 
+       ne = listnode_head(successors);
        prefix->state = EIGRP_FSM_STATE_ACTIVE_3;
        prefix->rdistance = prefix->distance = prefix->fdistance =
-               ((struct eigrp_neighbor_entry *)successors->head->data)
-                       ->distance;
-       prefix->reported_metric =
-               ((struct eigrp_neighbor_entry *)successors->head->data)
-                       ->total_metric;
+               ne->distance;
+       prefix->reported_metric = ne->total_metric;
        if (eigrp_nbr_count_get()) {
                prefix->req_action |= EIGRP_FSM_NEED_QUERY;
                listnode_add(eigrp->topology_changes_internalIPV4, prefix);
@@ -405,21 +401,15 @@ int eigrp_fsm_event_q_fcn(struct eigrp_fsm_action_message *msg)
 int eigrp_fsm_event_keep_state(struct eigrp_fsm_action_message *msg)
 {
        struct eigrp_prefix_entry *prefix = msg->prefix;
+       struct eigrp_neighbor_entry *ne = listnode_head(prefix->entries);
 
        if (prefix->state == EIGRP_FSM_STATE_PASSIVE) {
                if (!eigrp_metrics_is_same(prefix->reported_metric,
-                                          ((struct eigrp_neighbor_entry *)
-                                                   prefix->entries->head->data)
-                                                  ->total_metric)) {
+                                          ne->total_metric)) {
                        prefix->rdistance = prefix->fdistance =
-                               prefix->distance =
-                                       ((struct eigrp_neighbor_entry *)
-                                                prefix->entries->head->data)
-                                               ->distance;
+                               prefix->distance = ne->distance;
                        prefix->reported_metric =
-                               ((struct eigrp_neighbor_entry *)
-                                        prefix->entries->head->data)
-                                       ->total_metric;
+                               ne->total_metric;
                        if (msg->packet_type == EIGRP_OPC_QUERY)
                                eigrp_send_reply(msg->adv_router, prefix);
                        prefix->req_action |= EIGRP_FSM_NEED_UPDATE;
@@ -441,22 +431,20 @@ int eigrp_fsm_event_lr(struct eigrp_fsm_action_message *msg)
 {
        struct eigrp *eigrp = msg->eigrp;
        struct eigrp_prefix_entry *prefix = msg->prefix;
+       struct eigrp_neighbor_entry *ne = listnode_head(prefix->entries);
+
        prefix->fdistance = prefix->distance = prefix->rdistance =
-               ((struct eigrp_neighbor_entry *)(prefix->entries->head->data))
-                       ->distance;
-       prefix->reported_metric =
-               ((struct eigrp_neighbor_entry *)(prefix->entries->head->data))
-                       ->total_metric;
+               ne->distance;
+       prefix->reported_metric = ne->total_metric;
 
        if (prefix->state == EIGRP_FSM_STATE_ACTIVE_3) {
                struct list *successors = eigrp_topology_get_successor(prefix);
 
                assert(successors); // It's like Napolean and Waterloo
 
-               eigrp_send_reply(
-                       ((struct eigrp_neighbor_entry *)successors->head->data)
-                               ->adv_router,
-                       prefix);
+               ne = listnode_head(successors);
+               eigrp_send_reply(ne->adv_router,
+                                prefix);
                list_delete(successors);
        }
 
@@ -473,15 +461,15 @@ int eigrp_fsm_event_lr(struct eigrp_fsm_action_message *msg)
 int eigrp_fsm_event_dinc(struct eigrp_fsm_action_message *msg)
 {
        struct list *successors = eigrp_topology_get_successor(msg->prefix);
+       struct eigrp_neighbor_entry *ne;
 
        assert(successors); // Trump and his big hands
 
+       ne = listnode_head(successors);
        msg->prefix->state = msg->prefix->state == EIGRP_FSM_STATE_ACTIVE_1
                                     ? EIGRP_FSM_STATE_ACTIVE_0
                                     : EIGRP_FSM_STATE_ACTIVE_2;
-       msg->prefix->distance =
-               ((struct eigrp_neighbor_entry *)successors->head->data)
-                       ->distance;
+       msg->prefix->distance = ne->distance;
        if (!msg->prefix->rij->count)
                (*(NSM[msg->prefix->state][eigrp_get_fsm_event(msg)].func))(
                        msg);
@@ -495,13 +483,11 @@ int eigrp_fsm_event_lr_fcs(struct eigrp_fsm_action_message *msg)
 {
        struct eigrp *eigrp = msg->eigrp;
        struct eigrp_prefix_entry *prefix = msg->prefix;
+       struct eigrp_neighbor_entry *ne = listnode_head(prefix->entries);
+
        prefix->state = EIGRP_FSM_STATE_PASSIVE;
-       prefix->distance = prefix->rdistance =
-               ((struct eigrp_neighbor_entry *)(prefix->entries->head->data))
-                       ->distance;
-       prefix->reported_metric =
-               ((struct eigrp_neighbor_entry *)(prefix->entries->head->data))
-                       ->total_metric;
+       prefix->distance = prefix->rdistance = ne->distance;
+       prefix->reported_metric = ne->total_metric;
        prefix->fdistance = prefix->fdistance > prefix->distance
                                    ? prefix->distance
                                    : prefix->fdistance;
@@ -510,11 +496,9 @@ int eigrp_fsm_event_lr_fcs(struct eigrp_fsm_action_message *msg)
 
                assert(successors); // Having a spoon and all you need is a
                                    // knife
-
-               eigrp_send_reply(
-                       ((struct eigrp_neighbor_entry *)successors->head->data)
-                               ->adv_router,
-                       prefix);
+               ne = listnode_head(successors);
+               eigrp_send_reply(ne->adv_router,
+                                prefix);
 
                list_delete(successors);
        }
@@ -531,6 +515,7 @@ int eigrp_fsm_event_lr_fcn(struct eigrp_fsm_action_message *msg)
 {
        struct eigrp *eigrp = msg->eigrp;
        struct eigrp_prefix_entry *prefix = msg->prefix;
+       struct eigrp_neighbor_entry *best_successor;
        struct list *successors = eigrp_topology_get_successor(prefix);
 
        assert(successors); // Routing without a stack
@@ -538,8 +523,8 @@ int eigrp_fsm_event_lr_fcn(struct eigrp_fsm_action_message *msg)
        prefix->state = prefix->state == EIGRP_FSM_STATE_ACTIVE_0
                                ? EIGRP_FSM_STATE_ACTIVE_1
                                : EIGRP_FSM_STATE_ACTIVE_3;
-       struct eigrp_neighbor_entry *best_successor =
-               ((struct eigrp_neighbor_entry *)(successors->head->data));
+
+       best_successor = listnode_head(successors);
        prefix->rdistance = prefix->distance = best_successor->distance;
        prefix->reported_metric = best_successor->total_metric;
 
@@ -559,13 +544,13 @@ int eigrp_fsm_event_lr_fcn(struct eigrp_fsm_action_message *msg)
 int eigrp_fsm_event_qact(struct eigrp_fsm_action_message *msg)
 {
        struct list *successors = eigrp_topology_get_successor(msg->prefix);
+       struct eigrp_neighbor_entry *ne;
 
        assert(successors); // Cats and no Dogs
 
+       ne = listnode_head(successors);
        msg->prefix->state = EIGRP_FSM_STATE_ACTIVE_2;
-       msg->prefix->distance =
-               ((struct eigrp_neighbor_entry *)(successors->head->data))
-                       ->distance;
+       msg->prefix->distance = ne->distance;
 
        list_delete(successors);
        return 1;
index 97a1f49281a6dcd95bd43b52a546d4555eb0f8d6..8fad9d1f5118bdd134a33b2cb0e10d4a81c077a7 100644 (file)
@@ -28,8 +28,7 @@
 #ifndef _ZEBRA_EIGRP_FSM_H
 #define _ZEBRA_EIGRP_FSM_H
 
-extern int eigrp_get_fsm_event(struct eigrp_fsm_action_message *);
-extern int eigrp_fsm_event(struct eigrp_fsm_action_message *, int);
+extern int eigrp_fsm_event(struct eigrp_fsm_action_message *msg);
 
 
 #endif /* _ZEBRA_EIGRP_DUAL_H */
index b7c2f7f18d86a4570804b2bc3008e61d1e37ee41..ef10ebf54c7f59ea57b111470ed13fa84ac67252 100644 (file)
@@ -405,6 +405,20 @@ void eigrp_hello_receive(struct eigrp *eigrp, struct ip *iph,
                           inet_ntoa(nbr->src));
 }
 
+u_int32_t FRR_MAJOR;
+u_int32_t FRR_MINOR;
+
+void eigrp_sw_version_initialize(void)
+{
+       char ver_string[] = VERSION;
+       char *dash = strstr(ver_string, "-");
+
+       if (dash)
+               dash[0] = '\0';
+
+       sscanf(ver_string, "%d.%d", &FRR_MAJOR, &FRR_MINOR);
+}
+
 /**
  * @fn eigrp_sw_version_encode
  *
@@ -425,10 +439,8 @@ static u_int16_t eigrp_sw_version_encode(struct stream *s)
        stream_putw(s, EIGRP_TLV_SW_VERSION);
        stream_putw(s, length);
 
-       // encode the version of quagga we're running
-       // DVS: need to figure out a cleaner way to do this
-       stream_putc(s, 0);  //!< major os version
-       stream_putc(s, 99); //!< minor os version
+       stream_putc(s, FRR_MAJOR);  //!< major os version
+       stream_putc(s, FRR_MINOR); //!< minor os version
 
        /* and the core eigrp version */
        stream_putc(s, EIGRP_MAJOR_VERSION);
@@ -614,11 +626,11 @@ static struct eigrp_packet *eigrp_hello_encode(struct eigrp_interface *ei,
        u_int16_t length = EIGRP_HEADER_LEN;
 
        // allocate a new packet to be sent
-       ep = eigrp_packet_new(ei->ifp->mtu);
+       ep = eigrp_packet_new(ei->ifp->mtu, NULL);
 
        if (ep) {
                // encode common header feilds
-               eigrp_packet_header_init(EIGRP_OPC_HELLO, ei, ep->s, 0, 0, ack);
+               eigrp_packet_header_init(EIGRP_OPC_HELLO, ei->eigrp, ep->s, 0, 0, ack);
 
                // encode Authentication TLV
                if ((IF_DEF_PARAMS(ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5)
@@ -707,7 +719,7 @@ void eigrp_hello_send_ack(struct eigrp_neighbor *nbr)
                                   inet_ntoa(nbr->src));
 
                /* Add packet to the top of the interface output queue*/
-               eigrp_fifo_push_head(nbr->ei->obuf, ep);
+               eigrp_fifo_push(nbr->ei->obuf, ep);
 
                /* Hook thread to write packet. */
                if (nbr->ei->on_write_q == 0) {
@@ -755,7 +767,7 @@ void eigrp_hello_send(struct eigrp_interface *ei, u_char flags,
 
        if (ep) {
                // Add packet to the top of the interface output queue
-               eigrp_fifo_push_head(ei->obuf, ep);
+               eigrp_fifo_push(ei->obuf, ep);
 
                /* Hook thread to write packet. */
                if (ei->on_write_q == 0) {
index 7f05e147038c17778d1dd79b32a51e70e2aa6a2a..aa5951600250081076d7e17ddb27dd55f5342e5b 100644 (file)
@@ -53,6 +53,7 @@
 #include "eigrpd/eigrp_network.h"
 #include "eigrpd/eigrp_topology.h"
 #include "eigrpd/eigrp_memory.h"
+#include "eigrpd/eigrp_fsm.h"
 
 static void eigrp_delete_from_if(struct interface *, struct eigrp_interface *);
 
@@ -150,8 +151,8 @@ struct list *eigrp_iflist;
 void eigrp_if_init()
 {
        /* Initialize Zebra interface data structure. */
-       if_add_hook(IF_NEW_HOOK, eigrp_if_new_hook);
-       if_add_hook(IF_DELETE_HOOK, eigrp_if_delete_hook);
+       hook_register_prio(if_add, 0, eigrp_if_new_hook);
+       hook_register_prio(if_del, 0, eigrp_if_delete_hook);
 }
 
 int eigrp_if_new_hook(struct interface *ifp)
@@ -224,14 +225,14 @@ void eigrp_del_if_params(struct eigrp_if_params *eip)
 struct eigrp_if_params *eigrp_lookup_if_params(struct interface *ifp,
                                               struct in_addr addr)
 {
-       struct prefix_ipv4 p;
+       struct prefix p;
        struct route_node *rn;
 
        p.family = AF_INET;
        p.prefixlen = IPV4_MAX_PREFIXLEN;
-       p.prefix = addr;
+       p.u.prefix4 = addr;
 
-       rn = route_node_lookup(IF_OIFS_PARAMS(ifp), (struct prefix *)&p);
+       rn = route_node_lookup(IF_OIFS_PARAMS(ifp), &p);
 
        if (rn) {
                route_unlock_node(rn);
@@ -279,49 +280,63 @@ int eigrp_if_up(struct eigrp_interface *ei)
 
        /*Add connected entry to topology table*/
 
-       struct prefix_ipv4 dest_addr;
+       ne = eigrp_neighbor_entry_new();
+       ne->ei = ei;
+       ne->reported_metric = metric;
+       ne->total_metric = metric;
+       ne->distance = eigrp_calculate_metrics(eigrp, metric);
+       ne->reported_distance = 0;
+       ne->adv_router = eigrp->neighbor_self;
+       ne->flags = EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG;
+
+       struct prefix dest_addr;
 
        dest_addr.family = AF_INET;
-       dest_addr.prefix = ei->connected->address->u.prefix4;
+       dest_addr.u.prefix4 = ei->connected->address->u.prefix4;
        dest_addr.prefixlen = ei->connected->address->prefixlen;
-       apply_mask_ipv4(&dest_addr);
+       apply_mask(&dest_addr);
        pe = eigrp_topology_table_lookup_ipv4(eigrp->topology_table,
                                              &dest_addr);
 
        if (pe == NULL) {
                pe = eigrp_prefix_entry_new();
                pe->serno = eigrp->serno;
-               pe->destination_ipv4 = prefix_ipv4_new();
-               prefix_copy((struct prefix *)pe->destination_ipv4,
-                           (struct prefix *)&dest_addr);
+               pe->destination = (struct prefix *)prefix_ipv4_new();
+               prefix_copy(pe->destination, &dest_addr);
                pe->af = AF_INET;
                pe->nt = EIGRP_TOPOLOGY_TYPE_CONNECTED;
 
+               ne->prefix = pe;
+               pe->reported_metric = metric;
                pe->state = EIGRP_FSM_STATE_PASSIVE;
                pe->fdistance = eigrp_calculate_metrics(eigrp, metric);
                pe->req_action |= EIGRP_FSM_NEED_UPDATE;
                eigrp_prefix_entry_add(eigrp->topology_table, pe);
                listnode_add(eigrp->topology_changes_internalIPV4, pe);
-       }
-       ne = eigrp_neighbor_entry_new();
-       ne->ei = ei;
-       ne->reported_metric = metric;
-       ne->total_metric = metric;
-       ne->distance = eigrp_calculate_metrics(eigrp, metric);
-       ne->reported_distance = 0;
-       ne->prefix = pe;
-       ne->adv_router = eigrp->neighbor_self;
-       ne->flags = EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG;
-       eigrp_neighbor_entry_add(pe, ne);
 
-       for (ALL_LIST_ELEMENTS(eigrp->eiflist, node, nnode, ei2)) {
-               if (ei2->nbrs->count != 0) {
+               eigrp_neighbor_entry_add(pe, ne);
+
+               for (ALL_LIST_ELEMENTS(eigrp->eiflist, node, nnode, ei2)) {
                        eigrp_update_send(ei2);
                }
-       }
 
-       pe->req_action &= ~EIGRP_FSM_NEED_UPDATE;
-       listnode_delete(eigrp->topology_changes_internalIPV4, pe);
+               pe->req_action &= ~EIGRP_FSM_NEED_UPDATE;
+               listnode_delete(eigrp->topology_changes_internalIPV4, pe);
+       } else {
+               struct eigrp_fsm_action_message msg;
+
+               ne->prefix = pe;
+               eigrp_neighbor_entry_add(pe, ne);
+
+               msg.packet_type = EIGRP_OPC_UPDATE;
+               msg.eigrp = eigrp;
+               msg.data_type = EIGRP_CONNECTED;
+               msg.adv_router = NULL;
+               msg.entry = ne;
+               msg.prefix = pe;
+
+               eigrp_fsm_event(&msg);
+       }
 
        return 1;
 }
@@ -416,7 +431,7 @@ u_char eigrp_default_iftype(struct interface *ifp)
 
 void eigrp_if_free(struct eigrp_interface *ei, int source)
 {
-       struct prefix_ipv4 dest_addr;
+       struct prefix dest_addr;
        struct eigrp_prefix_entry *pe;
        struct eigrp *eigrp = eigrp_lookup();
 
@@ -425,10 +440,8 @@ void eigrp_if_free(struct eigrp_interface *ei, int source)
                eigrp_hello_send(ei, EIGRP_HELLO_GRACEFUL_SHUTDOWN, NULL);
        }
 
-       dest_addr.family = AF_INET;
-       dest_addr.prefix = ei->connected->address->u.prefix4;
-       dest_addr.prefixlen = ei->connected->address->prefixlen;
-       apply_mask_ipv4(&dest_addr);
+       dest_addr = *ei->connected->address;
+       apply_mask(&dest_addr);
        pe = eigrp_topology_table_lookup_ipv4(eigrp->topology_table,
                                              &dest_addr);
        if (pe)
@@ -532,11 +545,11 @@ struct eigrp_interface *eigrp_if_lookup_recv_if(struct eigrp *eigrp,
                                                struct interface *ifp)
 {
        struct route_node *rn;
-       struct prefix_ipv4 addr;
+       struct prefix addr;
        struct eigrp_interface *ei, *match;
 
        addr.family = AF_INET;
-       addr.prefix = src;
+       addr.u.prefix4 = src;
        addr.prefixlen = IPV4_MAX_BITLEN;
 
        match = NULL;
@@ -551,7 +564,7 @@ struct eigrp_interface *eigrp_if_lookup_recv_if(struct eigrp *eigrp,
                        continue;
 
                if (prefix_match(CONNECTED_PREFIX(ei->connected),
-                                (struct prefix *)&addr)) {
+                                &addr)) {
                        if ((match == NULL) || (match->address->prefixlen
                                                < ei->address->prefixlen))
                                match = ei;
index 4c99821d3c4b98ab8a5aca3e2c7820218621c785..705e04b34dda793d001c199fe0ed62da06664710 100644 (file)
@@ -159,6 +159,8 @@ int main(int argc, char **argv, char **envp)
                }
        }
 
+       eigrp_sw_version_initialize();
+
        /* EIGRP master init. */
        eigrp_master_init();
        eigrp_om->master = frr_init();
index d5fc6a299678440e57005e94cfeddf8e4daf18e3..5d78dc375c68fb6a13346e80f153e8f509c0100e 100644 (file)
@@ -357,3 +357,11 @@ void eigrp_nbr_hard_restart(struct eigrp_neighbor *nbr, struct vty *vty)
        /* delete neighbor */
        eigrp_nbr_delete(nbr);
 }
+
+int eigrp_nbr_split_horizon_check(struct eigrp_neighbor_entry *ne, struct eigrp_interface *ei)
+{
+       if (ne->distance == EIGRP_MAX_METRIC)
+               return 0;
+
+       return (ne->ei == ei);
+}
index 006aa9ab75ee54480981c06c49a14bd5c670fbf5..6467fb24a90cbdf77a6dad53061e6ca9b101eadd 100644 (file)
@@ -53,4 +53,6 @@ extern struct eigrp_neighbor *eigrp_nbr_lookup_by_addr_process(struct eigrp *,
                                                               struct in_addr);
 extern void eigrp_nbr_hard_restart(struct eigrp_neighbor *nbr, struct vty *vty);
 
+extern int eigrp_nbr_split_horizon_check(struct eigrp_neighbor_entry *ne,
+                                        struct eigrp_interface *ei);
 #endif /* _ZEBRA_EIGRP_NEIGHBOR_H */
index ec8806750b986e8439524df29d7d565f037fd8c4..0cf5bd9bad241cbb9ecf93400bad648ef79450d4 100644 (file)
@@ -229,7 +229,7 @@ int eigrp_if_drop_allspfrouters(struct eigrp *top, struct prefix *p,
        return ret;
 }
 
-int eigrp_network_set(struct eigrp *eigrp, struct prefix_ipv4 *p)
+int eigrp_network_set(struct eigrp *eigrp, struct prefix *p)
 {
        struct route_node *rn;
        struct interface *ifp;
@@ -242,7 +242,7 @@ int eigrp_network_set(struct eigrp *eigrp, struct prefix_ipv4 *p)
                return 0;
        }
 
-       struct prefix_ipv4 *pref = prefix_ipv4_new();
+       struct prefix *pref = prefix_new();
        PREFIX_COPY_IPV4(pref, p);
        rn->info = (void *)pref;
 
@@ -253,7 +253,7 @@ int eigrp_network_set(struct eigrp *eigrp, struct prefix_ipv4 *p)
        /* Get target interface. */
        for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) {
                zlog_debug("Setting up %s", ifp->name);
-               eigrp_network_run_interface(eigrp, (struct prefix *)p, ifp);
+               eigrp_network_run_interface(eigrp, p, ifp);
        }
        return 1;
 }
@@ -334,21 +334,21 @@ void eigrp_if_update(struct interface *ifp)
        }
 }
 
-int eigrp_network_unset(struct eigrp *eigrp, struct prefix_ipv4 *p)
+int eigrp_network_unset(struct eigrp *eigrp, struct prefix *p)
 {
        struct route_node *rn;
        struct listnode *node, *nnode;
        struct eigrp_interface *ei;
        struct prefix *pref;
 
-       rn = route_node_lookup(eigrp->networks, (struct prefix *)p);
+       rn = route_node_lookup(eigrp->networks, p);
        if (rn == NULL)
                return 0;
 
        pref = rn->info;
        route_unlock_node(rn);
 
-       if (!IPV4_ADDR_SAME(&pref->u.prefix4, &p->prefix))
+       if (!IPV4_ADDR_SAME(&pref->u.prefix4, &p->u.prefix4))
                return 0;
 
        prefix_ipv4_free(rn->info);
index e38f7ded40dffb423f6a092c85873aa31af127fa..6ddd57eee5596df5e3aca66b9daab53cdfaabde3 100644 (file)
@@ -32,8 +32,8 @@
 
 extern int eigrp_sock_init(void);
 extern int eigrp_if_ipmulticast(struct eigrp *, struct prefix *, unsigned int);
-extern int eigrp_network_set(struct eigrp *, struct prefix_ipv4 *);
-extern int eigrp_network_unset(struct eigrp *eigrp, struct prefix_ipv4 *p);
+extern int eigrp_network_set(struct eigrp *eigrp, struct prefix *p);
+extern int eigrp_network_unset(struct eigrp *eigrp, struct prefix *p);
 
 extern int eigrp_hello_timer(struct thread *);
 extern void eigrp_if_update(struct interface *);
index dfc7463025d77a77b3a5b9a7f482b4a0f06a2bf6..68e7cdcbbe7086dcbfb43eaa93bc164ae3ade225 100644 (file)
@@ -299,18 +299,6 @@ int eigrp_check_sha256_digest(struct stream *s,
        return 1;
 }
 
-/*
- * eigrp_packet_dump
- *
- * This routing dumps the contents of the IP packet either received or
- * built by EIGRP.
- */
-static void eigrp_packet_dump(struct stream *s)
-{
-       // not yet...
-       return;
-}
-
 int eigrp_write(struct thread *thread)
 {
        struct eigrp *eigrp = THREAD_ARG(thread);
@@ -322,6 +310,7 @@ int eigrp_write(struct thread *thread)
        struct msghdr msg;
        struct iovec iov[2];
        u_int16_t opcode = 0;
+       u_int32_t seqno, ack;
 
        int ret;
        int flags = 0;
@@ -347,7 +336,7 @@ int eigrp_write(struct thread *thread)
 #endif /* WANT_EIGRP_WRITE_FRAGMENT */
 
        /* Get one packet from queue. */
-       ep = eigrp_fifo_head(ei->obuf);
+       ep = eigrp_fifo_next(ei->obuf);
        assert(ep);
        assert(ep->length >= EIGRP_HEADER_LEN);
 
@@ -357,6 +346,25 @@ int eigrp_write(struct thread *thread)
        memset(&iph, 0, sizeof(struct ip));
        memset(&sa_dst, 0, sizeof(sa_dst));
 
+       /*
+        * We build and schedule packets to go out
+        * in the future.  In the mean time we may
+        * process some update packets from the
+        * neighbor, thus making it necessary
+        * to update the ack we are using for
+        * this outgoing packet.
+        */
+       eigrph = (struct eigrp_header *)STREAM_DATA(ep->s);
+       opcode = eigrph->opcode;
+       seqno = ntohl(eigrph->sequence);
+       ack = ntohl(eigrph->ack);
+       if (ep->nbr && (ack != ep->nbr->recv_sequence_number)) {
+               eigrph->ack = htonl(ep->nbr->recv_sequence_number);
+               ack = ep->nbr->recv_sequence_number;
+               eigrph->checksum = 0;
+               eigrp_packet_checksum(ei, ep->s, ep->length);
+       }
+
        sa_dst.sin_family = AF_INET;
 #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
        sa_dst.sin_len = sizeof(sa_dst);
@@ -412,8 +420,9 @@ int eigrp_write(struct thread *thread)
        if (IS_DEBUG_EIGRP_TRANSMIT(0, SEND)) {
                eigrph = (struct eigrp_header *)STREAM_DATA(ep->s);
                opcode = eigrph->opcode;
-               zlog_debug("Sending [%s] to [%s] via [%s] ret [%d].",
+               zlog_debug("Sending [%s][%d/%d] to [%s] via [%s] ret [%d].",
                           lookup_msg(eigrp_packet_type_str, opcode, NULL),
+                          seqno, ack,
                           inet_ntoa(ep->dst), IF_NAME(ei), ret);
        }
 
@@ -425,22 +434,10 @@ int eigrp_write(struct thread *thread)
                        iph.ip_len, ei->ifp->name, ei->ifp->mtu,
                        safe_strerror(errno));
 
-       /* Show debug sending packet. */
-       if (IS_DEBUG_EIGRP_TRANSMIT(0, SEND)
-           && (IS_DEBUG_EIGRP_TRANSMIT(0, PACKET_DETAIL))) {
-               zlog_debug(
-                       "-----------------------------------------------------");
-               eigrp_ip_header_dump(&iph);
-               stream_set_getp(ep->s, 0);
-               eigrp_packet_dump(ep->s);
-               zlog_debug(
-                       "-----------------------------------------------------");
-       }
-
        /* Now delete packet from queue. */
        eigrp_packet_delete(ei);
 
-       if (eigrp_fifo_head(ei->obuf) == NULL) {
+       if (eigrp_fifo_next(ei->obuf) == NULL) {
                ei->on_write_q = 0;
                list_delete_node(eigrp->oi_write_q, node);
        }
@@ -530,7 +527,7 @@ int eigrp_read(struct thread *thread)
 
        /* Self-originated packet should be discarded silently. */
        if (eigrp_if_lookup_by_local_addr(eigrp, NULL, iph->ip_src)
-           || (IPV4_ADDR_SAME(&iph->ip_src.s_addr, &ei->address->u.prefix4))) {
+           || (IPV4_ADDR_SAME(&iph->ip_src, &ei->address->u.prefix4))) {
                if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV))
                        zlog_debug(
                                "eigrp_read[%s]: Dropping self-originated packet",
@@ -615,52 +612,51 @@ int eigrp_read(struct thread *thread)
           start of the eigrp TLVs */
        opcode = eigrph->opcode;
 
-       if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV))
-               zlog_debug(
-                       "Received [%s] length [%u] via [%s] src [%s] dst [%s]",
-                       lookup_msg(eigrp_packet_type_str, opcode, NULL), length,
-                       IF_NAME(ei), inet_ntoa(iph->ip_src),
-                       inet_ntoa(iph->ip_dst));
+       if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV)) {
+               char src[100], dst[100];
+
+               strcpy(src, inet_ntoa(iph->ip_src));
+               strcpy(dst, inet_ntoa(iph->ip_dst));
+               zlog_debug("Received [%s][%d/%d] length [%u] via [%s] src [%s] dst [%s]",
+                          lookup_msg(eigrp_packet_type_str, opcode, NULL),
+                          ntohl(eigrph->sequence), ntohl(eigrph->ack), length,
+                          IF_NAME(ei), src, dst);
+       }
 
        /* Read rest of the packet and call each sort of packet routine. */
        stream_forward_getp(ibuf, EIGRP_HEADER_LEN);
 
        /* New testing block of code for handling Acks */
        if (ntohl(eigrph->ack) != 0) {
+               struct eigrp_packet *ep = NULL;
+
                nbr = eigrp_nbr_get(ei, eigrph, iph);
 
-               /* neighbor must be valid, eigrp_nbr_get creates if none existed
-                */
+               // neighbor must be valid, eigrp_nbr_get creates if none existed
                assert(nbr);
 
-               struct eigrp_packet *ep;
-
-               ep = eigrp_fifo_tail(nbr->retrans_queue);
-               if (ep) {
-                       if (ntohl(eigrph->ack) == ep->sequence_number) {
-                               if ((nbr->state == EIGRP_NEIGHBOR_PENDING)
-                                   && (ntohl(eigrph->ack)
-                                       == nbr->init_sequence_number)) {
-                                       eigrp_nbr_state_set(nbr,
-                                                           EIGRP_NEIGHBOR_UP);
-                                       zlog_info(
-                                               "Neighbor adjacency became full");
-                                       nbr->init_sequence_number = 0;
-                                       nbr->recv_sequence_number =
-                                               ntohl(eigrph->sequence);
-                                       eigrp_update_send_EOT(nbr);
-                               }
-                               ep = eigrp_fifo_pop_tail(nbr->retrans_queue);
-                               eigrp_packet_free(ep);
-                               if (nbr->retrans_queue->count > 0) {
-                                       eigrp_send_packet_reliably(nbr);
-                               }
+               ep = eigrp_fifo_next(nbr->retrans_queue);
+               if ((ep) && (ntohl(eigrph->ack) == ep->sequence_number)) {
+                       ep = eigrp_fifo_pop(nbr->retrans_queue);
+                       eigrp_packet_free(ep);
+
+                       if ((nbr->state == EIGRP_NEIGHBOR_PENDING)
+                           && (ntohl(eigrph->ack) == nbr->init_sequence_number)) {
+                               eigrp_nbr_state_set(nbr, EIGRP_NEIGHBOR_UP);
+                               zlog_info("Neighbor(%s) adjacency became full",
+                                         inet_ntoa(nbr->src));
+                               nbr->init_sequence_number = 0;
+                               nbr->recv_sequence_number =
+                                       ntohl(eigrph->sequence);
+                               eigrp_update_send_EOT(nbr);
                        }
+                       else
+                               eigrp_send_packet_reliably(nbr);
                }
-               ep = eigrp_fifo_tail(nbr->multicast_queue);
+               ep = eigrp_fifo_next(nbr->multicast_queue);
                if (ep) {
                        if (ntohl(eigrph->ack) == ep->sequence_number) {
-                               ep = eigrp_fifo_pop_tail(nbr->multicast_queue);
+                               ep = eigrp_fifo_pop(nbr->multicast_queue);
                                eigrp_packet_free(ep);
                                if (nbr->multicast_queue->count > 0) {
                                        eigrp_send_packet_reliably(nbr);
@@ -826,13 +822,14 @@ void eigrp_fifo_reset(struct eigrp_fifo *fifo)
        fifo->count = 0;
 }
 
-struct eigrp_packet *eigrp_packet_new(size_t size)
+struct eigrp_packet *eigrp_packet_new(size_t size, struct eigrp_neighbor *nbr)
 {
        struct eigrp_packet *new;
 
        new = XCALLOC(MTYPE_EIGRP_PACKET, sizeof(struct eigrp_packet));
        new->s = stream_new(size);
        new->retrans_counter = 0;
+       new->nbr = nbr;
 
        return new;
 }
@@ -841,13 +838,13 @@ void eigrp_send_packet_reliably(struct eigrp_neighbor *nbr)
 {
        struct eigrp_packet *ep;
 
-       ep = eigrp_fifo_tail(nbr->retrans_queue);
+       ep = eigrp_fifo_next(nbr->retrans_queue);
 
        if (ep) {
                struct eigrp_packet *duplicate;
                duplicate = eigrp_packet_duplicate(ep, nbr);
                /* Add packet to the top of the interface output queue*/
-               eigrp_fifo_push_head(nbr->ei->obuf, duplicate);
+               eigrp_fifo_push(nbr->ei->obuf, duplicate);
 
                /*Start retransmission timer*/
                thread_add_timer(master, eigrp_unack_packet_retrans, nbr,
@@ -880,7 +877,7 @@ void eigrp_packet_checksum(struct eigrp_interface *ei, struct stream *s,
 }
 
 /* Make EIGRP header. */
-void eigrp_packet_header_init(int type, struct eigrp_interface *ei,
+void eigrp_packet_header_init(int type, struct eigrp *eigrp,
                              struct stream *s, u_int32_t flags,
                              u_int32_t sequence, u_int32_t ack)
 {
@@ -893,15 +890,15 @@ void eigrp_packet_header_init(int type, struct eigrp_interface *ei,
        eigrph->opcode = (u_char)type;
        eigrph->checksum = 0;
 
-       eigrph->vrid = htons(ei->eigrp->vrid);
-       eigrph->ASNumber = htons(ei->eigrp->AS);
+       eigrph->vrid = htons(eigrp->vrid);
+       eigrph->ASNumber = htons(eigrp->AS);
        eigrph->ack = htonl(ack);
        eigrph->sequence = htonl(sequence);
        //  if(flags == EIGRP_INIT_FLAG)
        //    eigrph->sequence = htonl(3);
        eigrph->flags = htonl(flags);
 
-       if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV))
+       if (IS_DEBUG_EIGRP_TRANSMIT(0, PACKET_DETAIL))
                zlog_debug("Packet Header Init Seq [%u] Ack [%u]",
                           htonl(eigrph->sequence), htonl(eigrph->ack));
 
@@ -909,7 +906,7 @@ void eigrp_packet_header_init(int type, struct eigrp_interface *ei,
 }
 
 /* Add new packet to head of fifo. */
-void eigrp_fifo_push_head(struct eigrp_fifo *fifo, struct eigrp_packet *ep)
+void eigrp_fifo_push(struct eigrp_fifo *fifo, struct eigrp_packet *ep)
 {
        ep->next = fifo->head;
        ep->previous = NULL;
@@ -925,14 +922,8 @@ void eigrp_fifo_push_head(struct eigrp_fifo *fifo, struct eigrp_packet *ep)
        fifo->count++;
 }
 
-/* Return first fifo entry. */
-struct eigrp_packet *eigrp_fifo_head(struct eigrp_fifo *fifo)
-{
-       return fifo->head;
-}
-
 /* Return last fifo entry. */
-struct eigrp_packet *eigrp_fifo_tail(struct eigrp_fifo *fifo)
+struct eigrp_packet *eigrp_fifo_next(struct eigrp_fifo *fifo)
 {
        return fifo->tail;
 }
@@ -947,27 +938,6 @@ void eigrp_packet_delete(struct eigrp_interface *ei)
                eigrp_packet_free(ep);
 }
 
-/* Delete first packet from fifo. */
-struct eigrp_packet *eigrp_fifo_pop(struct eigrp_fifo *fifo)
-{
-       struct eigrp_packet *ep;
-
-       ep = fifo->head;
-
-       if (ep) {
-               fifo->head = ep->next;
-
-               if (fifo->head == NULL)
-                       fifo->tail = NULL;
-               else
-                       fifo->head->previous = NULL;
-
-               fifo->count--;
-       }
-
-       return ep;
-}
-
 void eigrp_packet_free(struct eigrp_packet *ep)
 {
        if (ep->s)
@@ -1028,14 +998,14 @@ int eigrp_unack_packet_retrans(struct thread *thread)
        nbr = (struct eigrp_neighbor *)THREAD_ARG(thread);
 
        struct eigrp_packet *ep;
-       ep = eigrp_fifo_tail(nbr->retrans_queue);
+       ep = eigrp_fifo_next(nbr->retrans_queue);
 
        if (ep) {
                struct eigrp_packet *duplicate;
                duplicate = eigrp_packet_duplicate(ep, nbr);
 
                /* Add packet to the top of the interface output queue*/
-               eigrp_fifo_push_head(nbr->ei->obuf, duplicate);
+               eigrp_fifo_push(nbr->ei->obuf, duplicate);
 
                ep->retrans_counter++;
                if (ep->retrans_counter == EIGRP_PACKET_RETRANS_MAX)
@@ -1065,13 +1035,13 @@ int eigrp_unack_multicast_packet_retrans(struct thread *thread)
        nbr = (struct eigrp_neighbor *)THREAD_ARG(thread);
 
        struct eigrp_packet *ep;
-       ep = eigrp_fifo_tail(nbr->multicast_queue);
+       ep = eigrp_fifo_next(nbr->multicast_queue);
 
        if (ep) {
                struct eigrp_packet *duplicate;
                duplicate = eigrp_packet_duplicate(ep, nbr);
                /* Add packet to the top of the interface output queue*/
-               eigrp_fifo_push_head(nbr->ei->obuf, duplicate);
+               eigrp_fifo_push(nbr->ei->obuf, duplicate);
 
                ep->retrans_counter++;
                if (ep->retrans_counter == EIGRP_PACKET_RETRANS_MAX)
@@ -1096,9 +1066,9 @@ int eigrp_unack_multicast_packet_retrans(struct thread *thread)
 }
 
 /* Get packet from tail of fifo. */
-struct eigrp_packet *eigrp_fifo_pop_tail(struct eigrp_fifo *fifo)
+struct eigrp_packet *eigrp_fifo_pop(struct eigrp_fifo *fifo)
 {
-       struct eigrp_packet *ep;
+       struct eigrp_packet *ep = NULL;
 
        ep = fifo->tail;
 
@@ -1121,7 +1091,7 @@ struct eigrp_packet *eigrp_packet_duplicate(struct eigrp_packet *old,
 {
        struct eigrp_packet *new;
 
-       new = eigrp_packet_new(nbr->ei->ifp->mtu);
+       new = eigrp_packet_new(nbr->ei->ifp->mtu, nbr);
        new->length = old->length;
        new->retrans_counter = old->retrans_counter;
        new->dst = old->dst;
@@ -1131,6 +1101,16 @@ struct eigrp_packet *eigrp_packet_duplicate(struct eigrp_packet *old,
        return new;
 }
 
+static struct TLV_IPv4_Internal_type *eigrp_IPv4_InternalTLV_new()
+{
+       struct TLV_IPv4_Internal_type *new;
+
+       new = XCALLOC(MTYPE_EIGRP_IPV4_INT_TLV,
+                     sizeof(struct TLV_IPv4_Internal_type));
+
+       return new;
+}
+
 struct TLV_IPv4_Internal_type *eigrp_read_ipv4_tlv(struct stream *s)
 {
        struct TLV_IPv4_Internal_type *tlv;
@@ -1187,21 +1167,21 @@ u_int16_t eigrp_add_internalTLV_to_stream(struct stream *s,
        u_int16_t length;
 
        stream_putw(s, EIGRP_TLV_IPv4_INT);
-       if (pe->destination_ipv4->prefixlen <= 8) {
+       if (pe->destination->prefixlen <= 8) {
                stream_putw(s, 0x001A);
                length = 0x001A;
        }
-       if ((pe->destination_ipv4->prefixlen > 8)
-           && (pe->destination_ipv4->prefixlen <= 16)) {
+       if ((pe->destination->prefixlen > 8)
+           && (pe->destination->prefixlen <= 16)) {
                stream_putw(s, 0x001B);
                length = 0x001B;
        }
-       if ((pe->destination_ipv4->prefixlen > 16)
-           && (pe->destination_ipv4->prefixlen <= 24)) {
+       if ((pe->destination->prefixlen > 16)
+           && (pe->destination->prefixlen <= 24)) {
                stream_putw(s, 0x001C);
                length = 0x001C;
        }
-       if (pe->destination_ipv4->prefixlen > 24) {
+       if (pe->destination->prefixlen > 24) {
                stream_putw(s, 0x001D);
                length = 0x001D;
        }
@@ -1220,34 +1200,18 @@ u_int16_t eigrp_add_internalTLV_to_stream(struct stream *s,
        stream_putc(s, pe->reported_metric.tag);
        stream_putc(s, pe->reported_metric.flags);
 
-       stream_putc(s, pe->destination_ipv4->prefixlen);
+       stream_putc(s, pe->destination->prefixlen);
 
-       if (pe->destination_ipv4->prefixlen <= 8) {
-               stream_putc(s, pe->destination_ipv4->prefix.s_addr & 0xFF);
-       }
-       if ((pe->destination_ipv4->prefixlen > 8)
-           && (pe->destination_ipv4->prefixlen <= 16)) {
-               stream_putc(s, pe->destination_ipv4->prefix.s_addr & 0xFF);
+       stream_putc(s, pe->destination->u.prefix4.s_addr & 0xFF);
+       if (pe->destination->prefixlen > 8)
                stream_putc(s,
-                           (pe->destination_ipv4->prefix.s_addr >> 8) & 0xFF);
-       }
-       if ((pe->destination_ipv4->prefixlen > 16)
-           && (pe->destination_ipv4->prefixlen <= 24)) {
-               stream_putc(s, pe->destination_ipv4->prefix.s_addr & 0xFF);
+                           (pe->destination->u.prefix4.s_addr >> 8) & 0xFF);
+       if (pe->destination->prefixlen > 16)
                stream_putc(s,
-                           (pe->destination_ipv4->prefix.s_addr >> 8) & 0xFF);
-               stream_putc(s,
-                           (pe->destination_ipv4->prefix.s_addr >> 16) & 0xFF);
-       }
-       if (pe->destination_ipv4->prefixlen > 24) {
-               stream_putc(s, pe->destination_ipv4->prefix.s_addr & 0xFF);
+                           (pe->destination->u.prefix4.s_addr >> 16) & 0xFF);
+       if (pe->destination->prefixlen > 24)
                stream_putc(s,
-                           (pe->destination_ipv4->prefix.s_addr >> 8) & 0xFF);
-               stream_putc(s,
-                           (pe->destination_ipv4->prefix.s_addr >> 16) & 0xFF);
-               stream_putc(s,
-                           (pe->destination_ipv4->prefix.s_addr >> 24) & 0xFF);
-       }
+                           (pe->destination->u.prefix4.s_addr >> 24) & 0xFF);
 
        return length;
 }
@@ -1362,16 +1326,6 @@ void eigrp_authTLV_SHA256_free(struct TLV_SHA256_Authentication_Type *authTLV)
        XFREE(MTYPE_EIGRP_AUTH_SHA256_TLV, authTLV);
 }
 
-struct TLV_IPv4_Internal_type *eigrp_IPv4_InternalTLV_new()
-{
-       struct TLV_IPv4_Internal_type *new;
-
-       new = XCALLOC(MTYPE_EIGRP_IPV4_INT_TLV,
-                     sizeof(struct TLV_IPv4_Internal_type));
-
-       return new;
-}
-
 void eigrp_IPv4_InternalTLV_free(
        struct TLV_IPv4_Internal_type *IPv4_InternalTLV)
 {
index 2f607e5cabbcadb182fdaaf879f2205ddb240636..e52fd268fa54decaad09ad5b37204b850895b21f 100644 (file)
 extern int eigrp_read(struct thread *);
 extern int eigrp_write(struct thread *);
 
-extern struct eigrp_packet *eigrp_packet_new(size_t);
+extern struct eigrp_packet *eigrp_packet_new(size_t, struct eigrp_neighbor *);
 extern struct eigrp_packet *eigrp_packet_duplicate(struct eigrp_packet *,
                                                   struct eigrp_neighbor *);
 extern void eigrp_packet_free(struct eigrp_packet *);
 extern void eigrp_packet_delete(struct eigrp_interface *);
-extern void eigrp_packet_header_init(int, struct eigrp_interface *,
+extern void eigrp_packet_header_init(int, struct eigrp *,
                                     struct stream *, u_int32_t, u_int32_t,
                                     u_int32_t);
 extern void eigrp_packet_checksum(struct eigrp_interface *, struct stream *,
                                  u_int16_t);
 
 extern struct eigrp_fifo *eigrp_fifo_new(void);
-extern struct eigrp_packet *eigrp_fifo_head(struct eigrp_fifo *);
-extern struct eigrp_packet *eigrp_fifo_tail(struct eigrp_fifo *);
+extern struct eigrp_packet *eigrp_fifo_next(struct eigrp_fifo *);
 extern struct eigrp_packet *eigrp_fifo_pop(struct eigrp_fifo *);
-extern struct eigrp_packet *eigrp_fifo_pop_tail(struct eigrp_fifo *);
-extern void eigrp_fifo_push_head(struct eigrp_fifo *, struct eigrp_packet *);
+extern void eigrp_fifo_push(struct eigrp_fifo *, struct eigrp_packet *);
 extern void eigrp_fifo_free(struct eigrp_fifo *);
 extern void eigrp_fifo_reset(struct eigrp_fifo *);
 
@@ -73,6 +71,7 @@ extern int eigrp_unack_multicast_packet_retrans(struct thread *);
  * untill there is reason to have their own header, these externs are found in
  * eigrp_hello.c
  */
+extern void eigrp_sw_version_initialize(void);
 extern void eigrp_hello_send(struct eigrp_interface *, u_char,
                             struct in_addr *);
 extern void eigrp_hello_send_ack(struct eigrp_neighbor *);
@@ -153,7 +152,6 @@ extern int eigrp_check_sha256_digest(struct stream *,
                                     struct eigrp_neighbor *, u_char);
 
 
-extern struct TLV_IPv4_Internal_type *eigrp_IPv4_InternalTLV_new(void);
 extern void eigrp_IPv4_InternalTLV_free(struct TLV_IPv4_Internal_type *);
 
 extern struct TLV_Sequence_Type *eigrp_SequenceTLV_new(void);
index 653eae258f0dad296d830d7870162bf3b305b36d..0167c8b3c2756cff04fc2173297892b94fe878ed 100644 (file)
@@ -91,8 +91,10 @@ void eigrp_query_receive(struct eigrp *eigrp, struct ip *iph,
 {
        struct eigrp_neighbor *nbr;
        struct TLV_IPv4_Internal_type *tlv;
+       struct prefix dest_addr;
 
        u_int16_t type;
+       u_int16_t length;
 
        /* increment statistics. */
        ei->query_in++;
@@ -107,15 +109,14 @@ void eigrp_query_receive(struct eigrp *eigrp, struct ip *iph,
 
        while (s->endp > s->getp) {
                type = stream_getw(s);
-               if (type == EIGRP_TLV_IPv4_INT) {
-                       struct prefix_ipv4 dest_addr;
-
+               switch (type) {
+               case EIGRP_TLV_IPv4_INT:
                        stream_set_getp(s, s->getp - sizeof(u_int16_t));
 
                        tlv = eigrp_read_ipv4_tlv(s);
 
                        dest_addr.family = AF_INET;
-                       dest_addr.prefix = tlv->destination;
+                       dest_addr.u.prefix4 = tlv->destination;
                        dest_addr.prefixlen = tlv->prefix_length;
                        struct eigrp_prefix_entry *dest =
                                eigrp_topology_table_lookup_ipv4(
@@ -124,24 +125,32 @@ void eigrp_query_receive(struct eigrp *eigrp, struct ip *iph,
                        /* If the destination exists (it should, but one never
                         * know)*/
                        if (dest != NULL) {
-                               struct eigrp_fsm_action_message *msg;
-                               msg = XCALLOC(MTYPE_EIGRP_FSM_MSG,
-                                             sizeof(struct
-                                                    eigrp_fsm_action_message));
+                               struct eigrp_fsm_action_message msg;
                                struct eigrp_neighbor_entry *entry =
                                        eigrp_prefix_entry_lookup(dest->entries,
                                                                  nbr);
-                               msg->packet_type = EIGRP_OPC_QUERY;
-                               msg->eigrp = eigrp;
-                               msg->data_type = EIGRP_TLV_IPv4_INT;
-                               msg->adv_router = nbr;
-                               msg->data.ipv4_int_type = tlv;
-                               msg->entry = entry;
-                               msg->prefix = dest;
-                               int event = eigrp_get_fsm_event(msg);
-                               eigrp_fsm_event(msg, event);
+                               msg.packet_type = EIGRP_OPC_QUERY;
+                               msg.eigrp = eigrp;
+                               msg.data_type = EIGRP_INT;
+                               msg.adv_router = nbr;
+                               msg.metrics = tlv->metric;
+                               msg.entry = entry;
+                               msg.prefix = dest;
+                               eigrp_fsm_event(&msg);
                        }
                        eigrp_IPv4_InternalTLV_free(tlv);
+                       break;
+
+               case EIGRP_TLV_IPv4_EXT:
+                       /* DVS: processing of external routes needs packet and fsm work.
+                        *      for now, lets just not creash the box
+                        */
+               default:
+                       length = stream_getw(s);
+                       // -2 for type, -2 for len
+                       for (length-=4; length ; length--) {
+                               (void)stream_getc(s);
+                       }
                }
        }
        eigrp_hello_send_ack(nbr);
@@ -159,10 +168,10 @@ void eigrp_send_query(struct eigrp_interface *ei)
        char has_tlv;
        bool ep_saved = false;
 
-       ep = eigrp_packet_new(ei->ifp->mtu);
+       ep = eigrp_packet_new(ei->ifp->mtu, NULL);
 
        /* Prepare EIGRP INIT UPDATE header */
-       eigrp_packet_header_init(EIGRP_OPC_QUERY, ei, ep->s, 0,
+       eigrp_packet_header_init(EIGRP_OPC_QUERY, ei->eigrp, ep->s, 0,
                                 ei->eigrp->sequence_number, 0);
 
        // encode Authentication TLV, if needed
@@ -207,7 +216,7 @@ void eigrp_send_query(struct eigrp_interface *ei)
        for (ALL_LIST_ELEMENTS(ei->nbrs, node2, nnode2, nbr)) {
                if (nbr->state == EIGRP_NEIGHBOR_UP) {
                        /*Put packet to retransmission queue*/
-                       eigrp_fifo_push_head(nbr->retrans_queue, ep);
+                       eigrp_fifo_push(nbr->retrans_queue, ep);
                        ep_saved = true;
 
                        if (nbr->retrans_queue->count == 1) {
index 4eb08c60d03bd98e448e69ad3fd12725ad2c4c14..2b5b0aa44b14c161e6287fc5d6306b785cbeb484 100644 (file)
@@ -84,40 +84,36 @@ void eigrp_send_reply(struct eigrp_neighbor *nbr, struct eigrp_prefix_entry *pe)
        plist = e->prefix[EIGRP_FILTER_OUT];
        alist_i = nbr->ei->list[EIGRP_FILTER_OUT];
        plist_i = nbr->ei->prefix[EIGRP_FILTER_OUT];
-       zlog_info("REPLY Send: Filtering");
 
-       zlog_info("REPLY SEND Prefix: %s", inet_ntoa(nbr->src));
        /* Check if any list fits */
        if ((alist
-            && access_list_apply(alist, (struct prefix *)pe2->destination_ipv4)
+            && access_list_apply(alist, pe2->destination)
                        == FILTER_DENY)
            || (plist
                && prefix_list_apply(plist,
-                                    (struct prefix *)pe2->destination_ipv4)
+                                    pe2->destination)
                           == PREFIX_DENY)
            || (alist_i
                && access_list_apply(alist_i,
-                                    (struct prefix *)pe2->destination_ipv4)
+                                    pe2->destination)
                           == FILTER_DENY)
            || (plist_i
                && prefix_list_apply(plist_i,
-                                    (struct prefix *)pe2->destination_ipv4)
+                                    pe2->destination)
                           == PREFIX_DENY)) {
                zlog_info("REPLY SEND: Setting Metric to max");
                pe2->reported_metric.delay = EIGRP_MAX_METRIC;
 
-       } else {
-               zlog_info("REPLY SEND: Not setting metric");
        }
 
        /*
         * End of filtering
         */
 
-       ep = eigrp_packet_new(nbr->ei->ifp->mtu);
+       ep = eigrp_packet_new(nbr->ei->ifp->mtu, nbr);
 
        /* Prepare EIGRP INIT UPDATE header */
-       eigrp_packet_header_init(EIGRP_OPC_REPLY, nbr->ei, ep->s, 0,
+       eigrp_packet_header_init(EIGRP_OPC_REPLY, e, ep->s, 0,
                                 nbr->ei->eigrp->sequence_number, 0);
 
        // encode Authentication TLV, if needed
@@ -144,7 +140,7 @@ void eigrp_send_reply(struct eigrp_neighbor *nbr, struct eigrp_prefix_entry *pe)
        ep->sequence_number = nbr->ei->eigrp->sequence_number;
 
        /*Put packet to retransmission queue*/
-       eigrp_fifo_push_head(nbr->retrans_queue, ep);
+       eigrp_fifo_push(nbr->retrans_queue, ep);
 
        if (nbr->retrans_queue->count == 1) {
                eigrp_send_packet_reliably(nbr);
@@ -183,14 +179,14 @@ void eigrp_reply_receive(struct eigrp *eigrp, struct ip *iph,
        while (s->endp > s->getp) {
                type = stream_getw(s);
                if (type == EIGRP_TLV_IPv4_INT) {
-                       struct prefix_ipv4 dest_addr;
+                       struct prefix dest_addr;
 
                        stream_set_getp(s, s->getp - sizeof(u_int16_t));
 
                        tlv = eigrp_read_ipv4_tlv(s);
 
                        dest_addr.family = AF_INET;
-                       dest_addr.prefix = tlv->destination;
+                       dest_addr.u.prefix4 = tlv->destination;
                        dest_addr.prefixlen = tlv->prefix_length;
                        struct eigrp_prefix_entry *dest =
                                eigrp_topology_table_lookup_ipv4(
@@ -200,9 +196,7 @@ void eigrp_reply_receive(struct eigrp *eigrp, struct ip *iph,
                         */
                        assert(dest);
 
-                       struct eigrp_fsm_action_message *msg;
-                       msg = XCALLOC(MTYPE_EIGRP_FSM_MSG,
-                                     sizeof(struct eigrp_fsm_action_message));
+                       struct eigrp_fsm_action_message msg;
                        struct eigrp_neighbor_entry *entry =
                                eigrp_prefix_entry_lookup(dest->entries, nbr);
 
@@ -241,15 +235,14 @@ void eigrp_reply_receive(struct eigrp *eigrp, struct ip *iph,
                         * End of filtering
                         */
 
-                       msg->packet_type = EIGRP_OPC_REPLY;
-                       msg->eigrp = eigrp;
-                       msg->data_type = EIGRP_TLV_IPv4_INT;
-                       msg->adv_router = nbr;
-                       msg->data.ipv4_int_type = tlv;
-                       msg->entry = entry;
-                       msg->prefix = dest;
-                       int event = eigrp_get_fsm_event(msg);
-                       eigrp_fsm_event(msg, event);
+                       msg.packet_type = EIGRP_OPC_REPLY;
+                       msg.eigrp = eigrp;
+                       msg.data_type = EIGRP_INT;
+                       msg.adv_router = nbr;
+                       msg.metrics = tlv->metric;
+                       msg.entry = entry;
+                       msg.prefix = dest;
+                       eigrp_fsm_event(&msg);
 
 
                        eigrp_IPv4_InternalTLV_free(tlv);
index f16f49a3305ece827a967d3b6b44f9711ef99fef..7264e53b6b139e93efbb393ca5b2fdae47724d9f 100644 (file)
@@ -78,14 +78,14 @@ void eigrp_siaquery_receive(struct eigrp *eigrp, struct ip *iph,
        while (s->endp > s->getp) {
                type = stream_getw(s);
                if (type == EIGRP_TLV_IPv4_INT) {
-                       struct prefix_ipv4 dest_addr;
+                       struct prefix dest_addr;
 
                        stream_set_getp(s, s->getp - sizeof(u_int16_t));
 
                        tlv = eigrp_read_ipv4_tlv(s);
 
                        dest_addr.family = AFI_IP;
-                       dest_addr.prefix = tlv->destination;
+                       dest_addr.u.prefix4 = tlv->destination;
                        dest_addr.prefixlen = tlv->prefix_length;
                        struct eigrp_prefix_entry *dest =
                                eigrp_topology_table_lookup_ipv4(
@@ -94,22 +94,18 @@ void eigrp_siaquery_receive(struct eigrp *eigrp, struct ip *iph,
                        /* If the destination exists (it should, but one never
                         * know)*/
                        if (dest != NULL) {
-                               struct eigrp_fsm_action_message *msg;
-                               msg = XCALLOC(MTYPE_EIGRP_FSM_MSG,
-                                             sizeof(struct
-                                                    eigrp_fsm_action_message));
+                               struct eigrp_fsm_action_message msg;
                                struct eigrp_neighbor_entry *entry =
                                        eigrp_prefix_entry_lookup(dest->entries,
                                                                  nbr);
-                               msg->packet_type = EIGRP_OPC_SIAQUERY;
-                               msg->eigrp = eigrp;
-                               msg->data_type = EIGRP_TLV_IPv4_INT;
-                               msg->adv_router = nbr;
-                               msg->data.ipv4_int_type = tlv;
-                               msg->entry = entry;
-                               msg->prefix = dest;
-                               int event = eigrp_get_fsm_event(msg);
-                               eigrp_fsm_event(msg, event);
+                               msg.packet_type = EIGRP_OPC_SIAQUERY;
+                               msg.eigrp = eigrp;
+                               msg.data_type = EIGRP_INT;
+                               msg.adv_router = nbr;
+                               msg.metrics = tlv->metric;
+                               msg.entry = entry;
+                               msg.prefix = dest;
+                               eigrp_fsm_event(&msg);
                        }
                        eigrp_IPv4_InternalTLV_free(tlv);
                }
@@ -123,10 +119,10 @@ void eigrp_send_siaquery(struct eigrp_neighbor *nbr,
        struct eigrp_packet *ep;
        u_int16_t length = EIGRP_HEADER_LEN;
 
-       ep = eigrp_packet_new(nbr->ei->ifp->mtu);
+       ep = eigrp_packet_new(nbr->ei->ifp->mtu, nbr);
 
        /* Prepare EIGRP INIT UPDATE header */
-       eigrp_packet_header_init(EIGRP_OPC_SIAQUERY, nbr->ei, ep->s, 0,
+       eigrp_packet_header_init(EIGRP_OPC_SIAQUERY, nbr->ei->eigrp, ep->s, 0,
                                 nbr->ei->eigrp->sequence_number, 0);
 
        // encode Authentication TLV, if needed
@@ -153,7 +149,7 @@ void eigrp_send_siaquery(struct eigrp_neighbor *nbr,
 
        if (nbr->state == EIGRP_NEIGHBOR_UP) {
                /*Put packet to retransmission queue*/
-               eigrp_fifo_push_head(nbr->retrans_queue, ep);
+               eigrp_fifo_push(nbr->retrans_queue, ep);
 
                if (nbr->retrans_queue->count == 1) {
                        eigrp_send_packet_reliably(nbr);
index 9a768566d3f00b7d181150e241600f45edbddedb..8496c05675316f834af7075e8526f07a715aa976 100644 (file)
@@ -77,14 +77,14 @@ void eigrp_siareply_receive(struct eigrp *eigrp, struct ip *iph,
        while (s->endp > s->getp) {
                type = stream_getw(s);
                if (type == EIGRP_TLV_IPv4_INT) {
-                       struct prefix_ipv4 dest_addr;
+                       struct prefix dest_addr;
 
                        stream_set_getp(s, s->getp - sizeof(u_int16_t));
 
                        tlv = eigrp_read_ipv4_tlv(s);
 
                        dest_addr.family = AFI_IP;
-                       dest_addr.prefix = tlv->destination;
+                       dest_addr.u.prefix4 = tlv->destination;
                        dest_addr.prefixlen = tlv->prefix_length;
                        struct eigrp_prefix_entry *dest =
                                eigrp_topology_table_lookup_ipv4(
@@ -93,22 +93,18 @@ void eigrp_siareply_receive(struct eigrp *eigrp, struct ip *iph,
                        /* If the destination exists (it should, but one never
                         * know)*/
                        if (dest != NULL) {
-                               struct eigrp_fsm_action_message *msg;
-                               msg = XCALLOC(MTYPE_EIGRP_FSM_MSG,
-                                             sizeof(struct
-                                                    eigrp_fsm_action_message));
+                               struct eigrp_fsm_action_message msg;
                                struct eigrp_neighbor_entry *entry =
                                        eigrp_prefix_entry_lookup(dest->entries,
                                                                  nbr);
-                               msg->packet_type = EIGRP_OPC_SIAQUERY;
-                               msg->eigrp = eigrp;
-                               msg->data_type = EIGRP_TLV_IPv4_INT;
-                               msg->adv_router = nbr;
-                               msg->data.ipv4_int_type = tlv;
-                               msg->entry = entry;
-                               msg->prefix = dest;
-                               int event = eigrp_get_fsm_event(msg);
-                               eigrp_fsm_event(msg, event);
+                               msg.packet_type = EIGRP_OPC_SIAQUERY;
+                               msg.eigrp = eigrp;
+                               msg.data_type = EIGRP_INT;
+                               msg.adv_router = nbr;
+                               msg.metrics = tlv->metric;
+                               msg.entry = entry;
+                               msg.prefix = dest;
+                               eigrp_fsm_event(&msg);
                        }
                        eigrp_IPv4_InternalTLV_free(tlv);
                }
@@ -122,10 +118,10 @@ void eigrp_send_siareply(struct eigrp_neighbor *nbr,
        struct eigrp_packet *ep;
        u_int16_t length = EIGRP_HEADER_LEN;
 
-       ep = eigrp_packet_new(nbr->ei->ifp->mtu);
+       ep = eigrp_packet_new(nbr->ei->ifp->mtu, nbr);
 
        /* Prepare EIGRP INIT UPDATE header */
-       eigrp_packet_header_init(EIGRP_OPC_SIAREPLY, nbr->ei, ep->s, 0,
+       eigrp_packet_header_init(EIGRP_OPC_SIAREPLY, nbr->ei->eigrp, ep->s, 0,
                                 nbr->ei->eigrp->sequence_number, 0);
 
        // encode Authentication TLV, if needed
@@ -152,7 +148,7 @@ void eigrp_send_siareply(struct eigrp_neighbor *nbr,
 
        if (nbr->state == EIGRP_NEIGHBOR_UP) {
                /*Put packet to retransmission queue*/
-               eigrp_fifo_push_head(nbr->retrans_queue, ep);
+               eigrp_fifo_push(nbr->retrans_queue, ep);
 
                if (nbr->retrans_queue->count == 1) {
                        eigrp_send_packet_reliably(nbr);
index fd3e4b2014b352f8f591f7ad267091e6e693f1d6..b769774a032810ef7d23d23d43d9c8edff2f3ad6 100644 (file)
@@ -311,6 +311,8 @@ struct eigrp_packet {
 
        /* EIGRP packet length. */
        u_int16_t length;
+
+       struct eigrp_neighbor *nbr;
 };
 
 struct eigrp_fifo {
@@ -467,10 +469,7 @@ struct eigrp_prefix_entry {
        u_char af;       // address family
        u_char req_action; // required action
 
-       struct prefix_ipv4
-               *destination_ipv4; // pointer to struct with ipv4 address
-       struct prefix_ipv6
-               *destination_ipv6; // pointer to struct with ipv6 address
+       struct prefix *destination;
 
        // If network type is REMOTE_EXTERNAL, pointer will have reference to
        // its external TLV
@@ -497,6 +496,11 @@ struct eigrp_neighbor_entry {
 };
 
 //---------------------------------------------------------------------------------------------------------------------------------------------
+typedef enum {
+       EIGRP_CONNECTED,
+       EIGRP_INT,
+       EIGRP_EXT,
+} msg_data_t;
 
 /* EIGRP Finite State Machine */
 
@@ -506,11 +510,8 @@ struct eigrp_fsm_action_message {
        struct eigrp_neighbor *adv_router; // advertising neighbor
        struct eigrp_neighbor_entry *entry;
        struct eigrp_prefix_entry *prefix;
-       int data_type; // internal or external tlv type
-       union {
-               struct TLV_IPv4_External_type *ipv4_ext_data;
-               struct TLV_IPv4_Internal_type *ipv4_int_type;
-       } data;
+       msg_data_t data_type; // internal or external tlv type
+       struct eigrp_metrics metrics;
 };
 
 #endif /* _ZEBRA_EIGRP_STRUCTURES_H_ */
index 50d83430a8e8cc2852507670e2e1dce4e09443b9..64e65b694cce8838dfd44de393cb22051b6c4fa3 100644 (file)
@@ -81,25 +81,18 @@ static int eigrp_prefix_entry_cmp(struct eigrp_prefix_entry *node1,
 {
        if (node1->af == AF_INET) {
                if (node2->af == AF_INET) {
-                       if (node1->destination_ipv4->prefix.s_addr
-                           < node2->destination_ipv4->prefix.s_addr) {
-                               return -1; // if it belong above node2
-                       } else {
-                               if (node1->destination_ipv4->prefix.s_addr
-                                   > node2->destination_ipv4->prefix.s_addr) {
-                                       return 1; // if it belongs under node2
-                               } else {
-                                       return 0; // same value... ERROR...in
-                                                 // case of adding same prefix
-                                                 // again
-                               }
-                       }
-               } else {
+                       if (node1->destination->u.prefix4.s_addr
+                           < node2->destination->u.prefix4.s_addr)
+                               return -1;
+                       if (node1->destination->u.prefix4.s_addr
+                           > node2->destination->u.prefix4.s_addr)
+                               return 1;
+                       else
+                               return 0;
+               } else
                        return 1;
-               }
-       } else {          // TODO check if the prefix dont exists
-               return 1; // add to end
-       }
+       } else
+               return 1;
 }
 
 /*
@@ -125,8 +118,7 @@ struct eigrp_prefix_entry *eigrp_prefix_entry_new()
        new->rij = list_new();
        new->entries->cmp = (int (*)(void *, void *))eigrp_neighbor_entry_cmp;
        new->distance = new->fdistance = new->rdistance = EIGRP_MAX_METRIC;
-       new->destination_ipv4 = NULL;
-       new->destination_ipv6 = NULL;
+       new->destination = NULL;
 
        return new;
 }
@@ -137,9 +129,8 @@ struct eigrp_prefix_entry *eigrp_prefix_entry_new()
 static int eigrp_neighbor_entry_cmp(struct eigrp_neighbor_entry *entry1,
                                    struct eigrp_neighbor_entry *entry2)
 {
-       if (entry1->distance
-           < entry2->distance) // parameter used in list_add_sort ()
-               return -1;      // actually set to sort by distance
+       if (entry1->distance < entry2->distance)
+               return -1;
        if (entry1->distance > entry2->distance)
                return 1;
 
@@ -205,7 +196,7 @@ void eigrp_neighbor_entry_add(struct eigrp_prefix_entry *node,
                listnode_add_sort(node->entries, entry);
                entry->prefix = node;
 
-               eigrp_zebra_route_add(node->destination_ipv4, l);
+               eigrp_zebra_route_add(node->destination, l);
        }
 
        list_delete(l);
@@ -230,7 +221,7 @@ void eigrp_prefix_entry_delete(struct list *topology,
                list_free(node->entries);
                list_free(node->rij);
                listnode_delete(topology, node);
-               eigrp_zebra_route_delete(node->destination_ipv4);
+               eigrp_zebra_route_delete(node->destination);
                XFREE(MTYPE_EIGRP_PREFIX_ENTRY, node);
        }
 }
@@ -243,7 +234,7 @@ void eigrp_neighbor_entry_delete(struct eigrp_prefix_entry *node,
 {
        if (listnode_lookup(node->entries, entry) != NULL) {
                listnode_delete(node->entries, entry);
-               eigrp_zebra_route_delete(node->destination_ipv4);
+               eigrp_zebra_route_delete(node->destination);
                XFREE(MTYPE_EIGRP_NEIGHBOR_ENTRY, entry);
        }
 }
@@ -270,16 +261,12 @@ unsigned int eigrp_topology_table_isempty(struct list *topology)
 
 struct eigrp_prefix_entry *
 eigrp_topology_table_lookup_ipv4(struct list *topology_table,
-                                struct prefix_ipv4 *address)
+                                struct prefix *address)
 {
        struct eigrp_prefix_entry *data;
        struct listnode *node;
        for (ALL_LIST_ELEMENTS_RO(topology_table, node, data)) {
-               if ((data->af == AF_INET)
-                   && (data->destination_ipv4->prefix.s_addr
-                       == address->prefix.s_addr)
-                   && (data->destination_ipv4->prefixlen
-                       == address->prefixlen))
+               if (prefix_same(data->destination, address))
                        return data;
        }
 
@@ -380,37 +367,56 @@ enum metric_change eigrp_topology_update_distance(struct eigrp_fsm_action_messag
        struct eigrp_prefix_entry *prefix = msg->prefix;
        struct eigrp_neighbor_entry *entry = msg->entry;
        enum metric_change change = METRIC_SAME;
+       u_int32_t new_reported_distance;
+
        assert(entry);
 
-       struct TLV_IPv4_External_type *ext_data = NULL;
-       struct TLV_IPv4_Internal_type *int_data = NULL;
-       if (msg->data_type == EIGRP_TLV_IPv4_INT) {
-               u_int32_t new_reported_distance;
+       switch(msg->data_type) {
+       case EIGRP_CONNECTED:
+               if (prefix->nt == EIGRP_TOPOLOGY_TYPE_CONNECTED)
+                       return change;
 
-               int_data = msg->data.ipv4_int_type;
-               if (eigrp_metrics_is_same(int_data->metric,
+               change = METRIC_DECREASE;
+               break;
+       case EIGRP_INT:
+               if (prefix->nt == EIGRP_TOPOLOGY_TYPE_CONNECTED) {
+                       change = METRIC_INCREASE;
+                       goto distance_done;
+               }
+               if (eigrp_metrics_is_same(msg->metrics,
                                          entry->reported_metric)) {
                        return change; // No change
                }
 
                new_reported_distance = eigrp_calculate_metrics(eigrp,
-                                                               int_data->metric);
+                                                               msg->metrics);
 
-               if (entry->reported_distance  < new_reported_distance)
+               if (entry->reported_distance < new_reported_distance) {
                        change = METRIC_INCREASE;
-               else
+                       goto distance_done;
+               } else
                        change = METRIC_DECREASE;
 
-               entry->reported_metric = int_data->metric;
+               entry->reported_metric = msg->metrics;
                entry->reported_distance = new_reported_distance;
-                       eigrp_calculate_metrics(eigrp, int_data->metric);
+               eigrp_calculate_metrics(eigrp, msg->metrics);
                entry->distance = eigrp_calculate_total_metrics(eigrp, entry);
-       } else {
-               ext_data = msg->data.ipv4_ext_data;
-               if (eigrp_metrics_is_same(ext_data->metric,
-                                         entry->reported_metric))
-                       return change;
+               break;
+       case EIGRP_EXT:
+               if (prefix->nt == EIGRP_TOPOLOGY_TYPE_REMOTE_EXTERNAL) {
+                       if (eigrp_metrics_is_same(msg->metrics,
+                                                 entry->reported_metric))
+                               return change;
+               } else {
+                       change = METRIC_INCREASE;
+                       goto distance_done;
+               }
+               break;
+       default:
+               zlog_err("%s: Please implement handler", __PRETTY_FUNCTION__);
+               break;
        }
+ distance_done:
        /*
         * Move to correct position in list according to new distance
         */
@@ -464,13 +470,14 @@ void eigrp_update_routing_table(struct eigrp_prefix_entry *prefix)
        struct eigrp_neighbor_entry *entry;
 
        if (successors) {
-               eigrp_zebra_route_add(prefix->destination_ipv4, successors);
+               eigrp_zebra_route_add(prefix->destination,
+                                     successors);
                for (ALL_LIST_ELEMENTS_RO(successors, node, entry))
                        entry->flags |= EIGRP_NEIGHBOR_ENTRY_INTABLE_FLAG;
 
                list_delete(successors);
        } else {
-               eigrp_zebra_route_delete(prefix->destination_ipv4);
+               eigrp_zebra_route_delete(prefix->destination);
                for (ALL_LIST_ELEMENTS_RO(prefix->entries, node, entry))
                        entry->flags &= ~EIGRP_NEIGHBOR_ENTRY_INTABLE_FLAG;
        }
@@ -485,24 +492,19 @@ void eigrp_topology_neighbor_down(struct eigrp *eigrp,
 
        for (ALL_LIST_ELEMENTS(eigrp->topology_table, node1, node11, prefix)) {
                for (ALL_LIST_ELEMENTS(prefix->entries, node2, node22, entry)) {
-                       if (entry->adv_router == nbr) {
-                               struct eigrp_fsm_action_message *msg;
-                               msg = XCALLOC(MTYPE_EIGRP_FSM_MSG,
-                                             sizeof(struct
-                                                    eigrp_fsm_action_message));
-                               struct TLV_IPv4_Internal_type *tlv =
-                                       eigrp_IPv4_InternalTLV_new();
-                               tlv->metric.delay = EIGRP_MAX_METRIC;
-                               msg->packet_type = EIGRP_OPC_UPDATE;
-                               msg->eigrp = eigrp;
-                               msg->data_type = EIGRP_TLV_IPv4_INT;
-                               msg->adv_router = nbr;
-                               msg->data.ipv4_int_type = tlv;
-                               msg->entry = entry;
-                               msg->prefix = prefix;
-                               int event = eigrp_get_fsm_event(msg);
-                               eigrp_fsm_event(msg, event);
-                       }
+                       struct eigrp_fsm_action_message msg;
+
+                       if (entry->adv_router != nbr)
+                               continue;
+
+                       msg.metrics.delay = EIGRP_MAX_METRIC;
+                       msg.packet_type = EIGRP_OPC_UPDATE;
+                       msg.eigrp = eigrp;
+                       msg.data_type = EIGRP_INT;
+                       msg.adv_router = nbr;
+                       msg.entry = entry;
+                       msg.prefix = prefix;
+                       eigrp_fsm_event(&msg);
                }
        }
 
index 0c9b5c60c6a077c9d417a92bcff09bcf811d0efd..8bff08b75a84857a69bf679e874b758f1c9b79ed 100644 (file)
@@ -49,7 +49,7 @@ extern void eigrp_neighbor_entry_delete(struct eigrp_prefix_entry *,
 extern void eigrp_topology_delete_all(struct list *);
 extern unsigned int eigrp_topology_table_isempty(struct list *);
 extern struct eigrp_prefix_entry *
-eigrp_topology_table_lookup_ipv4(struct list *, struct prefix_ipv4 *);
+eigrp_topology_table_lookup_ipv4(struct list *, struct prefix *);
 extern struct list *eigrp_topology_get_successor(struct eigrp_prefix_entry *);
 extern struct list *
 eigrp_topology_get_successor_max(struct eigrp_prefix_entry *pe,
index e0169c514b416a58bd09050188d4b444285943df..d6a1134124f581adbdbfa44af97e9a56189753ae 100644 (file)
@@ -112,47 +112,31 @@ static void eigrp_update_receive_GR_ask(struct eigrp *eigrp,
 {
        struct listnode *node1;
        struct eigrp_prefix_entry *prefix;
-       struct TLV_IPv4_Internal_type *tlv_max;
+       struct eigrp_fsm_action_message fsm_msg;
 
        /* iterate over all prefixes which weren't advertised by neighbor */
        for (ALL_LIST_ELEMENTS_RO(nbr_prefixes, node1, prefix)) {
-               zlog_debug("GR receive: Neighbor not advertised %s/%d",
-                          inet_ntoa(prefix->destination_ipv4->prefix),
-                          prefix->destination_ipv4->prefixlen);
-
-               /* create internal IPv4 TLV with infinite delay */
-               tlv_max = eigrp_IPv4_InternalTLV_new();
-               tlv_max->type = EIGRP_TLV_IPv4_INT;
-               tlv_max->length = 28U;
-               tlv_max->metric = prefix->reported_metric;
-               /* set delay to MAX */
-               tlv_max->metric.delay = EIGRP_MAX_METRIC;
-               tlv_max->destination = prefix->destination_ipv4->prefix;
-               tlv_max->prefix_length = prefix->destination_ipv4->prefixlen;
-
+               char buffer[PREFIX_STRLEN];
+               zlog_debug("GR receive: Neighbor not advertised %s",
+                          prefix2str(prefix->destination,
+                                     buffer, PREFIX_STRLEN));
 
-               /* prepare message for FSM */
-               struct eigrp_fsm_action_message *fsm_msg;
-               fsm_msg = XCALLOC(MTYPE_EIGRP_FSM_MSG,
-                                 sizeof(struct eigrp_fsm_action_message));
+               fsm_msg.metrics = prefix->reported_metric;
+               /* set delay to MAX */
+               fsm_msg.metrics.delay = EIGRP_MAX_METRIC;
 
                struct eigrp_neighbor_entry *entry =
                        eigrp_prefix_entry_lookup(prefix->entries, nbr);
 
-               fsm_msg->packet_type = EIGRP_OPC_UPDATE;
-               fsm_msg->eigrp = eigrp;
-               fsm_msg->data_type = EIGRP_TLV_IPv4_INT;
-               fsm_msg->adv_router = nbr;
-               fsm_msg->data.ipv4_int_type = tlv_max;
-               fsm_msg->entry = entry;
-               fsm_msg->prefix = prefix;
+               fsm_msg.packet_type = EIGRP_OPC_UPDATE;
+               fsm_msg.eigrp = eigrp;
+               fsm_msg.data_type = EIGRP_INT;
+               fsm_msg.adv_router = nbr;
+               fsm_msg.entry = entry;
+               fsm_msg.prefix = prefix;
 
                /* send message to FSM */
-               int event = eigrp_get_fsm_event(fsm_msg);
-               eigrp_fsm_event(fsm_msg, event);
-
-               /* free memory used by TLV */
-               eigrp_IPv4_InternalTLV_free(tlv_max);
+               eigrp_fsm_event(&fsm_msg);
        }
 }
 
@@ -169,9 +153,11 @@ void eigrp_update_receive(struct eigrp *eigrp, struct ip *iph,
        struct eigrp_neighbor_entry *ne;
        u_int32_t flags;
        u_int16_t type;
+       u_int16_t length;
        u_char same;
        struct access_list *alist;
        struct prefix_list *plist;
+       struct prefix dest_addr;
        struct eigrp *e;
        u_char graceful_restart;
        u_char graceful_restart_final;
@@ -287,16 +273,15 @@ void eigrp_update_receive(struct eigrp *eigrp, struct ip *iph,
        /*If there is topology information*/
        while (s->endp > s->getp) {
                type = stream_getw(s);
-               if (type == EIGRP_TLV_IPv4_INT) {
-                       struct prefix_ipv4 dest_addr;
-
+               switch (type) {
+               case EIGRP_TLV_IPv4_INT:
                        stream_set_getp(s, s->getp - sizeof(u_int16_t));
 
                        tlv = eigrp_read_ipv4_tlv(s);
 
                        /*searching if destination exists */
                        dest_addr.family = AF_INET;
-                       dest_addr.prefix = tlv->destination;
+                       dest_addr.u.prefix4 = tlv->destination;
                        dest_addr.prefixlen = tlv->prefix_length;
                        struct eigrp_prefix_entry *dest =
                                eigrp_topology_table_lookup_ipv4(
@@ -310,31 +295,26 @@ void eigrp_update_receive(struct eigrp *eigrp, struct ip *iph,
                                        remove_received_prefix_gr(nbr_prefixes,
                                                                  dest);
 
-                               struct eigrp_fsm_action_message *msg;
-                               msg = XCALLOC(MTYPE_EIGRP_FSM_MSG,
-                                             sizeof(struct
-                                                    eigrp_fsm_action_message));
+                               struct eigrp_fsm_action_message msg;
                                struct eigrp_neighbor_entry *entry =
                                        eigrp_prefix_entry_lookup(dest->entries,
                                                                  nbr);
 
-                               msg->packet_type = EIGRP_OPC_UPDATE;
-                               msg->eigrp = eigrp;
-                               msg->data_type = EIGRP_TLV_IPv4_INT;
-                               msg->adv_router = nbr;
-                               msg->data.ipv4_int_type = tlv;
-                               msg->entry = entry;
-                               msg->prefix = dest;
-                               int event = eigrp_get_fsm_event(msg);
-                               eigrp_fsm_event(msg, event);
+                               msg.packet_type = EIGRP_OPC_UPDATE;
+                               msg.eigrp = eigrp;
+                               msg.data_type = EIGRP_INT;
+                               msg.adv_router = nbr;
+                               msg.metrics = tlv->metric;
+                               msg.entry = entry;
+                               msg.prefix = dest;
+                               eigrp_fsm_event(&msg);
                        } else {
                                /*Here comes topology information save*/
                                pe = eigrp_prefix_entry_new();
                                pe->serno = eigrp->serno;
-                               pe->destination_ipv4 = prefix_ipv4_new();
-                               prefix_copy(
-                                       (struct prefix *)pe->destination_ipv4,
-                                       (struct prefix *)&dest_addr);
+                               pe->destination = (struct prefix *)prefix_ipv4_new();
+                               prefix_copy(pe->destination,
+                                           &dest_addr);
                                pe->af = AF_INET;
                                pe->state = EIGRP_FSM_STATE_PASSIVE;
                                pe->nt = EIGRP_TOPOLOGY_TYPE_REMOTE;
@@ -358,9 +338,8 @@ void eigrp_update_receive(struct eigrp *eigrp, struct ip *iph,
 
                                /* Check if access-list fits */
                                if (alist
-                                   && access_list_apply(
-                                              alist,
-                                              (struct prefix *)&dest_addr)
+                                   && access_list_apply(alist,
+                                                        &dest_addr)
                                               == FILTER_DENY) {
                                        /* If yes, set reported metric to Max */
                                        ne->reported_metric.delay =
@@ -375,9 +354,8 @@ void eigrp_update_receive(struct eigrp *eigrp, struct ip *iph,
 
                                /* Check if prefix-list fits */
                                if (plist
-                                   && prefix_list_apply(
-                                              plist,
-                                              (struct prefix *)&dest_addr)
+                                   && prefix_list_apply(plist,
+                                                        &dest_addr)
                                               == PREFIX_DENY) {
                                        /* If yes, set reported metric to Max */
                                        ne->reported_metric.delay =
@@ -389,9 +367,8 @@ void eigrp_update_receive(struct eigrp *eigrp, struct ip *iph,
 
                                /* Check if access-list fits */
                                if (alist
-                                   && access_list_apply(
-                                              alist,
-                                              (struct prefix *)&dest_addr)
+                                   && access_list_apply(alist,
+                                                        &dest_addr)
                                               == FILTER_DENY) {
                                        /* If yes, set reported metric to Max */
                                        ne->reported_metric.delay =
@@ -402,9 +379,8 @@ void eigrp_update_receive(struct eigrp *eigrp, struct ip *iph,
 
                                /* Check if prefix-list fits */
                                if (plist
-                                   && prefix_list_apply(
-                                              plist,
-                                              (struct prefix *)&dest_addr)
+                                   && prefix_list_apply(plist,
+                                                        &dest_addr)
                                               == PREFIX_DENY) {
                                        /* If yes, set reported metric to Max */
                                        ne->reported_metric.delay =
@@ -436,6 +412,18 @@ void eigrp_update_receive(struct eigrp *eigrp, struct ip *iph,
                                        pe);
                        }
                        eigrp_IPv4_InternalTLV_free(tlv);
+                       break;
+
+               case EIGRP_TLV_IPv4_EXT:
+                       /* DVS: processing of external routes needs packet and fsm work.
+                        *      for now, lets just not creash the box
+                        */
+               default:
+                       length = stream_getw(s);
+                       // -2 for type, -2 for len
+                       for (length-=4; length ; length--) {
+                               (void)stream_getc(s);
+                       }
                }
        }
 
@@ -463,7 +451,7 @@ void eigrp_update_send_init(struct eigrp_neighbor *nbr)
        struct eigrp_packet *ep;
        u_int16_t length = EIGRP_HEADER_LEN;
 
-       ep = eigrp_packet_new(nbr->ei->ifp->mtu);
+       ep = eigrp_packet_new(nbr->ei->ifp->mtu, nbr);
 
        /* Prepare EIGRP INIT UPDATE header */
        if (IS_DEBUG_EIGRP_PACKET(0, RECV))
@@ -471,9 +459,10 @@ void eigrp_update_send_init(struct eigrp_neighbor *nbr)
                           nbr->ei->eigrp->sequence_number,
                           nbr->recv_sequence_number);
 
-       eigrp_packet_header_init(
-               EIGRP_OPC_UPDATE, nbr->ei, ep->s, EIGRP_INIT_FLAG,
-               nbr->ei->eigrp->sequence_number, nbr->recv_sequence_number);
+       eigrp_packet_header_init(EIGRP_OPC_UPDATE, nbr->ei->eigrp,
+                                ep->s, EIGRP_INIT_FLAG,
+                                nbr->ei->eigrp->sequence_number,
+                                nbr->recv_sequence_number);
 
        // encode Authentication TLV, if needed
        if ((IF_DEF_PARAMS(nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5)
@@ -497,7 +486,7 @@ void eigrp_update_send_init(struct eigrp_neighbor *nbr)
                           ep->length, ep->sequence_number, inet_ntoa(ep->dst));
 
        /*Put packet to retransmission queue*/
-       eigrp_fifo_push_head(nbr->retrans_queue, ep);
+       eigrp_fifo_push(nbr->retrans_queue, ep);
 
        if (nbr->retrans_queue->count == 1) {
                eigrp_send_packet_reliably(nbr);
@@ -528,7 +517,42 @@ static void eigrp_update_place_on_nbr_queue(struct eigrp_neighbor *nbr,
                           ep->length, ep->sequence_number, inet_ntoa(ep->dst));
 
        /*Put packet to retransmission queue*/
-       eigrp_fifo_push_head(nbr->retrans_queue, ep);
+       eigrp_fifo_push(nbr->retrans_queue, ep);
+
+       if (nbr->retrans_queue->count == 1)
+               eigrp_send_packet_reliably(nbr);
+}
+
+static void eigrp_update_send_to_all_nbrs(struct eigrp_interface *ei,
+                                         struct eigrp_packet *ep)
+{
+       struct listnode *node, *nnode;
+       struct eigrp_neighbor *nbr;
+       bool packet_sent = false;
+
+       for (ALL_LIST_ELEMENTS(ei->nbrs, node, nnode, nbr)) {
+               struct eigrp_packet *ep_dup;
+
+               if (nbr->state != EIGRP_NEIGHBOR_UP)
+                       continue;
+
+               if (packet_sent)
+                       ep_dup = eigrp_packet_duplicate(ep, NULL);
+               else
+                       ep_dup = ep;
+
+               ep_dup->nbr = nbr;
+               packet_sent = true;
+               /*Put packet to retransmission queue*/
+               eigrp_fifo_push(nbr->retrans_queue, ep_dup);
+
+               if (nbr->retrans_queue->count == 1) {
+                       eigrp_send_packet_reliably(nbr);
+               }
+       }
+
+       if (!packet_sent)
+               eigrp_packet_free(ep);
 }
 
 void eigrp_update_send_EOT(struct eigrp_neighbor *nbr)
@@ -543,15 +567,15 @@ void eigrp_update_send_EOT(struct eigrp_neighbor *nbr)
        struct access_list *alist_i;
        struct prefix_list *plist_i;
        struct eigrp *e;
-       struct prefix_ipv4 *dest_addr;
+       struct prefix *dest_addr;
        u_int32_t seq_no = nbr->ei->eigrp->sequence_number;
 
-       ep = eigrp_packet_new(nbr->ei->ifp->mtu);
+       ep = eigrp_packet_new(nbr->ei->ifp->mtu, nbr);
 
        /* Prepare EIGRP EOT UPDATE header */
-       eigrp_packet_header_init(EIGRP_OPC_UPDATE, nbr->ei, ep->s, EIGRP_EOT_FLAG,
-                                seq_no,
-                                nbr->recv_sequence_number);
+       eigrp_packet_header_init(EIGRP_OPC_UPDATE, nbr->ei->eigrp,
+                                ep->s, EIGRP_EOT_FLAG,
+                                seq_no, nbr->recv_sequence_number);
 
        // encode Authentication TLV, if needed
        if((IF_DEF_PARAMS (nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) &&
@@ -561,18 +585,17 @@ void eigrp_update_send_EOT(struct eigrp_neighbor *nbr)
 
        for (ALL_LIST_ELEMENTS(nbr->ei->eigrp->topology_table, node, nnode, pe)) {
                for (ALL_LIST_ELEMENTS(pe->entries, node2, nnode2, te)) {
-                       if ((te->ei == nbr->ei)
-                           && (te->prefix->nt == EIGRP_TOPOLOGY_TYPE_REMOTE))
+                       if (eigrp_nbr_split_horizon_check(te, nbr->ei))
                                continue;
 
                        if ((length + 0x001D) > (u_int16_t)nbr->ei->ifp->mtu) {
                                eigrp_update_place_on_nbr_queue (nbr, ep, seq_no, length);
-                               eigrp_send_packet_reliably(nbr);
                                seq_no++;
 
                                length = EIGRP_HEADER_LEN;
-                               ep = eigrp_packet_new(nbr->ei->ifp->mtu);
-                               eigrp_packet_header_init(EIGRP_OPC_UPDATE, nbr->ei, ep->s, EIGRP_EOT_FLAG,
+                               ep = eigrp_packet_new(nbr->ei->ifp->mtu, nbr);
+                               eigrp_packet_header_init(EIGRP_OPC_UPDATE, nbr->ei->eigrp,
+                                                        ep->s, EIGRP_EOT_FLAG,
                                                         seq_no, nbr->recv_sequence_number);
 
                                if((IF_DEF_PARAMS (nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) &&
@@ -582,7 +605,7 @@ void eigrp_update_send_EOT(struct eigrp_neighbor *nbr)
                                }
                        }
                        /* Get destination address from prefix */
-                       dest_addr = pe->destination_ipv4;
+                       dest_addr = pe->destination;
 
                        /*
                         * Filtering
@@ -599,13 +622,13 @@ void eigrp_update_send_EOT(struct eigrp_neighbor *nbr)
                        /* Check if any list fits */
                        if ((alist
                             && access_list_apply (alist,
-                                                  (struct prefix *) dest_addr) == FILTER_DENY)||
+                                                  dest_addr) == FILTER_DENY)||
                            (plist && prefix_list_apply (plist,
-                                                        (struct prefix *) dest_addr) == PREFIX_DENY)||
+                                                        dest_addr) == PREFIX_DENY)||
                            (alist_i && access_list_apply (alist_i,
-                                                          (struct prefix *) dest_addr) == FILTER_DENY)||
+                                                          dest_addr) == FILTER_DENY)||
                            (plist_i && prefix_list_apply (plist_i,
-                                                          (struct prefix *) dest_addr) == PREFIX_DENY)) {
+                                                          dest_addr) == PREFIX_DENY)) {
                                //pe->reported_metric.delay = EIGRP_MAX_METRIC;
                                continue;
                        } else {
@@ -615,14 +638,13 @@ void eigrp_update_send_EOT(struct eigrp_neighbor *nbr)
        }
 
        eigrp_update_place_on_nbr_queue (nbr, ep, seq_no, length);
-       eigrp_send_packet_reliably(nbr);
+       nbr->ei->eigrp->sequence_number = seq_no++;
 }
 
 void eigrp_update_send(struct eigrp_interface *ei)
 {
        struct eigrp_packet *ep;
        struct listnode *node, *nnode;
-       struct eigrp_neighbor *nbr;
        struct eigrp_prefix_entry *pe;
        u_char has_tlv;
        struct access_list *alist;
@@ -630,16 +652,19 @@ void eigrp_update_send(struct eigrp_interface *ei)
        struct access_list *alist_i;
        struct prefix_list *plist_i;
        struct eigrp *e;
-       struct prefix_ipv4 *dest_addr;
-       bool packet_sent = false;
+       struct prefix *dest_addr;
+       u_int32_t seq_no = ei->eigrp->sequence_number;
+
+       if (ei->nbrs->count == 0)
+               return;
 
        u_int16_t length = EIGRP_HEADER_LEN;
 
-       ep = eigrp_packet_new(ei->ifp->mtu);
+       ep = eigrp_packet_new(ei->ifp->mtu, NULL);
 
        /* Prepare EIGRP INIT UPDATE header */
-       eigrp_packet_header_init(EIGRP_OPC_UPDATE, ei, ep->s, 0,
-                                ei->eigrp->sequence_number, 0);
+       eigrp_packet_header_init(EIGRP_OPC_UPDATE, ei->eigrp,
+                                ep->s, 0, seq_no, 0);
 
        // encode Authentication TLV, if needed
        if ((IF_DEF_PARAMS(ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5)
@@ -650,57 +675,77 @@ void eigrp_update_send(struct eigrp_interface *ei)
        has_tlv = 0;
        for (ALL_LIST_ELEMENTS(ei->eigrp->topology_changes_internalIPV4, node,
                               nnode, pe)) {
-               if (pe->req_action & EIGRP_FSM_NEED_UPDATE) {
-                       /* Get destination address from prefix */
-                       dest_addr = pe->destination_ipv4;
+               struct eigrp_neighbor_entry *ne;
 
-                       /*
-                        * Filtering
-                        */
-                       // TODO: Work in progress
-                       /* get list from eigrp process */
-                       e = eigrp_lookup();
-                       /* Get access-lists and prefix-lists from process and
-                        * interface */
-                       alist = e->list[EIGRP_FILTER_OUT];
-                       plist = e->prefix[EIGRP_FILTER_OUT];
-                       alist_i = ei->list[EIGRP_FILTER_OUT];
-                       plist_i = ei->prefix[EIGRP_FILTER_OUT];
+               if (!(pe->req_action & EIGRP_FSM_NEED_UPDATE))
+                       continue;
 
-                       /* Check if any list fits */
-                       if ((alist
-                            && access_list_apply(alist,
-                                                 (struct prefix *)dest_addr)
-                                       == FILTER_DENY)
-                           || (plist
-                               && prefix_list_apply(plist,
-                                                    (struct prefix *)dest_addr)
-                                          == PREFIX_DENY)
-                           || (alist_i
-                               && access_list_apply(alist_i,
-                                                    (struct prefix *)dest_addr)
-                                          == FILTER_DENY)
-                           || (plist_i
-                               && prefix_list_apply(plist_i,
-                                                    (struct prefix *)dest_addr)
-                                          == PREFIX_DENY)) {
-                               zlog_info("PROC OUT: Skipping");
-                               // pe->reported_metric.delay = EIGRP_MAX_METRIC;
-                               zlog_info("PROC OUT Prefix: %s",
-                                         inet_ntoa(dest_addr->prefix));
-                               continue;
-                       } else {
-                               zlog_info("PROC OUT: NENastavujem metriku ");
-                               length += eigrp_add_internalTLV_to_stream(ep->s,
-                                                                         pe);
-                               has_tlv = 1;
+               ne = listnode_head(pe->entries);
+               if (eigrp_nbr_split_horizon_check(ne, ei))
+                       continue;
+
+               if ((length + 0x001D) > (u_int16_t)ei->ifp->mtu) {
+                       if ((IF_DEF_PARAMS(ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5)
+                           && (IF_DEF_PARAMS(ei->ifp)->auth_keychain != NULL)) {
+                               eigrp_make_md5_digest(ei, ep->s, EIGRP_AUTH_UPDATE_FLAG);
                        }
-                       /*
-                        * End of filtering
-                        */
 
-                       /* NULL the pointer */
-                       dest_addr = NULL;
+                       eigrp_packet_checksum(ei, ep->s, length);
+                       ep->length = length;
+
+                       ep->dst.s_addr = htonl(EIGRP_MULTICAST_ADDRESS);
+
+                       ep->sequence_number = seq_no;
+                       seq_no++;
+                       eigrp_update_send_to_all_nbrs(ei, ep);
+
+                       length = EIGRP_HEADER_LEN;
+                       ep = eigrp_packet_new(ei->ifp->mtu, NULL);
+                       eigrp_packet_header_init(EIGRP_OPC_UPDATE, ei->eigrp,
+                                                ep->s, 0, seq_no, 0);
+                       if ((IF_DEF_PARAMS(ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5)
+                           && (IF_DEF_PARAMS(ei->ifp)->auth_keychain != NULL)) {
+                               length += eigrp_add_authTLV_MD5_to_stream(ep->s, ei);
+                       }
+                       has_tlv = 0;
+               }
+               /* Get destination address from prefix */
+               dest_addr = pe->destination;
+
+               /*
+                * Filtering
+                */
+               e = eigrp_lookup();
+               /* Get access-lists and prefix-lists from process and
+                * interface */
+               alist = e->list[EIGRP_FILTER_OUT];
+               plist = e->prefix[EIGRP_FILTER_OUT];
+               alist_i = ei->list[EIGRP_FILTER_OUT];
+               plist_i = ei->prefix[EIGRP_FILTER_OUT];
+
+               /* Check if any list fits */
+               if ((alist
+                    && access_list_apply(alist,
+                                         dest_addr)
+                    == FILTER_DENY)
+                   || (plist
+                       && prefix_list_apply(plist,
+                                            dest_addr)
+                       == PREFIX_DENY)
+                   || (alist_i
+                       && access_list_apply(alist_i,
+                                            dest_addr)
+                       == FILTER_DENY)
+                   || (plist_i
+                       && prefix_list_apply(plist_i,
+                                            dest_addr)
+                       == PREFIX_DENY)) {
+                       // pe->reported_metric.delay = EIGRP_MAX_METRIC;
+                       continue;
+               } else {
+                       length += eigrp_add_internalTLV_to_stream(ep->s,
+                                                                 pe);
+                       has_tlv = 1;
                }
        }
 
@@ -727,20 +772,8 @@ void eigrp_update_send(struct eigrp_interface *ei)
                zlog_debug("Enqueuing Update length[%u] Seq [%u]", length,
                           ep->sequence_number);
 
-       for (ALL_LIST_ELEMENTS(ei->nbrs, node, nnode, nbr)) {
-               if (nbr->state == EIGRP_NEIGHBOR_UP) {
-                       packet_sent = true;
-                       /*Put packet to retransmission queue*/
-                       eigrp_fifo_push_head(nbr->retrans_queue, ep);
-
-                       if (nbr->retrans_queue->count == 1) {
-                               eigrp_send_packet_reliably(nbr);
-                       }
-               }
-       }
-
-       if (!packet_sent)
-               eigrp_packet_free(ep);
+       eigrp_update_send_to_all_nbrs(ei, ep);
+       ei->eigrp->sequence_number = seq_no++;
 }
 
 void eigrp_update_send_all(struct eigrp *eigrp,
@@ -762,8 +795,6 @@ void eigrp_update_send_all(struct eigrp *eigrp,
                        pe->req_action &= ~EIGRP_FSM_NEED_UPDATE;
                        listnode_delete(eigrp->topology_changes_internalIPV4,
                                        pe);
-                       zlog_debug("UPDATE COUNT: %d",
-                                  eigrp->topology_changes_internalIPV4->count);
                }
        }
 }
@@ -789,14 +820,13 @@ static void eigrp_update_send_GR_part(struct eigrp_neighbor *nbr)
        u_int16_t length = EIGRP_HEADER_LEN;
        struct listnode *node, *nnode;
        struct eigrp_prefix_entry *pe;
-       struct prefix_ipv4 *dest_addr;
+       struct prefix *dest_addr;
        struct eigrp *e;
        struct access_list *alist, *alist_i;
        struct prefix_list *plist, *plist_i;
        struct list *prefixes;
        u_int32_t flags;
        unsigned int send_prefixes;
-       struct TLV_IPv4_Internal_type *tlv_max;
 
        /* get prefixes to send to neighbor */
        prefixes = nbr->nbr_gr_prefixes_send;
@@ -835,10 +865,10 @@ static void eigrp_update_send_GR_part(struct eigrp_neighbor *nbr)
                }
        }
 
-       ep = eigrp_packet_new(nbr->ei->ifp->mtu);
+       ep = eigrp_packet_new(nbr->ei->ifp->mtu, nbr);
 
        /* Prepare EIGRP Graceful restart UPDATE header */
-       eigrp_packet_header_init(EIGRP_OPC_UPDATE, nbr->ei, ep->s, flags,
+       eigrp_packet_header_init(EIGRP_OPC_UPDATE, nbr->ei->eigrp, ep->s, flags,
                                 nbr->ei->eigrp->sequence_number,
                                 nbr->recv_sequence_number);
 
@@ -853,7 +883,7 @@ static void eigrp_update_send_GR_part(struct eigrp_neighbor *nbr)
                /*
                 * Filtering
                 */
-               dest_addr = pe->destination_ipv4;
+               dest_addr = pe->destination;
                /* get list from eigrp process */
                e = eigrp_lookup();
                /* Get access-lists and prefix-lists from process and interface
@@ -865,22 +895,20 @@ static void eigrp_update_send_GR_part(struct eigrp_neighbor *nbr)
 
                /* Check if any list fits */
                if ((alist
-                    && access_list_apply(alist, (struct prefix *)dest_addr)
+                    && access_list_apply(alist, dest_addr)
                                == FILTER_DENY)
                    || (plist
-                       && prefix_list_apply(plist, (struct prefix *)dest_addr)
+                       && prefix_list_apply(plist, dest_addr)
                                   == PREFIX_DENY)
                    || (alist_i
-                       && access_list_apply(alist_i,
-                                            (struct prefix *)dest_addr)
+                       && access_list_apply(alist_i, dest_addr)
                                   == FILTER_DENY)
                    || (plist_i
-                       && prefix_list_apply(plist_i,
-                                            (struct prefix *)dest_addr)
+                       && prefix_list_apply(plist_i, dest_addr)
                                   == PREFIX_DENY)) {
                        /* do not send filtered route */
                        zlog_info("Filtered prefix %s won't be sent out.",
-                                 inet_ntoa(dest_addr->prefix));
+                                 inet_ntoa(dest_addr->u.prefix4));
                } else {
                        /* sending route which wasn't filtered */
                        length += eigrp_add_internalTLV_to_stream(ep->s, pe);
@@ -894,56 +922,39 @@ static void eigrp_update_send_GR_part(struct eigrp_neighbor *nbr)
 
                /* Check if any list fits */
                if ((alist
-                    && access_list_apply(alist, (struct prefix *)dest_addr)
+                    && access_list_apply(alist, dest_addr)
                                == FILTER_DENY)
                    || (plist
-                       && prefix_list_apply(plist, (struct prefix *)dest_addr)
+                       && prefix_list_apply(plist, dest_addr)
                                   == PREFIX_DENY)
                    || (alist_i
-                       && access_list_apply(alist_i,
-                                            (struct prefix *)dest_addr)
+                       && access_list_apply(alist_i, dest_addr)
                                   == FILTER_DENY)
                    || (plist_i
-                       && prefix_list_apply(plist_i,
-                                            (struct prefix *)dest_addr)
+                       && prefix_list_apply(plist_i, dest_addr)
                                   == PREFIX_DENY)) {
                        /* do not send filtered route */
                        zlog_info("Filtered prefix %s will be removed.",
-                                 inet_ntoa(dest_addr->prefix));
-
-                       tlv_max = eigrp_IPv4_InternalTLV_new();
-                       tlv_max->type = EIGRP_TLV_IPv4_INT;
-                       tlv_max->length = 28U;
-                       tlv_max->metric = pe->reported_metric;
-                       /* set delay to MAX */
-                       tlv_max->metric.delay = EIGRP_MAX_METRIC;
-                       tlv_max->destination = pe->destination_ipv4->prefix;
-                       tlv_max->prefix_length =
-                               pe->destination_ipv4->prefixlen;
+                                 inet_ntoa(dest_addr->u.prefix4));
 
                        /* prepare message for FSM */
-                       struct eigrp_fsm_action_message *fsm_msg;
-                       fsm_msg = XCALLOC(
-                               MTYPE_EIGRP_FSM_MSG,
-                               sizeof(struct eigrp_fsm_action_message));
+                       struct eigrp_fsm_action_message fsm_msg;
 
                        struct eigrp_neighbor_entry *entry =
                                eigrp_prefix_entry_lookup(pe->entries, nbr);
 
-                       fsm_msg->packet_type = EIGRP_OPC_UPDATE;
-                       fsm_msg->eigrp = e;
-                       fsm_msg->data_type = EIGRP_TLV_IPv4_INT;
-                       fsm_msg->adv_router = nbr;
-                       fsm_msg->data.ipv4_int_type = tlv_max;
-                       fsm_msg->entry = entry;
-                       fsm_msg->prefix = pe;
+                       fsm_msg.packet_type = EIGRP_OPC_UPDATE;
+                       fsm_msg.eigrp = e;
+                       fsm_msg.data_type = EIGRP_INT;
+                       fsm_msg.adv_router = nbr;
+                       fsm_msg.metrics = pe->reported_metric;
+                       /* Set delay to MAX */
+                       fsm_msg.metrics.delay = EIGRP_MAX_METRIC;
+                       fsm_msg.entry = entry;
+                       fsm_msg.prefix = pe;
 
                        /* send message to FSM */
-                       int event = eigrp_get_fsm_event(fsm_msg);
-                       eigrp_fsm_event(fsm_msg, event);
-
-                       /* free memory used by TLV */
-                       eigrp_IPv4_InternalTLV_free(tlv_max);
+                       eigrp_fsm_event(&fsm_msg);
                }
                /*
                 * End of filtering
@@ -980,7 +991,7 @@ static void eigrp_update_send_GR_part(struct eigrp_neighbor *nbr)
                           ep->length, ep->sequence_number, inet_ntoa(ep->dst));
 
        /*Put packet to retransmission queue*/
-       eigrp_fifo_push_head(nbr->retrans_queue, ep);
+       eigrp_fifo_push(nbr->retrans_queue, ep);
 
        if (nbr->retrans_queue->count == 1) {
                eigrp_send_packet_reliably(nbr);
index 465007478d940cfe328c187bf200a3196fc93f0e..4a8842f30e9c65dd8fb7101b3768cbd152e6b736 100644 (file)
@@ -391,10 +391,10 @@ DEFUN (eigrp_network,
        "EIGRP network prefix\n")
 {
        VTY_DECLVAR_CONTEXT(eigrp, eigrp);
-       struct prefix_ipv4 p;
+       struct prefix p;
        int ret;
 
-       str2prefix_ipv4(argv[1]->arg, &p);
+       str2prefix(argv[1]->arg, &p);
 
        ret = eigrp_network_set(eigrp, &p);
 
@@ -414,10 +414,10 @@ DEFUN (no_eigrp_network,
        "EIGRP network prefix\n")
 {
        VTY_DECLVAR_CONTEXT(eigrp, eigrp);
-       struct prefix_ipv4 p;
+       struct prefix p;
        int ret;
 
-       str2prefix_ipv4(argv[2]->arg, &p);
+       str2prefix(argv[2]->arg, &p);
 
        ret = eigrp_network_unset(eigrp, &p);
 
index 1ee1237f756ba14ea28274261079fe312e3fadb1..47871dfd3e381484c8ca611e41cf85d31b4dc065 100644 (file)
@@ -66,8 +66,8 @@ static int eigrp_interface_state_down(int, struct zclient *, zebra_size_t,
                                      vrf_id_t vrf_id);
 static struct interface *zebra_interface_if_lookup(struct stream *);
 
-static int eigrp_zebra_read_ipv4(int, struct zclient *, zebra_size_t,
-                                vrf_id_t vrf_id);
+static int eigrp_zebra_read_route(int, struct zclient *, zebra_size_t,
+                                 vrf_id_t vrf_id);
 
 /* Zebra structure to hold current status. */
 struct zclient *zclient = NULL;
@@ -112,59 +112,31 @@ void eigrp_zebra_init(void)
        zclient->interface_down = eigrp_interface_state_down;
        zclient->interface_address_add = eigrp_interface_address_add;
        zclient->interface_address_delete = eigrp_interface_address_delete;
-       zclient->redistribute_route_ipv4_add = eigrp_zebra_read_ipv4;
-       zclient->redistribute_route_ipv4_del = eigrp_zebra_read_ipv4;
+       zclient->redistribute_route_add = eigrp_zebra_read_route;
+       zclient->redistribute_route_del = eigrp_zebra_read_route;
 }
 
 
 /* Zebra route add and delete treatment. */
-static int eigrp_zebra_read_ipv4(int command, struct zclient *zclient,
-                                zebra_size_t length, vrf_id_t vrf_id)
+static int eigrp_zebra_read_route(int command, struct zclient *zclient,
+                                 zebra_size_t length, vrf_id_t vrf_id)
 {
-       struct stream *s;
-       struct zapi_ipv4 api;
-       struct prefix_ipv4 p;
+       struct zapi_route api;
        struct eigrp *eigrp;
 
-       s = zclient->ibuf;
-
-       /* Type, flags, message. */
-       api.type = stream_getc(s);
-       api.instance = stream_getw(s);
-       api.flags = stream_getc(s);
-       api.message = stream_getc(s);
-
-       /* IPv4 prefix. */
-       memset(&p, 0, sizeof(struct prefix_ipv4));
-       p.family = AF_INET;
-       p.prefixlen = stream_getc(s);
-       stream_get(&p.prefix, s, PSIZE(p.prefixlen));
+       if (zapi_route_decode(zclient->ibuf, &api) < 0)
+               return -1;
 
-       if (IPV4_NET127(ntohl(p.prefix.s_addr)))
+       if (IPV4_NET127(ntohl(api.prefix.u.prefix4.s_addr)))
                return 0;
 
-       /* Nexthop, ifindex, distance, metric. */
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) {
-               api.nexthop_num = stream_getc(s);
-               stream_get_ipv4(s);
-       }
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) {
-               api.ifindex_num = stream_getc(s);
-               /* XXX assert(api.ifindex_num == 1); */
-               stream_getl(s); /* ifindex, unused */
-       }
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE))
-               api.distance = stream_getc(s);
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC))
-               api.metric = stream_getl(s);
-
        eigrp = eigrp_lookup();
        if (eigrp == NULL)
                return 0;
 
-       if (command == ZEBRA_IPV4_ROUTE_ADD) {
+       if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD) {
 
-       } else /* if (command == ZEBRA_IPV4_ROUTE_DELETE) */
+       } else /* if (command == ZEBRA_REDISTRIBUTE_ROUTE_DEL) */
        {
        }
 
@@ -389,90 +361,67 @@ static struct interface *zebra_interface_if_lookup(struct stream *s)
                ifname_tmp, strnlen(ifname_tmp, INTERFACE_NAMSIZ), VRF_DEFAULT);
 }
 
-void eigrp_zebra_route_add(struct prefix_ipv4 *p, struct list *successors)
+void eigrp_zebra_route_add(struct prefix *p, struct list *successors)
 {
+       struct zapi_route api;
+       struct zapi_nexthop *api_nh;
        struct eigrp_neighbor_entry *te;
        struct listnode *node;
-       u_char message;
-       u_char flags;
-       int psize;
-       struct stream *s;
-
-       if (zclient->redist[AFI_IP][ZEBRA_ROUTE_EIGRP]) {
-               message = 0;
-               flags = 0;
-
-               /* EIGRP pass nexthop and metric */
-               SET_FLAG(message, ZAPI_MESSAGE_NEXTHOP);
-
-               /* Make packet. */
-               s = zclient->obuf;
-               stream_reset(s);
-
-               /* Put command, type, flags, message. */
-               zclient_create_header(s, ZEBRA_IPV4_ROUTE_ADD, VRF_DEFAULT);
-               stream_putc(s, ZEBRA_ROUTE_EIGRP);
-               stream_putw(s, 0);
-               stream_putl(s, flags);
-               stream_putc(s, message);
-               stream_putw(s, SAFI_UNICAST);
-
-               /* Put prefix information. */
-               psize = PSIZE(p->prefixlen);
-               stream_putc(s, p->prefixlen);
-               stream_write(s, (u_char *)&p->prefix, psize);
-
-               /* Nexthop count. */
-               stream_putc(s, successors->count);
-
-               /* Nexthop, ifindex, distance and metric information. */
-               for (ALL_LIST_ELEMENTS_RO(successors, node, te)) {
-                       if (te->adv_router->src.s_addr) {
-                               stream_putc(s, NEXTHOP_TYPE_IPV4_IFINDEX);
-                               stream_put_in_addr(s, &te->adv_router->src);
-                       } else
-                               stream_putc(s, NEXTHOP_TYPE_IFINDEX);
-                       stream_putl(s, te->ei->ifp->ifindex);
-               }
-
-               if (IS_DEBUG_EIGRP(zebra, ZEBRA_REDISTRIBUTE)) {
-                       char buf[2][INET_ADDRSTRLEN];
-                       zlog_debug("Zebra: Route add %s/%d nexthop %s",
-                                  inet_ntop(AF_INET, &p->prefix, buf[0],
-                                            sizeof(buf[0])),
-                                  p->prefixlen,
-                                  inet_ntop(AF_INET, 0 /*&p->nexthop*/, buf[1],
-                                            sizeof(buf[1])));
-               }
-
-               stream_putw_at(s, 0, stream_get_endp(s));
+       int count = 0;
+
+       if (!zclient->redist[AFI_IP][ZEBRA_ROUTE_EIGRP])
+               return;
+
+       memset(&api, 0, sizeof(api));
+       api.vrf_id = VRF_DEFAULT;
+       api.type = ZEBRA_ROUTE_EIGRP;
+       api.safi = SAFI_UNICAST;
+       memcpy(&api.prefix, p, sizeof(*p));
+
+       SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
+       api.nexthop_num = successors->count;
+
+       /* Nexthop, ifindex, distance and metric information. */
+       for (ALL_LIST_ELEMENTS_RO(successors, node, te)) {
+               api_nh = &api.nexthops[count];
+               if (te->adv_router->src.s_addr) {
+                       api_nh->gate.ipv4 = te->adv_router->src;
+                       api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX;
+               } else
+                       api_nh->type = NEXTHOP_TYPE_IFINDEX;
+               api_nh->ifindex = te->ei->ifp->ifindex;
+
+               count++;
+       }
 
-               zclient_send_message(zclient);
+       if (IS_DEBUG_EIGRP(zebra, ZEBRA_REDISTRIBUTE)) {
+               char buf[2][PREFIX_STRLEN];
+               zlog_debug("Zebra: Route add %s nexthop %s",
+                          prefix2str(p, buf[0], PREFIX_STRLEN),
+                          inet_ntop(AF_INET, 0, buf[1], PREFIX_STRLEN));
        }
+
+       zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api);
 }
 
-void eigrp_zebra_route_delete(struct prefix_ipv4 *p)
+void eigrp_zebra_route_delete(struct prefix *p)
 {
-       struct zapi_ipv4 api;
-
-       if (zclient->redist[AFI_IP][ZEBRA_ROUTE_EIGRP]) {
-               api.vrf_id = VRF_DEFAULT;
-               api.type = ZEBRA_ROUTE_EIGRP;
-               api.instance = 0;
-               api.flags = 0;
-               api.message = 0;
-               api.safi = SAFI_UNICAST;
-               zapi_ipv4_route(ZEBRA_IPV4_ROUTE_DELETE, zclient, p, &api);
-
-               if (IS_DEBUG_EIGRP(zebra, ZEBRA_REDISTRIBUTE)) {
-                       char buf[2][INET_ADDRSTRLEN];
-                       zlog_debug("Zebra: Route del %s/%d nexthop %s",
-                                  inet_ntop(AF_INET, &p->prefix, buf[0],
-                                            sizeof(buf[0])),
-                                  p->prefixlen,
-                                  inet_ntop(AF_INET, 0 /*&p->nexthop*/, buf[1],
-                                            sizeof(buf[1])));
-               }
+       struct zapi_route api;
+
+       if (!zclient->redist[AFI_IP][ZEBRA_ROUTE_EIGRP])
+               return;
+
+       memset(&api, 0, sizeof(api));
+       api.vrf_id = VRF_DEFAULT;
+       api.type = ZEBRA_ROUTE_EIGRP;
+       api.safi = SAFI_UNICAST;
+       memcpy(&api.prefix, p, sizeof(*p));
+       zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
+
+       if (IS_DEBUG_EIGRP(zebra, ZEBRA_REDISTRIBUTE)) {
+               char buf[PREFIX_STRLEN];
+               zlog_debug("Zebra: Route del %s",
+                          prefix2str(p, buf, PREFIX_STRLEN));
        }
 
        return;
index 3281c470180f76169d437f2350dcf54923fa4799..1c418dddef61c2f38833c32ef78c7117e58a7a61 100644 (file)
@@ -33,8 +33,8 @@
 
 extern void eigrp_zebra_init(void);
 
-extern void eigrp_zebra_route_add(struct prefix_ipv4 *, struct list *);
-extern void eigrp_zebra_route_delete(struct prefix_ipv4 *);
+extern void eigrp_zebra_route_add(struct prefix *, struct list *);
+extern void eigrp_zebra_route_delete(struct prefix *);
 extern int eigrp_redistribute_set(struct eigrp *, int, struct eigrp_metrics);
 extern int eigrp_redistribute_unset(struct eigrp *, int);
 extern int eigrp_is_type_redistributed(int);
index b0dd8db6dea092d043c93a42dbf9e73a0bcda4b4..c207f5946fdf2a99bad26772bf7e089aa8c90539 100644 (file)
@@ -11,14 +11,28 @@ def run(cmd):
     proc.wait()
     return rv
 
+clangfmt = run(['git', 'show', 'master:.clang-format'])
+
 argp = argparse.ArgumentParser(description = 'git whitespace-fixing tool')
 argp.add_argument('branch', metavar='BRANCH', type = str, nargs = '?', default = 'HEAD')
 args = argp.parse_args()
 
 branch = args.branch
 commit   = run(['git', 'rev-list', '-n', '1', branch, '--']).strip()
-beforeid = run(['git', 'rev-list', '-n', '1', 'reindent-master-before', '--']).strip()
-afterid  = run(['git', 'rev-list', '-n', '1', 'reindent-master-after', '--']).strip()
+
+# frr-3.1-dev = first commit that is on master but not on stable/3.0
+masterid = run(['git', 'rev-list', '-n', '1', 'frr-3.1-dev', '--']).strip()
+masterbase = run(['git', 'merge-base', commit, masterid]).strip()
+
+if masterbase == masterid:
+    refbranch = 'master'
+else:
+    refbranch = '3.0'
+
+sys.stderr.write('autodetected base: %s (can be 3.0 or master)\n' % refbranch)
+
+beforeid = run(['git', 'rev-list', '-n', '1', 'reindent-%s-before' % refbranch, '--']).strip()
+afterid  = run(['git', 'rev-list', '-n', '1', 'reindent-%s-after' % refbranch, '--']).strip()
 
 beforebase = run(['git', 'merge-base', commit, beforeid]).strip()
 afterbase  = run(['git', 'merge-base', commit, afterid]).strip()
@@ -28,10 +42,10 @@ if afterbase == afterid:
     sys.exit(1)
 
 if beforebase != beforeid:
-    sys.stderr.write('you need to rebase your branch onto the tag "reindent-master-before"\n')
+    sys.stderr.write('you need to rebase your branch onto the tag "reindent-%s-before"\n' % refbranch)
     sys.exit(1)
 
-revs = run(['git', 'rev-list', 'reindent-master-before..%s' % commit]).strip().split('\n')
+revs = run(['git', 'rev-list', 'reindent-%s-before..%s' % (refbranch, commit)]).strip().split('\n')
 revs.reverse()
 
 srcdir = os.getcwd()
@@ -39,9 +53,12 @@ tmpdir = tempfile.mkdtemp('frrindent')
 os.chdir(tmpdir)
 
 sys.stderr.write('using temporary directory %s; %d revisions\n' % (tmpdir, len(revs)))
-run(['git', 'clone', '-s', '-b', 'reindent-master-after', srcdir, 'repo'])
+run(['git', 'clone', '-s', '-b', 'reindent-%s-after' % refbranch, srcdir, 'repo'])
 os.chdir('repo')
 
+with open('.clang-format', 'w') as fd:
+    fd.write(clangfmt)
+
 prev = beforeid
 for rev in revs:
     filestat = run(['git', 'diff', '-z', '--name-status', prev, rev]).rstrip('\0').split('\0')
index 98f612f827874b4b74259250c2b1b5d710bbd0e6..2c8b12608818fd8435f1b3c320b7847553c9338a 100644 (file)
 extern struct zebra_privs_t isisd_privs;
 
 struct bpf_insn llcfilter[] = {
-       BPF_STMT(BPF_LD + BPF_B + BPF_ABS,
-                ETHER_HDR_LEN), /* check first byte */
+       /* check first byte */
+       BPF_STMT(BPF_LD + BPF_B + BPF_ABS, ETH_ALEN),
        BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ISO_SAP, 0, 5),
-       BPF_STMT(BPF_LD + BPF_B + BPF_ABS, ETHER_HDR_LEN + 1),
-       BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ISO_SAP, 0,
-                3), /* check second byte */
-       BPF_STMT(BPF_LD + BPF_B + BPF_ABS, ETHER_HDR_LEN + 2),
-       BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x03, 0, 1), /* check third byte */
+       /* check second byte */
+       BPF_STMT(BPF_LD + BPF_B + BPF_ABS, ETH_ALEN + 1),
+       BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ISO_SAP, 0, 3),
+       /* check third byte */
+       BPF_STMT(BPF_LD + BPF_B + BPF_ABS, ETH_ALEN + 2),
+       BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x03, 0, 1),
        BPF_STMT(BPF_RET + BPF_K, (u_int)-1),
        BPF_STMT(BPF_RET + BPF_K, 0)};
 u_int readblen = 0;
@@ -243,15 +244,14 @@ int isis_recv_pdu_bcast(struct isis_circuit *circuit, u_char *ssnpa)
 
        assert(bpf_hdr->bh_caplen == bpf_hdr->bh_datalen);
 
-       offset = bpf_hdr->bh_hdrlen + LLC_LEN + ETHER_HDR_LEN;
+       offset = bpf_hdr->bh_hdrlen + LLC_LEN + ETH_ALEN;
 
        /* then we lose the BPF, LLC and ethernet headers */
        stream_write(circuit->rcv_stream, readbuff + offset,
-                    bpf_hdr->bh_caplen - LLC_LEN - ETHER_HDR_LEN);
+                    bpf_hdr->bh_caplen - LLC_LEN - ETH_ALEN);
        stream_set_getp(circuit->rcv_stream, 0);
 
-       memcpy(ssnpa, readbuff + bpf_hdr->bh_hdrlen + ETH_ALEN,
-              ETH_ALEN);
+       memcpy(ssnpa, readbuff + bpf_hdr->bh_hdrlen + ETH_ALEN, ETH_ALEN);
 
        if (ioctl(circuit->fd, BIOCFLUSH, &one) < 0)
                zlog_warn("Flushing failed: %s", safe_strerror(errno));
@@ -265,7 +265,7 @@ int isis_send_pdu_bcast(struct isis_circuit *circuit, int level)
        ssize_t written;
        size_t buflen;
 
-       buflen = stream_get_endp(circuit->snd_stream) + LLC_LEN + ETHER_HDR_LEN;
+       buflen = stream_get_endp(circuit->snd_stream) + LLC_LEN + ETH_ALEN;
        if (buflen > sizeof(sock_buff)) {
                zlog_warn(
                        "isis_send_pdu_bcast: sock_buff size %zu is less than "
@@ -291,12 +291,12 @@ int isis_send_pdu_bcast(struct isis_circuit *circuit, int level)
        /*
         * Then the LLC
         */
-       sock_buff[ETHER_HDR_LEN] = ISO_SAP;
-       sock_buff[ETHER_HDR_LEN + 1] = ISO_SAP;
-       sock_buff[ETHER_HDR_LEN + 2] = 0x03;
+       sock_buff[ETH_ALEN] = ISO_SAP;
+       sock_buff[ETH_ALEN + 1] = ISO_SAP;
+       sock_buff[ETH_ALEN + 2] = 0x03;
 
        /* then we copy the data */
-       memcpy(sock_buff + (LLC_LEN + ETHER_HDR_LEN), circuit->snd_stream->data,
+       memcpy(sock_buff + (LLC_LEN + ETH_ALEN), circuit->snd_stream->data,
               stream_get_endp(circuit->snd_stream));
 
        /* now we can send this */
index 9622dcdbc4e480c424a7f20fb231920385cfe35d..a1aa87e396d15ecbfc7333a90eca2c6c12304a4a 100644 (file)
@@ -1336,8 +1336,8 @@ int isis_if_delete_hook(struct interface *ifp)
 void isis_circuit_init()
 {
        /* Initialize Zebra interface data structure */
-       if_add_hook(IF_NEW_HOOK, isis_if_new_hook);
-       if_add_hook(IF_DELETE_HOOK, isis_if_delete_hook);
+       hook_register_prio(if_add, 0, isis_if_new_hook);
+       hook_register_prio(if_del, 0, isis_if_delete_hook);
 
        /* Install interface node */
        install_node(&interface_node, isis_interface_config_write);
index 2a19465a01feafa4e269060d477699efc249961d..17d8ad3c0b887924c148fa49395789ee65896083 100644 (file)
@@ -181,7 +181,7 @@ DEFUN (no_isis_passive,
 
        if (if_is_loopback(circuit->interface)) {
                vty_out(vty, "Can't set no passive for loopback interface\n");
-               return CMD_ERR_AMBIGUOUS;
+               return CMD_WARNING_CONFIG_FAILED;
        }
 
        isis_circuit_passive_set(circuit, 0);
@@ -206,7 +206,7 @@ DEFUN (isis_circuit_type,
        is_type = string2circuit_t(argv[idx_level]->arg);
        if (!is_type) {
                vty_out(vty, "Unknown circuit-type \n");
-               return CMD_ERR_AMBIGUOUS;
+               return CMD_WARNING_CONFIG_FAILED;
        }
 
        if (circuit->state == C_STATE_UP
@@ -214,7 +214,7 @@ DEFUN (isis_circuit_type,
            && circuit->area->is_type != is_type) {
                vty_out(vty, "Invalid circuit level for area %s.\n",
                        circuit->area->area_tag);
-               return CMD_ERR_AMBIGUOUS;
+               return CMD_WARNING_CONFIG_FAILED;
        }
        isis_circuit_is_type_set(circuit, is_type);
 
@@ -262,7 +262,7 @@ DEFUN (isis_network,
        if (isis_circuit_circ_type_set(circuit, CIRCUIT_T_P2P)) {
                vty_out(vty,
                        "isis network point-to-point is valid only on broadcast interfaces\n");
-               return CMD_ERR_AMBIGUOUS;
+               return CMD_WARNING_CONFIG_FAILED;
        }
 
        return CMD_SUCCESS;
@@ -283,7 +283,7 @@ DEFUN (no_isis_network,
        if (isis_circuit_circ_type_set(circuit, CIRCUIT_T_BROADCAST)) {
                vty_out(vty,
                        "isis network point-to-point is valid only on broadcast interfaces\n");
-               return CMD_ERR_AMBIGUOUS;
+               return CMD_WARNING_CONFIG_FAILED;
        }
 
        return CMD_SUCCESS;
@@ -313,7 +313,7 @@ DEFUN (isis_passwd,
                                                       argv[idx_word]->arg);
        if (rv) {
                vty_out(vty, "Too long circuit password (>254)\n");
-               return CMD_ERR_AMBIGUOUS;
+               return CMD_WARNING_CONFIG_FAILED;
        }
 
        return CMD_SUCCESS;
@@ -355,7 +355,7 @@ DEFUN (isis_priority,
        prio = atoi(argv[idx_number]->arg);
        if (prio < MIN_PRIORITY || prio > MAX_PRIORITY) {
                vty_out(vty, "Invalid priority %d - should be <0-127>\n", prio);
-               return CMD_ERR_AMBIGUOUS;
+               return CMD_WARNING_CONFIG_FAILED;
        }
 
        circuit->priority[0] = prio;
@@ -400,7 +400,7 @@ DEFUN (isis_priority_l1,
        prio = atoi(argv[idx_number]->arg);
        if (prio < MIN_PRIORITY || prio > MAX_PRIORITY) {
                vty_out(vty, "Invalid priority %d - should be <0-127>\n", prio);
-               return CMD_ERR_AMBIGUOUS;
+               return CMD_WARNING_CONFIG_FAILED;
        }
 
        circuit->priority[0] = prio;
@@ -444,7 +444,7 @@ DEFUN (isis_priority_l2,
        prio = atoi(argv[idx_number]->arg);
        if (prio < MIN_PRIORITY || prio > MAX_PRIORITY) {
                vty_out(vty, "Invalid priority %d - should be <0-127>\n", prio);
-               return CMD_ERR_AMBIGUOUS;
+               return CMD_WARNING_CONFIG_FAILED;
        }
 
        circuit->priority[1] = prio;
@@ -494,7 +494,7 @@ DEFUN (isis_metric,
                        "Invalid metric %d - should be <0-63> "
                        "when narrow metric type enabled\n",
                        met);
-               return CMD_ERR_AMBIGUOUS;
+               return CMD_WARNING_CONFIG_FAILED;
        }
 
        /* RFC4444 */
@@ -504,7 +504,7 @@ DEFUN (isis_metric,
                        "Invalid metric %d - should be <0-16777215> "
                        "when wide metric type enabled\n",
                        met);
-               return CMD_ERR_AMBIGUOUS;
+               return CMD_WARNING_CONFIG_FAILED;
        }
 
        isis_circuit_metric_set(circuit, IS_LEVEL_1, met);
@@ -554,7 +554,7 @@ DEFUN (isis_metric_l1,
                        "Invalid metric %d - should be <0-63> "
                        "when narrow metric type enabled\n",
                        met);
-               return CMD_ERR_AMBIGUOUS;
+               return CMD_WARNING_CONFIG_FAILED;
        }
 
        /* RFC4444 */
@@ -564,7 +564,7 @@ DEFUN (isis_metric_l1,
                        "Invalid metric %d - should be <0-16777215> "
                        "when wide metric type enabled\n",
                        met);
-               return CMD_ERR_AMBIGUOUS;
+               return CMD_WARNING_CONFIG_FAILED;
        }
 
        isis_circuit_metric_set(circuit, IS_LEVEL_1, met);
@@ -613,7 +613,7 @@ DEFUN (isis_metric_l2,
                        "Invalid metric %d - should be <0-63> "
                        "when narrow metric type enabled\n",
                        met);
-               return CMD_ERR_AMBIGUOUS;
+               return CMD_WARNING_CONFIG_FAILED;
        }
 
        /* RFC4444 */
@@ -623,7 +623,7 @@ DEFUN (isis_metric_l2,
                        "Invalid metric %d - should be <0-16777215> "
                        "when wide metric type enabled\n",
                        met);
-               return CMD_ERR_AMBIGUOUS;
+               return CMD_WARNING_CONFIG_FAILED;
        }
 
        isis_circuit_metric_set(circuit, IS_LEVEL_2, met);
@@ -667,7 +667,7 @@ DEFUN (isis_hello_interval,
        if (interval < MIN_HELLO_INTERVAL || interval > MAX_HELLO_INTERVAL) {
                vty_out(vty, "Invalid hello-interval %d - should be <1-600>\n",
                        interval);
-               return CMD_ERR_AMBIGUOUS;
+               return CMD_WARNING_CONFIG_FAILED;
        }
 
        circuit->hello_interval[0] = (u_int16_t)interval;
@@ -714,7 +714,7 @@ DEFUN (isis_hello_interval_l1,
        if (interval < MIN_HELLO_INTERVAL || interval > MAX_HELLO_INTERVAL) {
                vty_out(vty, "Invalid hello-interval %ld - should be <1-600>\n",
                        interval);
-               return CMD_ERR_AMBIGUOUS;
+               return CMD_WARNING_CONFIG_FAILED;
        }
 
        circuit->hello_interval[0] = (u_int16_t)interval;
@@ -760,7 +760,7 @@ DEFUN (isis_hello_interval_l2,
        if (interval < MIN_HELLO_INTERVAL || interval > MAX_HELLO_INTERVAL) {
                vty_out(vty, "Invalid hello-interval %ld - should be <1-600>\n",
                        interval);
-               return CMD_ERR_AMBIGUOUS;
+               return CMD_WARNING_CONFIG_FAILED;
        }
 
        circuit->hello_interval[1] = (u_int16_t)interval;
@@ -806,7 +806,7 @@ DEFUN (isis_hello_multiplier,
                vty_out(vty,
                        "Invalid hello-multiplier %d - should be <2-100>\n",
                        mult);
-               return CMD_ERR_AMBIGUOUS;
+               return CMD_WARNING_CONFIG_FAILED;
        }
 
        circuit->hello_multiplier[0] = (u_int16_t)mult;
@@ -854,7 +854,7 @@ DEFUN (isis_hello_multiplier_l1,
                vty_out(vty,
                        "Invalid hello-multiplier %d - should be <2-100>\n",
                        mult);
-               return CMD_ERR_AMBIGUOUS;
+               return CMD_WARNING_CONFIG_FAILED;
        }
 
        circuit->hello_multiplier[0] = (u_int16_t)mult;
@@ -901,7 +901,7 @@ DEFUN (isis_hello_multiplier_l2,
                vty_out(vty,
                        "Invalid hello-multiplier %d - should be <2-100>\n",
                        mult);
-               return CMD_ERR_AMBIGUOUS;
+               return CMD_WARNING_CONFIG_FAILED;
        }
 
        circuit->hello_multiplier[1] = (u_int16_t)mult;
@@ -979,7 +979,7 @@ DEFUN (csnp_interval,
        if (interval < MIN_CSNP_INTERVAL || interval > MAX_CSNP_INTERVAL) {
                vty_out(vty, "Invalid csnp-interval %lu - should be <1-600>\n",
                        interval);
-               return CMD_ERR_AMBIGUOUS;
+               return CMD_WARNING_CONFIG_FAILED;
        }
 
        circuit->csnp_interval[0] = (u_int16_t)interval;
@@ -1026,7 +1026,7 @@ DEFUN (csnp_interval_l1,
        if (interval < MIN_CSNP_INTERVAL || interval > MAX_CSNP_INTERVAL) {
                vty_out(vty, "Invalid csnp-interval %lu - should be <1-600>\n",
                        interval);
-               return CMD_ERR_AMBIGUOUS;
+               return CMD_WARNING_CONFIG_FAILED;
        }
 
        circuit->csnp_interval[0] = (u_int16_t)interval;
@@ -1072,7 +1072,7 @@ DEFUN (csnp_interval_l2,
        if (interval < MIN_CSNP_INTERVAL || interval > MAX_CSNP_INTERVAL) {
                vty_out(vty, "Invalid csnp-interval %lu - should be <1-600>\n",
                        interval);
-               return CMD_ERR_AMBIGUOUS;
+               return CMD_WARNING_CONFIG_FAILED;
        }
 
        circuit->csnp_interval[1] = (u_int16_t)interval;
@@ -1117,7 +1117,7 @@ DEFUN (psnp_interval,
        if (interval < MIN_PSNP_INTERVAL || interval > MAX_PSNP_INTERVAL) {
                vty_out(vty, "Invalid psnp-interval %lu - should be <1-120>\n",
                        interval);
-               return CMD_ERR_AMBIGUOUS;
+               return CMD_WARNING_CONFIG_FAILED;
        }
 
        circuit->psnp_interval[0] = (u_int16_t)interval;
@@ -1164,7 +1164,7 @@ DEFUN (psnp_interval_l1,
        if (interval < MIN_PSNP_INTERVAL || interval > MAX_PSNP_INTERVAL) {
                vty_out(vty, "Invalid psnp-interval %lu - should be <1-120>\n",
                        interval);
-               return CMD_ERR_AMBIGUOUS;
+               return CMD_WARNING_CONFIG_FAILED;
        }
 
        circuit->psnp_interval[0] = (u_int16_t)interval;
@@ -1210,7 +1210,7 @@ DEFUN (psnp_interval_l2,
        if (interval < MIN_PSNP_INTERVAL || interval > MAX_PSNP_INTERVAL) {
                vty_out(vty, "Invalid psnp-interval %lu - should be <1-120>\n",
                        interval);
-               return CMD_ERR_AMBIGUOUS;
+               return CMD_WARNING_CONFIG_FAILED;
        }
 
        circuit->psnp_interval[1] = (u_int16_t)interval;
@@ -1253,12 +1253,12 @@ DEFUN (circuit_topology,
        if (circuit->area && circuit->area->oldmetric) {
                vty_out(vty,
                        "Multi topology IS-IS can only be used with wide metrics\n");
-               return CMD_ERR_AMBIGUOUS;
+               return CMD_WARNING_CONFIG_FAILED;
        }
 
        if (mtid == (uint16_t)-1) {
                vty_out(vty, "Don't know topology '%s'\n", arg);
-               return CMD_ERR_AMBIGUOUS;
+               return CMD_WARNING_CONFIG_FAILED;
        }
 
        return isis_circuit_mt_enabled_set(circuit, mtid, true);
@@ -1281,12 +1281,12 @@ DEFUN (no_circuit_topology,
        if (circuit->area && circuit->area->oldmetric) {
                vty_out(vty,
                        "Multi topology IS-IS can only be used with wide metrics\n");
-               return CMD_ERR_AMBIGUOUS;
+               return CMD_WARNING_CONFIG_FAILED;
        }
 
        if (mtid == (uint16_t)-1) {
                vty_out(vty, "Don't know topology '%s'\n", arg);
-               return CMD_ERR_AMBIGUOUS;
+               return CMD_WARNING_CONFIG_FAILED;
        }
 
        return isis_circuit_mt_enabled_set(circuit, mtid, false);
@@ -1298,11 +1298,11 @@ static int validate_metric_style_narrow(struct vty *vty, struct isis_area *area)
        struct listnode *node;
 
        if (!vty)
-               return CMD_ERR_AMBIGUOUS;
+               return CMD_WARNING_CONFIG_FAILED;
 
        if (!area) {
                vty_out(vty, "ISIS area is invalid\n");
-               return CMD_ERR_AMBIGUOUS;
+               return CMD_WARNING_CONFIG_FAILED;
        }
 
        for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit)) {
@@ -1311,14 +1311,14 @@ static int validate_metric_style_narrow(struct vty *vty, struct isis_area *area)
                    && (circuit->te_metric[0] > MAX_NARROW_LINK_METRIC)) {
                        vty_out(vty, "ISIS circuit %s metric is invalid\n",
                                circuit->interface->name);
-                       return CMD_ERR_AMBIGUOUS;
+                       return CMD_WARNING_CONFIG_FAILED;
                }
                if ((area->is_type & IS_LEVEL_2)
                    && (circuit->is_type & IS_LEVEL_2)
                    && (circuit->te_metric[1] > MAX_NARROW_LINK_METRIC)) {
                        vty_out(vty, "ISIS circuit %s metric is invalid\n",
                                circuit->interface->name);
-                       return CMD_ERR_AMBIGUOUS;
+                       return CMD_WARNING_CONFIG_FAILED;
                }
        }
 
@@ -1345,7 +1345,7 @@ DEFUN (metric_style,
        if (area_is_mt(area)) {
                vty_out(vty,
                        "Narrow metrics cannot be used while multi topology IS-IS is active\n");
-               return CMD_ERR_AMBIGUOUS;
+               return CMD_WARNING_CONFIG_FAILED;
        }
 
        ret = validate_metric_style_narrow(vty, area);
@@ -1373,7 +1373,7 @@ DEFUN (no_metric_style,
        if (area_is_mt(area)) {
                vty_out(vty,
                        "Narrow metrics cannot be used while multi topology IS-IS is active\n");
-               return CMD_ERR_AMBIGUOUS;
+               return CMD_WARNING_CONFIG_FAILED;
        }
 
        ret = validate_metric_style_narrow(vty, area);
@@ -1470,7 +1470,7 @@ static int area_lsp_mtu_set(struct vty *vty, unsigned int lsp_mtu)
                                "ISIS area contains circuit %s, which has a maximum PDU size of %zu.\n",
                                circuit->interface->name,
                                isis_circuit_pdu_size(circuit));
-                       return CMD_ERR_AMBIGUOUS;
+                       return CMD_WARNING_CONFIG_FAILED;
                }
        }
 
@@ -1568,7 +1568,7 @@ static int set_lsp_gen_interval(struct vty *vty, struct isis_area *area,
                                "LSP gen interval %us must be less than "
                                "the LSP refresh interval %us\n",
                                interval, area->lsp_refresh[lvl - 1]);
-                       return CMD_ERR_AMBIGUOUS;
+                       return CMD_WARNING_CONFIG_FAILED;
                }
        }
 
@@ -1817,7 +1817,7 @@ static int area_max_lsp_lifetime_set(struct vty *vty, int level,
                                        "the configured LSP gen interval %us\n",
                                        refresh_interval,
                                        area->lsp_gen_interval[lvl - 1]);
-                               return CMD_ERR_AMBIGUOUS;
+                               return CMD_WARNING_CONFIG_FAILED;
                        }
                }
        }
@@ -1890,14 +1890,14 @@ static int area_lsp_refresh_interval_set(struct vty *vty, int level,
                                "LSP refresh interval %us must be greater than "
                                "the configured LSP gen interval %us\n",
                                interval, area->lsp_gen_interval[lvl - 1]);
-                       return CMD_ERR_AMBIGUOUS;
+                       return CMD_WARNING_CONFIG_FAILED;
                }
                if (interval > (area->max_lsp_lifetime[lvl - 1] - 300)) {
                        vty_out(vty,
                                "LSP refresh interval %us must be less than "
                                "the configured LSP lifetime %us less 300\n",
                                interval, area->max_lsp_lifetime[lvl - 1]);
-                       return CMD_ERR_AMBIGUOUS;
+                       return CMD_WARNING_CONFIG_FAILED;
                }
        }
 
@@ -1961,7 +1961,7 @@ static int area_passwd_set(struct vty *vty, int level,
 
        if (passwd && strlen(passwd) > 254) {
                vty_out(vty, "Too long area password (>254)\n");
-               return CMD_ERR_AMBIGUOUS;
+               return CMD_WARNING_CONFIG_FAILED;
        }
 
        type_set(area, level, passwd, snp_auth);
index 8c6968f8ececb27686c963de912b9c8776dd171d..ed96bd31c29867d17e40d3b53d8343ce1fc7c8fe 100644 (file)
@@ -245,260 +245,91 @@ static int isis_zebra_link_params(int command, struct zclient *zclient,
        return 0;
 }
 
-static void isis_zebra_route_add_ipv4(struct prefix *prefix,
-                                     struct isis_route_info *route_info)
+static void isis_zebra_route_add_route(struct prefix *prefix,
+                                      struct isis_route_info *route_info)
 {
-       u_char message;
-       u_int32_t flags;
-       int psize;
-       struct stream *stream;
+       struct zapi_route api;
+       struct zapi_nexthop *api_nh;
        struct isis_nexthop *nexthop;
-       struct listnode *node;
-
-       if (CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
-               return;
-
-       if (vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_ISIS],
-                            VRF_DEFAULT)) {
-               message = 0;
-               flags = 0;
-
-               SET_FLAG(message, ZAPI_MESSAGE_NEXTHOP);
-               SET_FLAG(message, ZAPI_MESSAGE_METRIC);
-#if 0
-      SET_FLAG (message, ZAPI_MESSAGE_DISTANCE);
-#endif
-
-               stream = zclient->obuf;
-               stream_reset(stream);
-               zclient_create_header(stream, ZEBRA_IPV4_ROUTE_ADD,
-                                     VRF_DEFAULT);
-               /* type */
-               stream_putc(stream, ZEBRA_ROUTE_ISIS);
-               /* instance */
-               stream_putw(stream, 0);
-               /* flags */
-               stream_putl(stream, flags);
-               /* message */
-               stream_putc(stream, message);
-               /* SAFI */
-               stream_putw(stream, SAFI_UNICAST);
-               /* prefix information */
-               psize = PSIZE(prefix->prefixlen);
-               stream_putc(stream, prefix->prefixlen);
-               stream_write(stream, (u_char *)&prefix->u.prefix4, psize);
-
-               stream_putc(stream, listcount(route_info->nexthops));
-
-               /* Nexthop, ifindex, distance and metric information */
-               for (ALL_LIST_ELEMENTS_RO(route_info->nexthops, node,
-                                         nexthop)) {
-                       /* FIXME: can it be ? */
-                       if (nexthop->ip.s_addr != INADDR_ANY) {
-                               stream_putc(stream, NEXTHOP_TYPE_IPV4_IFINDEX);
-                               stream_put_in_addr(stream, &nexthop->ip);
-                               stream_putl(stream, nexthop->ifindex);
-                       } else {
-                               stream_putc(stream, NEXTHOP_TYPE_IFINDEX);
-                               stream_putl(stream, nexthop->ifindex);
-                       }
-               }
-#if 0
-      if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE))
-       stream_putc (stream, route_info->depth);
-#endif
-               if (CHECK_FLAG(message, ZAPI_MESSAGE_METRIC))
-                       stream_putl(stream, route_info->cost);
-
-               stream_putw_at(stream, 0, stream_get_endp(stream));
-               zclient_send_message(zclient);
-               SET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
-               UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC);
-       }
-}
-
-static void isis_zebra_route_del_ipv4(struct prefix *prefix,
-                                     struct isis_route_info *route_info)
-{
-       struct zapi_ipv4 api;
-       struct prefix_ipv4 prefix4;
-
-       if (vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_ISIS],
-                            VRF_DEFAULT)) {
-               api.vrf_id = VRF_DEFAULT;
-               api.type = ZEBRA_ROUTE_ISIS;
-               api.instance = 0;
-               api.flags = 0;
-               api.message = 0;
-               api.safi = SAFI_UNICAST;
-               prefix4.family = AF_INET;
-               prefix4.prefixlen = prefix->prefixlen;
-               prefix4.prefix = prefix->u.prefix4;
-               zapi_ipv4_route(ZEBRA_IPV4_ROUTE_DELETE, zclient, &prefix4,
-                               &api);
-       }
-       UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
-
-       return;
-}
-
-static void isis_zebra_route_add_ipv6(struct prefix *prefix,
-                                     struct isis_route_info *route_info)
-{
-       struct zapi_ipv6 api;
-       struct in6_addr **nexthop_list;
-       ifindex_t *ifindex_list;
        struct isis_nexthop6 *nexthop6;
-       int i, size;
        struct listnode *node;
-       struct prefix_ipv6 prefix6;
+       int count = 0;
 
        if (CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
                return;
 
+       memset(&api, 0, sizeof(api));
        api.vrf_id = VRF_DEFAULT;
        api.type = ZEBRA_ROUTE_ISIS;
-       api.instance = 0;
-       api.flags = 0;
-       api.message = 0;
        api.safi = SAFI_UNICAST;
+       api.prefix = *prefix;
        SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
-       SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX);
        SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
        api.metric = route_info->cost;
 #if 0
-  SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE);
-  api.distance = route_info->depth;
+       SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE);
+       api.distance = route_info->depth;
 #endif
-       api.nexthop_num = listcount(route_info->nexthops6);
-       api.ifindex_num = listcount(route_info->nexthops6);
-
-       /* allocate memory for nexthop_list */
-       size = sizeof(struct isis_nexthop6 *)
-              * listcount(route_info->nexthops6);
-       nexthop_list = (struct in6_addr **)XMALLOC(MTYPE_ISIS_TMP, size);
-       if (!nexthop_list) {
-               zlog_err("isis_zebra_add_route_ipv6: out of memory!");
-               return;
-       }
-
-       /* allocate memory for ifindex_list */
-       size = sizeof(unsigned int) * listcount(route_info->nexthops6);
-       ifindex_list = (ifindex_t *)XMALLOC(MTYPE_ISIS_TMP, size);
-       if (!ifindex_list) {
-               zlog_err("isis_zebra_add_route_ipv6: out of memory!");
-               XFREE(MTYPE_ISIS_TMP, nexthop_list);
-               return;
-       }
 
-       /* for each nexthop */
-       i = 0;
-       for (ALL_LIST_ELEMENTS_RO(route_info->nexthops6, node, nexthop6)) {
-               if (!IN6_IS_ADDR_LINKLOCAL(&nexthop6->ip6)
-                   && !IN6_IS_ADDR_UNSPECIFIED(&nexthop6->ip6)) {
-                       api.nexthop_num--;
-                       api.ifindex_num--;
-                       continue;
+       /* Nexthops */
+       switch (prefix->family) {
+       case AF_INET:
+               for (ALL_LIST_ELEMENTS_RO(route_info->nexthops, node,
+                                         nexthop)) {
+                       api_nh = &api.nexthops[count];
+                       /* FIXME: can it be ? */
+                       if (nexthop->ip.s_addr != INADDR_ANY) {
+                               api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX;
+                               api_nh->gate.ipv4 = nexthop->ip;
+                       } else {
+                               api_nh->type = NEXTHOP_TYPE_IFINDEX;
+                       }
+                       api_nh->ifindex = nexthop->ifindex;
+                       count++;
                }
+               break;
+       case AF_INET6:
+               for (ALL_LIST_ELEMENTS_RO(route_info->nexthops6, node,
+                                         nexthop6)) {
+                       if (!IN6_IS_ADDR_LINKLOCAL(&nexthop6->ip6)
+                           && !IN6_IS_ADDR_UNSPECIFIED(&nexthop6->ip6)) {
+                               continue;
+                       }
 
-               nexthop_list[i] = &nexthop6->ip6;
-               ifindex_list[i] = nexthop6->ifindex;
-               i++;
-       }
-
-       api.nexthop = nexthop_list;
-       api.ifindex = ifindex_list;
-
-       if (api.nexthop_num && api.ifindex_num) {
-               prefix6.family = AF_INET6;
-               prefix6.prefixlen = prefix->prefixlen;
-               memcpy(&prefix6.prefix, &prefix->u.prefix6,
-                      sizeof(struct in6_addr));
-               zapi_ipv6_route(ZEBRA_IPV6_ROUTE_ADD, zclient, &prefix6, NULL,
-                               &api);
-               SET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
-               UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC);
+                       api_nh = &api.nexthops[count];
+                       api_nh->gate.ipv6 = nexthop6->ip6;
+                       api_nh->ifindex = nexthop6->ifindex;
+                       api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
+                       count++;
+               }
+               break;
        }
+       if (!count)
+               return;
 
-       XFREE(MTYPE_ISIS_TMP, nexthop_list);
-       XFREE(MTYPE_ISIS_TMP, ifindex_list);
+       api.nexthop_num = count;
 
-       return;
+       zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api);
+       SET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
+       UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC);
 }
 
-static void isis_zebra_route_del_ipv6(struct prefix *prefix,
-                                     struct isis_route_info *route_info)
+static void isis_zebra_route_del_route(struct prefix *prefix,
+                                      struct isis_route_info *route_info)
 {
-       struct zapi_ipv6 api;
-       struct in6_addr **nexthop_list;
-       ifindex_t *ifindex_list;
-       struct isis_nexthop6 *nexthop6;
-       int i, size;
-       struct listnode *node;
-       struct prefix_ipv6 prefix6;
+       struct zapi_route api;
 
        if (!CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
                return;
 
+       memset(&api, 0, sizeof(api));
        api.vrf_id = VRF_DEFAULT;
        api.type = ZEBRA_ROUTE_ISIS;
-       api.instance = 0;
-       api.flags = 0;
-       api.message = 0;
        api.safi = SAFI_UNICAST;
-       SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
-       SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX);
-       api.nexthop_num = listcount(route_info->nexthops6);
-       api.ifindex_num = listcount(route_info->nexthops6);
-
-       /* allocate memory for nexthop_list */
-       size = sizeof(struct isis_nexthop6 *)
-              * listcount(route_info->nexthops6);
-       nexthop_list = (struct in6_addr **)XMALLOC(MTYPE_ISIS_TMP, size);
-       if (!nexthop_list) {
-               zlog_err("isis_zebra_route_del_ipv6: out of memory!");
-               return;
-       }
-
-       /* allocate memory for ifindex_list */
-       size = sizeof(unsigned int) * listcount(route_info->nexthops6);
-       ifindex_list = (ifindex_t *)XMALLOC(MTYPE_ISIS_TMP, size);
-       if (!ifindex_list) {
-               zlog_err("isis_zebra_route_del_ipv6: out of memory!");
-               XFREE(MTYPE_ISIS_TMP, nexthop_list);
-               return;
-       }
-
-       /* for each nexthop */
-       i = 0;
-       for (ALL_LIST_ELEMENTS_RO(route_info->nexthops6, node, nexthop6)) {
-               if (!IN6_IS_ADDR_LINKLOCAL(&nexthop6->ip6)
-                   && !IN6_IS_ADDR_UNSPECIFIED(&nexthop6->ip6)) {
-                       api.nexthop_num--;
-                       api.ifindex_num--;
-                       continue;
-               }
+       api.prefix = *prefix;
 
-               nexthop_list[i] = &nexthop6->ip6;
-               ifindex_list[i] = nexthop6->ifindex;
-               i++;
-       }
-
-       api.nexthop = nexthop_list;
-       api.ifindex = ifindex_list;
-
-       if (api.nexthop_num && api.ifindex_num) {
-               prefix6.family = AF_INET6;
-               prefix6.prefixlen = prefix->prefixlen;
-               memcpy(&prefix6.prefix, &prefix->u.prefix6,
-                      sizeof(struct in6_addr));
-               zapi_ipv6_route(ZEBRA_IPV6_ROUTE_DELETE, zclient, &prefix6,
-                               NULL, &api);
-               UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
-       }
-
-       XFREE(MTYPE_ISIS_TMP, nexthop_list);
-       XFREE(MTYPE_ISIS_TMP, ifindex_list);
+       zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
+       UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
 }
 
 void isis_zebra_route_update(struct prefix *prefix,
@@ -507,130 +338,23 @@ void isis_zebra_route_update(struct prefix *prefix,
        if (zclient->sock < 0)
                return;
 
-       if ((prefix->family == AF_INET
-            && !vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_ISIS],
-                                 VRF_DEFAULT))
-           || (prefix->family == AF_INET6
-               && !vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_ISIS],
-                                    VRF_DEFAULT)))
-               return;
-
-       if (CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ACTIVE)) {
-               if (prefix->family == AF_INET)
-                       isis_zebra_route_add_ipv4(prefix, route_info);
-               else if (prefix->family == AF_INET6)
-                       isis_zebra_route_add_ipv6(prefix, route_info);
-       } else {
-               if (prefix->family == AF_INET)
-                       isis_zebra_route_del_ipv4(prefix, route_info);
-               else if (prefix->family == AF_INET6)
-                       isis_zebra_route_del_ipv6(prefix, route_info);
-       }
-       return;
-}
-
-static int isis_zebra_read_ipv4(int command, struct zclient *zclient,
-                               zebra_size_t length, vrf_id_t vrf_id)
-{
-       struct stream *stream;
-       struct zapi_ipv4 api;
-       struct prefix_ipv4 p;
-       struct prefix *p_generic = (struct prefix *)&p;
-
-       stream = zclient->ibuf;
-       memset(&api, 0, sizeof(api));
-       memset(&p, 0, sizeof(struct prefix_ipv4));
-
-       api.type = stream_getc(stream);
-       api.instance = stream_getw(stream);
-       api.flags = stream_getl(stream);
-       api.message = stream_getc(stream);
-
-       p.family = AF_INET;
-       p.prefixlen = MIN(IPV4_MAX_PREFIXLEN, stream_getc(stream));
-       stream_get(&p.prefix, stream, PSIZE(p.prefixlen));
-
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) {
-               api.nexthop_num = stream_getc(stream);
-               (void)stream_get_ipv4(stream);
-       }
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) {
-               api.ifindex_num = stream_getc(stream);
-               stream_getl(stream);
-       }
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE))
-               api.distance = stream_getc(stream);
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC))
-               api.metric = stream_getl(stream);
-
-       /*
-        * Avoid advertising a false default reachability. (A default
-        * route installed by IS-IS gets redistributed from zebra back
-        * into IS-IS causing us to start advertising default reachabity
-        * without this check)
-        */
-       if (p.prefixlen == 0 && api.type == ZEBRA_ROUTE_ISIS)
-               command = ZEBRA_IPV4_ROUTE_DELETE;
-
-       if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD)
-               isis_redist_add(api.type, p_generic, api.distance, api.metric);
+       if (CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ACTIVE))
+               isis_zebra_route_add_route(prefix, route_info);
        else
-               isis_redist_delete(api.type, p_generic);
-
-       return 0;
+               isis_zebra_route_del_route(prefix, route_info);
 }
 
-static int isis_zebra_read_ipv6(int command, struct zclient *zclient,
-                               zebra_size_t length, vrf_id_t vrf_id)
+static int isis_zebra_read(int command, struct zclient *zclient,
+                          zebra_size_t length, vrf_id_t vrf_id)
 {
-       struct stream *stream;
-       struct zapi_ipv6 api;
-       struct prefix_ipv6 p;
-       struct prefix src_p;
-       struct prefix *p_generic = (struct prefix *)&p;
-       struct in6_addr nexthop;
-       unsigned long ifindex __attribute__((unused));
-
-       stream = zclient->ibuf;
-       memset(&api, 0, sizeof(api));
-       memset(&p, 0, sizeof(struct prefix_ipv6));
-       memset(&nexthop, 0, sizeof(nexthop));
-       ifindex = 0;
-
-       api.type = stream_getc(stream);
-       api.instance = stream_getw(stream);
-       api.flags = stream_getl(stream);
-       api.message = stream_getc(stream);
-
-       p.family = AF_INET6;
-       p.prefixlen = stream_getc(stream);
-       stream_get(&p.prefix, stream, PSIZE(p.prefixlen));
-
-       memset(&src_p, 0, sizeof(struct prefix));
-       src_p.family = AF_INET6;
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) {
-               src_p.prefixlen = stream_getc(stream);
-               stream_get(&src_p.u.prefix6, stream, PSIZE(src_p.prefixlen));
-       }
+       struct zapi_route api;
 
-       if (src_p.prefixlen)
-               /* we completely ignore srcdest routes for now. */
-               return 0;
+       if (zapi_route_decode(zclient->ibuf, &api) < 0)
+               return -1;
 
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) {
-               api.nexthop_num = stream_getc(stream); /* this is always 1 */
-               stream_get(&nexthop, stream, sizeof(nexthop));
-       }
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) {
-               api.ifindex_num = stream_getc(stream);
-               ifindex = stream_getl(stream);
-       }
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE))
-               api.distance = stream_getc(stream);
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC))
-               api.metric = stream_getl(stream);
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG))
-               api.tag = stream_getl(stream);
+       /* we completely ignore srcdest routes for now. */
+       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
+               return 0;
 
        /*
         * Avoid advertising a false default reachability. (A default
@@ -638,13 +362,14 @@ static int isis_zebra_read_ipv6(int command, struct zclient *zclient,
         * into IS-IS causing us to start advertising default reachabity
         * without this check)
         */
-       if (p.prefixlen == 0 && api.type == ZEBRA_ROUTE_ISIS)
-               command = ZEBRA_IPV6_ROUTE_DELETE;
+       if (api.prefix.prefixlen == 0 && api.type == ZEBRA_ROUTE_ISIS)
+               command = ZEBRA_REDISTRIBUTE_ROUTE_DEL;
 
-       if (command == ZEBRA_REDISTRIBUTE_IPV6_ADD)
-               isis_redist_add(api.type, p_generic, api.distance, api.metric);
+       if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
+               isis_redist_add(api.type, &api.prefix, api.distance,
+                               api.metric);
        else
-               isis_redist_delete(api.type, p_generic);
+               isis_redist_delete(api.type, &api.prefix);
 
        return 0;
 }
@@ -692,10 +417,8 @@ void isis_zebra_init(struct thread_master *master)
        zclient->interface_address_add = isis_zebra_if_address_add;
        zclient->interface_address_delete = isis_zebra_if_address_del;
        zclient->interface_link_params = isis_zebra_link_params;
-       zclient->redistribute_route_ipv4_add = isis_zebra_read_ipv4;
-       zclient->redistribute_route_ipv4_del = isis_zebra_read_ipv4;
-       zclient->redistribute_route_ipv6_add = isis_zebra_read_ipv6;
-       zclient->redistribute_route_ipv6_del = isis_zebra_read_ipv6;
+       zclient->redistribute_route_add = isis_zebra_read;
+       zclient->redistribute_route_del = isis_zebra_read;
 
        return;
 }
index e654f8557c284d496ff187f0f470c33053920e25..bdc1d836db6bb89515589fa8e63ed7ceb08e3e76 100644 (file)
@@ -347,14 +347,14 @@ int area_net_title(struct vty *vty, const char *net_title)
                        "area address must be at least 8..20 octets long (%d)\n",
                        addr->addr_len);
                XFREE(MTYPE_ISIS_AREA_ADDR, addr);
-               return CMD_ERR_AMBIGUOUS;
+               return CMD_WARNING_CONFIG_FAILED;
        }
 
        if (addr->area_addr[addr->addr_len - 1] != 0) {
                vty_out(vty,
                        "nsel byte (last byte) in area address must be 0\n");
                XFREE(MTYPE_ISIS_AREA_ADDR, addr);
-               return CMD_ERR_AMBIGUOUS;
+               return CMD_WARNING_CONFIG_FAILED;
        }
 
        if (isis->sysid_set == 0) {
@@ -374,7 +374,7 @@ int area_net_title(struct vty *vty, const char *net_title)
                        vty_out(vty,
                                "System ID must not change when defining additional area addresses\n");
                        XFREE(MTYPE_ISIS_AREA_ADDR, addr);
-                       return CMD_ERR_AMBIGUOUS;
+                       return CMD_WARNING_CONFIG_FAILED;
                }
 
                /* now we see that we don't already have this address */
@@ -419,7 +419,7 @@ int area_clear_net_title(struct vty *vty, const char *net_title)
                vty_out(vty,
                        "Unsupported area address length %d, should be 8...20 \n",
                        addr.addr_len);
-               return CMD_ERR_AMBIGUOUS;
+               return CMD_WARNING_CONFIG_FAILED;
        }
 
        memcpy(addr.area_addr, buff, (int)addr.addr_len);
@@ -758,17 +758,18 @@ void print_debug(struct vty *vty, int flags, int onoff)
                vty_out(vty, "IS-IS LSP scheduling debugging is %s\n", onoffs);
 }
 
-DEFUN (show_debugging,
-       show_debugging_isis_cmd,
-       "show debugging isis",
-       SHOW_STR
-       "State of each debugging option\n"
-       ISIS_STR)
+DEFUN_NOSH (show_debugging,
+           show_debugging_isis_cmd,
+           "show debugging [isis]",
+           SHOW_STR
+           "State of each debugging option\n"
+           ISIS_STR)
 {
-       if (isis->debugs) {
-               vty_out(vty, "IS-IS:\n");
+       vty_out (vty, "IS-IS debugging status:\n");
+
+       if (isis->debugs)
                print_debug(vty, isis->debugs, 1);
-       }
+
        return CMD_SUCCESS;
 }
 
@@ -1259,8 +1260,8 @@ DEFUN (show_isis_spf_ietf,
                        if (area->spf_timer[level - 1]) {
                                struct timeval remain = thread_timer_remain(
                                        area->spf_timer[level - 1]);
-                               vty_out(vty, "Pending, due in %ld msec\n",
-                                       remain.tv_sec * 1000
+                               vty_out(vty, "Pending, due in %lld msec\n",
+                                       (long long)remain.tv_sec * 1000
                                                + remain.tv_usec / 1000);
                        } else {
                                vty_out(vty, "Not scheduled\n");
@@ -1404,7 +1405,7 @@ static int show_isis_database(struct vty *vty, const char *argv, int ui_level)
                                (u_char)strtol((char *)number, NULL, 16);
                        pos -= 4;
                        if (strncmp(pos, ".", 1) != 0)
-                               return CMD_ERR_AMBIGUOUS;
+                               return CMD_WARNING;
                }
                if (strncmp(pos, ".", 1) == 0) {
                        memcpy(number, ++pos, 2);
@@ -1569,16 +1570,16 @@ DEFUN (isis_topology,
        if (area->oldmetric) {
                vty_out(vty,
                        "Multi topology IS-IS can only be used with wide metrics\n");
-               return CMD_ERR_AMBIGUOUS;
+               return CMD_WARNING_CONFIG_FAILED;
        }
 
        if (mtid == (uint16_t)-1) {
                vty_out(vty, "Don't know topology '%s'\n", arg);
-               return CMD_ERR_AMBIGUOUS;
+               return CMD_WARNING_CONFIG_FAILED;
        }
        if (mtid == ISIS_MT_IPV4_UNICAST) {
                vty_out(vty, "Cannot configure IPv4 unicast topology\n");
-               return CMD_ERR_AMBIGUOUS;
+               return CMD_WARNING_CONFIG_FAILED;
        }
 
        area_set_mt_enabled(area, mtid, true);
@@ -1602,16 +1603,16 @@ DEFUN (no_isis_topology,
        if (area->oldmetric) {
                vty_out(vty,
                        "Multi topology IS-IS can only be used with wide metrics\n");
-               return CMD_ERR_AMBIGUOUS;
+               return CMD_WARNING_CONFIG_FAILED;
        }
 
        if (mtid == (uint16_t)-1) {
                vty_out(vty, "Don't know topology '%s'\n", arg);
-               return CMD_ERR_AMBIGUOUS;
+               return CMD_WARNING_CONFIG_FAILED;
        }
        if (mtid == ISIS_MT_IPV4_UNICAST) {
                vty_out(vty, "Cannot configure IPv4 unicast topology\n");
-               return CMD_ERR_AMBIGUOUS;
+               return CMD_WARNING_CONFIG_FAILED;
        }
 
        area_set_mt_enabled(area, mtid, false);
index da02854f5c4d678e89feb2b5bf52e5c2d925f2b8..36fe0b5937dd4dab5161f1c30ace3d9f537d92fd 100644 (file)
@@ -25,8 +25,6 @@
 
 #include "vty.h"
 
-#define ISISD_VERSION "0.0.7"
-
 #include "isisd/isis_constants.h"
 #include "isisd/isis_common.h"
 #include "isisd/isis_redist.h"
index 0e66a1636aa88354fd83db989b961856cf05aa4f..23edb5f24d9360772166ff9e92365fa592e69d06 100644 (file)
@@ -19,7 +19,7 @@
 #ifndef _CONTROL_H_
 #define        _CONTROL_H_
 
-#include "openbsd-queue.h"
+#include "queue.h"
 
 struct ctl_conn {
        TAILQ_ENTRY(ctl_conn)   entry;
index 43f1d36481767029d997a91d2c221f6b96a821b8..94077d16316be8b948d2a2881e4ab3fab01c0638 100644 (file)
@@ -21,7 +21,7 @@
 #ifndef _LDE_H_
 #define _LDE_H_
 
-#include "openbsd-queue.h"
+#include "queue.h"
 #include "openbsd-tree.h"
 #include "if.h"
 
index db92b936287f9caab164e9f288c3cc37d26aa3c2..be473063cdabc68d325c17fc3a6ead2122574db5 100644 (file)
@@ -684,13 +684,13 @@ DEFPY  (ldp_show_l2vpn_atom_vc,
        return (ldp_vty_show_atom_vc(vty, json));
 }
 
-DEFPY  (ldp_show_debugging_mpls_ldp,
-       ldp_show_debugging_mpls_ldp_cmd,
-       "show debugging mpls ldp",
-       "Show running system information\n"
-       "Debugging functions\n"
-       "MPLS information\n"
-       "Label Distribution Protocol\n")
+DEFUN_NOSH (ldp_show_debugging_mpls_ldp,
+           ldp_show_debugging_mpls_ldp_cmd,
+           "show debugging [mpls ldp]",
+           "Show running system information\n"
+           "Debugging functions\n"
+           "MPLS information\n"
+           "Label Distribution Protocol\n")
 {
        return (ldp_vty_show_debugging(vty));
 }
index ecc7db8f2ebb30ec6dffb87bd2f92e380f89e276..c50cc0fda2e2227306f0598bd33ef3ad37e0e43a 100644 (file)
@@ -396,19 +396,34 @@ static int
 ldp_zebra_read_route(int command, struct zclient *zclient, zebra_size_t length,
     vrf_id_t vrf_id)
 {
-       struct stream           *s;
-       u_char                   type;
-       u_char                   message_flags;
+       struct zapi_route        api;
+       struct zapi_nexthop     *api_nh;
        struct kroute            kr;
-       int                      nhnum = 0, nhlen;
-       size_t                   nhmark;
-       int                      add = 0;
+       int                      i, add = 0;
+
+       if (zapi_route_decode(zclient->ibuf, &api) < 0)
+               return -1;
+
+       /* we completely ignore srcdest routes for now. */
+       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
+               return (0);
 
        memset(&kr, 0, sizeof(kr));
-       s = zclient->ibuf;
+       kr.af = api.prefix.family;
+       switch (kr.af) {
+       case AF_INET:
+               kr.prefix.v4 = api.prefix.u.prefix4;
+               break;
+       case AF_INET6:
+               kr.prefix.v6 = api.prefix.u.prefix6;
+               break;
+       default:
+               break;
+       }
+       kr.prefixlen = api.prefix.prefixlen;
+       kr.priority = api.distance;
 
-       type = stream_getc(s);
-       switch (type) {
+       switch (api.type) {
        case ZEBRA_ROUTE_CONNECT:
                kr.flags |= F_CONNECTED;
                break;
@@ -419,84 +434,38 @@ ldp_zebra_read_route(int command, struct zclient *zclient, zebra_size_t length,
                break;
        }
 
-       stream_getl(s); /* flags, unused */
-       stream_getw(s); /* instance, unused */
-       message_flags = stream_getc(s);
-
-       switch (command) {
-       case ZEBRA_REDISTRIBUTE_IPV4_ADD:
-       case ZEBRA_REDISTRIBUTE_IPV4_DEL:
-               kr.af = AF_INET;
-               nhlen = sizeof(struct in_addr);
-               break;
-       case ZEBRA_REDISTRIBUTE_IPV6_ADD:
-       case ZEBRA_REDISTRIBUTE_IPV6_DEL:
-               kr.af = AF_INET6;
-               nhlen = sizeof(struct in6_addr);
-               break;
-       default:
-               fatalx("ldp_zebra_read_route: unknown command");
-       }
-       kr.prefixlen = stream_getc(s);
-       stream_get(&kr.prefix, s, PSIZE(kr.prefixlen));
-
        if (bad_addr(kr.af, &kr.prefix) ||
            (kr.af == AF_INET6 && IN6_IS_SCOPE_EMBED(&kr.prefix.v6)))
                return (0);
 
-       if (kr.af == AF_INET6 &&
-           CHECK_FLAG(message_flags, ZAPI_MESSAGE_SRCPFX)) {
-               uint8_t src_prefixlen;
-
-               src_prefixlen = stream_getc(s);
-
-               /* we completely ignore srcdest routes for now. */
-               if (src_prefixlen)
-                       return (0);
-       }
-
-       if (CHECK_FLAG(message_flags, ZAPI_MESSAGE_NEXTHOP)) {
-               nhnum = stream_getc(s);
-               nhmark = stream_get_getp(s);
-               stream_set_getp(s, nhmark + nhnum * (nhlen + 5));
-       }
-
-       if (CHECK_FLAG(message_flags, ZAPI_MESSAGE_DISTANCE))
-               kr.priority = stream_getc(s);
-       if (CHECK_FLAG(message_flags, ZAPI_MESSAGE_METRIC))
-               stream_getl(s); /* metric, not used */
-
-       if (CHECK_FLAG(message_flags, ZAPI_MESSAGE_NEXTHOP))
-               stream_set_getp(s, nhmark);
-
-       if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD ||
-           command == ZEBRA_REDISTRIBUTE_IPV6_ADD)
+       if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
                add = 1;
 
-       if (nhnum == 0)
+       if (api.nexthop_num == 0)
                debug_zebra_in("route %s %s/%d (%s)", (add) ? "add" : "delete",
                    log_addr(kr.af, &kr.prefix), kr.prefixlen,
-                   zebra_route_string(type));
+                   zebra_route_string(api.type));
 
        /* loop through all the nexthops */
-       for (; nhnum > 0; nhnum--) {
+       for (i = 0; i < api.nexthop_num; i++) {
+               api_nh = &api.nexthops[i];
+
                switch (kr.af) {
                case AF_INET:
-                       kr.nexthop.v4.s_addr = stream_get_ipv4(s);
+                       kr.nexthop.v4 = api_nh->gate.ipv4;
                        break;
                case AF_INET6:
-                       stream_get(&kr.nexthop.v6, s, sizeof(kr.nexthop.v6));
+                       kr.nexthop.v6 = api_nh->gate.ipv6;
                        break;
                default:
                        break;
                }
-               stream_getc(s); /* ifindex_num, unused. */
-               kr.ifindex = stream_getl(s);
+               kr.ifindex = api_nh->ifindex;;
 
                debug_zebra_in("route %s %s/%d nexthop %s ifindex %u (%s)",
                    (add) ? "add" : "delete", log_addr(kr.af, &kr.prefix),
                    kr.prefixlen, log_addr(kr.af, &kr.nexthop), kr.ifindex,
-                   zebra_route_string(type));
+                   zebra_route_string(api.type));
 
                if (add)
                        main_imsg_compose_lde(IMSG_NETWORK_ADD, 0, &kr,
@@ -553,10 +522,8 @@ ldp_zebra_init(struct thread_master *master)
        zclient->interface_down = ldp_interface_status_change;
        zclient->interface_address_add = ldp_interface_address_add;
        zclient->interface_address_delete = ldp_interface_address_delete;
-       zclient->redistribute_route_ipv4_add = ldp_zebra_read_route;
-       zclient->redistribute_route_ipv4_del = ldp_zebra_read_route;
-       zclient->redistribute_route_ipv6_add = ldp_zebra_read_route;
-       zclient->redistribute_route_ipv6_del = ldp_zebra_read_route;
+       zclient->redistribute_route_add = ldp_zebra_read_route;
+       zclient->redistribute_route_del = ldp_zebra_read_route;
        zclient->pw_status_update = ldp_zebra_read_pw_status_update;
 }
 
index 80af2b14e5da6accde082303f01eae3427835f10..0a586ec1c5b123671954ca019712d50e859bb0b3 100644 (file)
@@ -392,6 +392,8 @@ ldpd_shutdown(void)
        pid_t            pid;
        int              status;
 
+       frr_early_fini();
+
        /* close pipes */
        msgbuf_clear(&iev_ldpe->ibuf.w);
        close(iev_ldpe->ibuf.fd);
@@ -423,13 +425,9 @@ ldpd_shutdown(void)
 
        vrf_terminate();
        access_list_reset();
-       cmd_terminate();
-       vty_terminate();
        ldp_zebra_destroy();
-       zprivs_terminate(&ldpd_privs);
-       thread_master_free(master);
-       closezlog();
 
+       frr_fini();
        exit(0);
 }
 
index 31d0bc69b159b7c586a4ef8f6b3cfeafadb00546..5580ea5d676db10a160a7b0cf9dd60c735718ee7 100644 (file)
@@ -22,7 +22,7 @@
 #ifndef _LDPD_H_
 #define _LDPD_H_
 
-#include "openbsd-queue.h"
+#include "queue.h"
 #include "openbsd-tree.h"
 #include "imsg.h"
 #include "thread.h"
index 74f6b852b0cda4824e89c58f755fa397aebd3d7c..ccff1e803d354f890e528b6e72c1245fca668561 100644 (file)
@@ -21,7 +21,7 @@
 #ifndef _LDPE_H_
 #define _LDPE_H_
 
-#include "openbsd-queue.h"
+#include "queue.h"
 #include "openbsd-tree.h"
 #ifdef __OpenBSD__
 #include <net/pfkeyv2.h>
index 9421fadc0b1a70f87cfb26815b5537086eef7e29..24095de4f01168efcab556ef051cfa8b3a5bd19e 100644 (file)
@@ -42,6 +42,7 @@
 #include "command_graph.h"
 #include "qobj.h"
 #include "defaults.h"
+#include "libfrr.h"
 
 DEFINE_MTYPE(LIB, HOST, "Host config")
 DEFINE_MTYPE(LIB, STRVEC, "String vector")
@@ -376,21 +377,23 @@ void install_element(enum node_type ntype, struct cmd_element *cmd)
                return;
        }
 
-       cnode = vector_slot(cmdvec, ntype);
+       cnode = vector_lookup(cmdvec, ntype);
 
        if (cnode == NULL) {
                fprintf(stderr,
-                       "Command node %d doesn't exist, please check it\n",
-                       ntype);
-               fprintf(stderr,
-                       "Have you called install_node before this install_element?\n");
+                       "%s[%s]:\n"
+                       "\tnode %d (%s) does not exist.\n"
+                       "\tplease call install_node() before install_element()\n",
+                       cmd->name, cmd->string, ntype, node_names[ntype]);
                exit(EXIT_FAILURE);
        }
 
        if (hash_lookup(cnode->cmd_hash, cmd) != NULL) {
                fprintf(stderr,
-                       "Multiple command installs to node %d of command:\n%s\n",
-                       ntype, cmd->string);
+                       "%s[%s]:\n"
+                       "\tnode %d (%s) already has this command installed.\n"
+                       "\tduplicate install_element call?\n",
+                       cmd->name, cmd->string, ntype, node_names[ntype]);
                return;
        }
 
@@ -423,21 +426,23 @@ void uninstall_element(enum node_type ntype, struct cmd_element *cmd)
                return;
        }
 
-       cnode = vector_slot(cmdvec, ntype);
+       cnode = vector_lookup(cmdvec, ntype);
 
        if (cnode == NULL) {
                fprintf(stderr,
-                       "Command node %d doesn't exist, please check it\n",
-                       ntype);
-               fprintf(stderr,
-                       "Have you called install_node before this install_element?\n");
+                       "%s[%s]:\n"
+                       "\tnode %d (%s) does not exist.\n"
+                       "\tplease call install_node() before uninstall_element()\n",
+                       cmd->name, cmd->string, ntype, node_names[ntype]);
                exit(EXIT_FAILURE);
        }
 
        if (hash_release(cnode->cmd_hash, cmd) == NULL) {
                fprintf(stderr,
-                       "Trying to uninstall non-installed command (node %d):\n%s\n",
-                       ntype, cmd->string);
+                       "%s[%s]:\n"
+                       "\tnode %d (%s) does not have this command installed.\n"
+                       "\tduplicate uninstall_element call?\n",
+                       cmd->name, cmd->string, ntype, node_names[ntype]);
                return;
        }
 
@@ -572,6 +577,9 @@ static int config_write_host(struct vty *vty)
        else if (!host.motd)
                vty_out(vty, "no banner motd\n");
 
+       if (debug_memstats_at_exit)
+               vty_out(vty, "!\ndebug memstats-at-exit\n");
+
        return 1;
 }
 
@@ -2417,6 +2425,17 @@ DEFUN (no_config_log_timestamp_precision,
        return CMD_SUCCESS;
 }
 
+DEFUN (debug_memstats,
+       debug_memstats_cmd,
+       "[no] debug memstats-at-exit",
+       NO_STR
+       DEBUG_STR
+       "Print memory type statistics at exit\n")
+{
+       debug_memstats_at_exit = !!strcmp(argv[0]->text, "no");
+       return CMD_SUCCESS;
+}
+
 int cmd_banner_motd_file(const char *file)
 {
        int success = CMD_SUCCESS;
@@ -2589,6 +2608,7 @@ void cmd_init(int terminal)
        /* Each node's basic commands. */
        install_element(VIEW_NODE, &show_version_cmd);
        install_element(ENABLE_NODE, &show_startup_config_cmd);
+       install_element(ENABLE_NODE, &debug_memstats_cmd);
 
        if (terminal) {
                install_element(VIEW_NODE, &config_list_cmd);
@@ -2624,6 +2644,7 @@ void cmd_init(int terminal)
        install_element(CONFIG_NODE, &domainname_cmd);
        install_element(CONFIG_NODE, &no_domainname_cmd);
        install_element(CONFIG_NODE, &frr_version_defaults_cmd);
+       install_element(CONFIG_NODE, &debug_memstats_cmd);
 
        if (terminal > 0) {
                install_element(CONFIG_NODE, &password_cmd);
index f07448d716c4783cfbeb3b7a3189100209a6f0b0..ad3ec2492e6e96b574da01244478d4b25018f330 100644 (file)
@@ -46,8 +46,9 @@ DEFINE_MTYPE_STATIC(LIB, CMD_MATCHSTACK, "Command Match Stack")
 static int add_nexthops(struct list *, struct graph_node *,
                        struct graph_node **, size_t);
 
-static struct list *command_match_r(struct graph_node *, vector, unsigned int,
-                                   struct graph_node **);
+static enum matcher_rv command_match_r(struct graph_node *, vector,
+                                      unsigned int, struct graph_node **,
+                                      struct list **);
 
 static int score_precedence(enum cmd_token_type);
 
@@ -80,14 +81,12 @@ static enum match_type match_variable(struct cmd_token *, const char *);
 
 static enum match_type match_mac(const char *, bool);
 
-/* matching functions */
-static enum matcher_rv matcher_rv;
-
 enum matcher_rv command_match(struct graph *cmdgraph, vector vline,
                              struct list **argv, const struct cmd_element **el)
 {
        struct graph_node *stack[MAXDEPTH];
-       matcher_rv = MATCHER_NO_MATCH;
+       enum matcher_rv status;
+       *argv = NULL;
 
        // prepend a dummy token to match that pesky start node
        vector vvline = vector_init(vline->alloced + 1);
@@ -97,9 +96,8 @@ enum matcher_rv command_match(struct graph *cmdgraph, vector vline,
        vvline->active = vline->active + 1;
 
        struct graph_node *start = vector_slot(cmdgraph->nodes, 0);
-       if ((*argv = command_match_r(start, vvline, 0,
-                                    stack))) // successful match
-       {
+       status = command_match_r(start, vvline, 0, stack, argv);
+       if (status == MATCHER_OK) { // successful match
                struct listnode *head = listhead(*argv);
                struct listnode *tail = listtail(*argv);
 
@@ -115,6 +113,9 @@ enum matcher_rv command_match(struct graph *cmdgraph, vector vline,
                // input, with each cmd_token->arg holding the corresponding
                // input
                assert(*el);
+       } else if (*argv) {
+               del_arglist(*argv);
+               *argv = NULL;
        }
 
        if (!*el) {
@@ -129,7 +130,7 @@ enum matcher_rv command_match(struct graph *cmdgraph, vector vline,
        // free vector
        vector_free(vvline);
 
-       return matcher_rv;
+       return status;
 }
 
 /**
@@ -183,11 +184,15 @@ enum matcher_rv command_match(struct graph *cmdgraph, vector vline,
  *
  * If no match was found, the return value is NULL.
  */
-static struct list *command_match_r(struct graph_node *start, vector vline,
-                                   unsigned int n, struct graph_node **stack)
+static enum matcher_rv command_match_r(struct graph_node *start, vector vline,
+                                      unsigned int n,
+                                      struct graph_node **stack,
+                                      struct list **currbest)
 {
        assert(n < vector_active(vline));
 
+       enum matcher_rv status = MATCHER_NO_MATCH;
+
        // get the minimum match level that can count as a full match
        struct cmd_token *token = start->data;
        enum match_type minmatch = min_match_level(token->type);
@@ -196,11 +201,11 @@ static struct list *command_match_r(struct graph_node *start, vector vline,
         * this disallows matching the same one more than once if there is a
         * circle in the graph (used for keyword arguments) */
        if (n == MAXDEPTH)
-               return NULL;
+               return MATCHER_NO_MATCH;
        if (!token->allowrepeat)
                for (size_t s = 0; s < n; s++)
                        if (stack[s] == start)
-                               return NULL;
+                               return MATCHER_NO_MATCH;
 
        // get the current operating input token
        char *input_token = vector_slot(vline, n);
@@ -231,7 +236,7 @@ static struct list *command_match_r(struct graph_node *start, vector vline,
 
        // if we don't match this node, die
        if (match_token(token, input_token) < minmatch)
-               return NULL;
+               return MATCHER_NO_MATCH;
 
        stack[n] = start;
 
@@ -244,86 +249,92 @@ static struct list *command_match_r(struct graph_node *start, vector vline,
        add_nexthops(next, start, NULL, 0);
 
        // determine the best match
-       int ambiguous = 0;
-       struct list *currbest = NULL;
        for (ALL_LIST_ELEMENTS_RO(next, ln, gn)) {
                // if we've matched all input we're looking for END_TKN
                if (n + 1 == vector_active(vline)) {
                        struct cmd_token *tok = gn->data;
                        if (tok->type == END_TKN) {
-                               if (currbest) // there is more than one END_TKN
-                                             // in the follow set
-                               {
-                                       ambiguous = 1;
+                               // if more than one END_TKN in the follow set
+                               if (*currbest) {
+                                       status = MATCHER_AMBIGUOUS;
                                        break;
+                               } else {
+                                       status = MATCHER_OK;
                                }
-                               currbest = list_new();
+                               *currbest = list_new();
                                // node should have one child node with the
                                // element
                                struct graph_node *leaf =
                                        vector_slot(gn->to, 0);
                                // last node in the list will hold the
-                               // cmd_element;
-                               // this is important because list_delete()
-                               // expects
-                               // that all nodes have the same data type, so
-                               // when
-                               // deleting this list the last node must be
-                               // manually deleted
+                               // cmd_element; this is important because
+                               // list_delete() expects that all nodes have
+                               // the same data type, so when deleting this
+                               // list the last node must be manually deleted
                                struct cmd_element *el = leaf->data;
-                               listnode_add(currbest, el);
-                               currbest->del =
+                               listnode_add(*currbest, el);
+                               (*currbest)->del =
                                        (void (*)(void *)) & cmd_token_del;
                                // do not break immediately; continue walking
-                               // through the follow set
-                               // to ensure that there is exactly one END_TKN
+                               // through the follow set to ensure that there
+                               // is exactly one END_TKN
                        }
                        continue;
                }
 
                // else recurse on candidate child node
-               struct list *result = command_match_r(gn, vline, n + 1, stack);
+               struct list *result = NULL;
+               enum matcher_rv rstat =
+                       command_match_r(gn, vline, n + 1, stack, &result);
 
                // save the best match
-               if (result && currbest) {
+               if (result && *currbest) {
                        // pick the best of two matches
                        struct list *newbest =
-                               disambiguate(currbest, result, vline, n + 1);
-                       // set ambiguity flag
-                       ambiguous =
-                               !newbest || (ambiguous && newbest == currbest);
+                               disambiguate(*currbest, result, vline, n + 1);
+
+                       // current best and result are ambiguous
+                       if (!newbest)
+                               status = MATCHER_AMBIGUOUS;
+                       // current best is still the best, but ambiguous
+                       else if (newbest == *currbest
+                                && status == MATCHER_AMBIGUOUS)
+                               status = MATCHER_AMBIGUOUS;
+                       // result is better, but also ambiguous
+                       else if (newbest == result
+                                && rstat == MATCHER_AMBIGUOUS)
+                               status = MATCHER_AMBIGUOUS;
+                       // one or the other is superior and not ambiguous
+                       else
+                               status = MATCHER_OK;
+
                        // delete the unnecessary result
                        struct list *todelete =
-                               ((newbest && newbest == result) ? currbest
+                               ((newbest && newbest == result) ? *currbest
                                                                : result);
                        del_arglist(todelete);
 
-                       currbest = newbest ? newbest : currbest;
-               } else if (result)
-                       currbest = result;
-       }
-
-       if (currbest) {
-               if (ambiguous) {
-                       del_arglist(currbest);
-                       currbest = NULL;
-                       matcher_rv = MATCHER_AMBIGUOUS;
-               } else {
-                       // copy token, set arg and prepend to currbest
-                       struct cmd_token *token = start->data;
-                       struct cmd_token *copy = cmd_token_dup(token);
-                       copy->arg = XSTRDUP(MTYPE_CMD_ARG, input_token);
-                       listnode_add_before(currbest, currbest->head, copy);
-                       matcher_rv = MATCHER_OK;
+                       *currbest = newbest ? newbest : *currbest;
+               } else if (result) {
+                       status = rstat;
+                       *currbest = result;
+               } else if (!*currbest) {
+                       status = MAX(rstat, status);
                }
-       } else if (n + 1 == vector_active(vline)
-                  && matcher_rv == MATCHER_NO_MATCH)
-               matcher_rv = MATCHER_INCOMPLETE;
+       }
+       if (*currbest) {
+               // copy token, set arg and prepend to currbest
+               struct cmd_token *token = start->data;
+               struct cmd_token *copy = cmd_token_dup(token);
+               copy->arg = XSTRDUP(MTYPE_CMD_ARG, input_token);
+               listnode_add_before(*currbest, (*currbest)->head, copy);
+       } else if (n + 1 == vector_active(vline) && status == MATCHER_NO_MATCH)
+               status = MATCHER_INCOMPLETE;
 
        // cleanup
        list_delete(next);
 
-       return currbest;
+       return status;
 }
 
 static void stack_del(void *val)
@@ -432,12 +443,12 @@ enum matcher_rv command_complete(struct graph *graph, vector vline,
         * next     = set of all nodes reachable from all nodes in `matched`
         */
 
-       matcher_rv = idx == vector_active(vline) && next->count
-                            ? MATCHER_OK
-                            : MATCHER_NO_MATCH;
+       enum matcher_rv mrv = idx == vector_active(vline) && next->count
+                                     ? MATCHER_OK
+                                     : MATCHER_NO_MATCH;
 
        *completions = NULL;
-       if (!MATCHER_ERROR(matcher_rv)) {
+       if (!MATCHER_ERROR(mrv)) {
                // extract cmd_token into list
                *completions = list_new();
                for (ALL_LIST_ELEMENTS_RO(next, node, gstack)) {
@@ -448,7 +459,7 @@ enum matcher_rv command_complete(struct graph *graph, vector vline,
        list_delete(current);
        list_delete(next);
 
-       return matcher_rv;
+       return mrv;
 }
 
 /**
diff --git a/lib/compiler.h b/lib/compiler.h
new file mode 100644 (file)
index 0000000..49a2f2a
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2015-2017  David Lamparter, for NetDEF, Inc.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _FRR_COMPILER_H
+#define _FRR_COMPILER_H
+
+/* function attributes, use like
+ *   void prototype(void) __attribute__((_CONSTRUCTOR(100)));
+ */
+#if defined(__clang__)
+# if __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 5)
+#  define _RET_NONNULL    , returns_nonnull
+# endif
+# define _CONSTRUCTOR(x)  constructor(x)
+#elif defined(__GNUC__)
+# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
+#  define _RET_NONNULL    , returns_nonnull
+# endif
+# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)
+#  define _CONSTRUCTOR(x) constructor(x)
+#  define _DESTRUCTOR(x)  destructor(x)
+#  define _ALLOC_SIZE(x)  alloc_size(x)
+# endif
+#endif
+
+#ifdef __sun
+/* Solaris doesn't do constructor priorities due to linker restrictions */
+# undef _CONSTRUCTOR
+# undef _DESTRUCTOR
+#endif
+
+/* fallback versions */
+#ifndef _RET_NONNULL
+# define _RET_NONNULL
+#endif
+#ifndef _CONSTRUCTOR
+# define _CONSTRUCTOR(x) constructor
+#endif
+#ifndef _DESTRUCTOR
+# define _DESTRUCTOR(x) destructor
+#endif
+#ifndef _ALLOC_SIZE
+# define _ALLOC_SIZE(x)
+#endif
+
+/*
+ * for warnings on macros, put in the macro content like this:
+ *   #define MACRO BLA CPP_WARN("MACRO has been deprecated")
+ */
+#define CPP_STR(X) #X
+
+#if defined(__ICC)
+#define CPP_NOTICE(text) _Pragma(CPP_STR(message __FILE__ ": " text))
+#define CPP_WARN(text) CPP_NOTICE(text)
+
+#elif (defined(__GNUC__)                                                       \
+       && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)))           \
+       || (defined(__clang__)                                                 \
+           && (__clang_major__ >= 4                                           \
+               || (__clang_major__ == 3 && __clang_minor__ >= 5)))
+#define CPP_WARN(text) _Pragma(CPP_STR(GCC warning text))
+#define CPP_NOTICE(text) _Pragma(CPP_STR(message text))
+
+#else
+#define CPP_WARN(text)
+#endif
+
+#endif /* _FRR_COMPILER_H */
diff --git a/lib/freebsd-queue.h b/lib/freebsd-queue.h
new file mode 100644 (file)
index 0000000..d198f56
--- /dev/null
@@ -0,0 +1,679 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)queue.h     8.5 (Berkeley) 8/20/94
+ * $FreeBSD$
+ */
+
+#ifndef _SYS_QUEUE_H_
+#define        _SYS_QUEUE_H_
+
+/*
+ * This file defines four types of data structures: singly-linked lists,
+ * singly-linked tail queues, lists and tail queues.
+ *
+ * A singly-linked list is headed by a single forward pointer. The elements
+ * are singly linked for minimum space and pointer manipulation overhead at
+ * the expense of O(n) removal for arbitrary elements. New elements can be
+ * added to the list after an existing element or at the head of the list.
+ * Elements being removed from the head of the list should use the explicit
+ * macro for this purpose for optimum efficiency. A singly-linked list may
+ * only be traversed in the forward direction.  Singly-linked lists are ideal
+ * for applications with large datasets and few or no removals or for
+ * implementing a LIFO queue.
+ *
+ * A singly-linked tail queue is headed by a pair of pointers, one to the
+ * head of the list and the other to the tail of the list. The elements are
+ * singly linked for minimum space and pointer manipulation overhead at the
+ * expense of O(n) removal for arbitrary elements. New elements can be added
+ * to the list after an existing element, at the head of the list, or at the
+ * end of the list. Elements being removed from the head of the tail queue
+ * should use the explicit macro for this purpose for optimum efficiency.
+ * A singly-linked tail queue may only be traversed in the forward direction.
+ * Singly-linked tail queues are ideal for applications with large datasets
+ * and few or no removals or for implementing a FIFO queue.
+ *
+ * A list is headed by a single forward pointer (or an array of forward
+ * pointers for a hash table header). The elements are doubly linked
+ * so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before
+ * or after an existing element or at the head of the list. A list
+ * may only be traversed in the forward direction.
+ *
+ * A tail queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or
+ * after an existing element, at the head of the list, or at the end of
+ * the list. A tail queue may be traversed in either direction.
+ *
+ * For details on the use of these macros, see the queue(3) manual page.
+ *
+ *
+ *                             SLIST   LIST    STAILQ  TAILQ
+ * _HEAD                       +       +       +       +
+ * _HEAD_INITIALIZER           +       +       +       +
+ * _ENTRY                      +       +       +       +
+ * _INIT                       +       +       +       +
+ * _EMPTY                      +       +       +       +
+ * _FIRST                      +       +       +       +
+ * _NEXT                       +       +       +       +
+ * _PREV                       -       -       -       +
+ * _LAST                       -       -       +       +
+ * _FOREACH                    +       +       +       +
+ * _FOREACH_SAFE               +       +       +       +
+ * _FOREACH_REVERSE            -       -       -       +
+ * _FOREACH_REVERSE_SAFE       -       -       -       +
+ * _INSERT_HEAD                        +       +       +       +
+ * _INSERT_BEFORE              -       +       -       +
+ * _INSERT_AFTER               +       +       +       +
+ * _INSERT_TAIL                        -       -       +       +
+ * _CONCAT                     -       -       +       +
+ * _REMOVE_AFTER               +       -       +       -
+ * _REMOVE_HEAD                        +       -       +       -
+ * _REMOVE                     +       +       +       +
+ * _SWAP                       +       +       +       +
+ *
+ */
+#ifdef QUEUE_MACRO_DEBUG
+/* Store the last 2 places the queue element or head was altered */
+struct qm_trace {
+       char *lastfile;
+       int lastline;
+       char *prevfile;
+       int prevline;
+};
+
+#define        TRACEBUF        struct qm_trace trace;
+#define        TRASHIT(x)      do {(x) = (void *)-1;} while (0)
+#define        QMD_SAVELINK(name, link)        void **name = (void *)&(link)
+
+#define QMD_TRACE_HEAD(head)                                                   \
+       do {                                                                   \
+               (head)->trace.prevline = (head)->trace.lastline;               \
+               (head)->trace.prevfile = (head)->trace.lastfile;               \
+               (head)->trace.lastline = __LINE__;                             \
+               (head)->trace.lastfile = __FILE__;                             \
+       } while (0)
+
+#define QMD_TRACE_ELEM(elem)                                                   \
+       do {                                                                   \
+               (elem)->trace.prevline = (elem)->trace.lastline;               \
+               (elem)->trace.prevfile = (elem)->trace.lastfile;               \
+               (elem)->trace.lastline = __LINE__;                             \
+               (elem)->trace.lastfile = __FILE__;                             \
+       } while (0)
+
+#else
+#define        QMD_TRACE_ELEM(elem)
+#define        QMD_TRACE_HEAD(head)
+#define        QMD_SAVELINK(name, link)
+#define        TRACEBUF
+#define        TRASHIT(x)
+#endif /* QUEUE_MACRO_DEBUG */
+
+/*
+ * Singly-linked List declarations.
+ */
+#define SLIST_HEAD(name, type)                                                 \
+       struct name {                                                          \
+               struct type *slh_first; /* first element */                    \
+       }
+
+#define SLIST_HEAD_INITIALIZER(head)                                           \
+       {                                                                      \
+               NULL                                                           \
+       }
+
+#define SLIST_ENTRY(type)                                                      \
+       struct {                                                               \
+               struct type *sle_next; /* next element */                      \
+       }
+
+/*
+ * Singly-linked List functions.
+ */
+#define        SLIST_EMPTY(head)       ((head)->slh_first == NULL)
+
+#define        SLIST_FIRST(head)       ((head)->slh_first)
+
+#define SLIST_FOREACH(var, head, field)                                        \
+       for ((var) = SLIST_FIRST((head)); (var);                               \
+            (var) = SLIST_NEXT((var), field))
+
+#define SLIST_FOREACH_SAFE(var, head, field, tvar)                             \
+       for ((var) = SLIST_FIRST((head));                                      \
+            (var) && ((tvar) = SLIST_NEXT((var), field), 1); (var) = (tvar))
+
+#define SLIST_FOREACH_PREVPTR(var, varp, head, field)                          \
+       for ((varp) = &SLIST_FIRST((head)); ((var) = *(varp)) != NULL;         \
+            (varp) = &SLIST_NEXT((var), field))
+
+#define SLIST_INIT(head)                                                       \
+       do {                                                                   \
+               SLIST_FIRST((head)) = NULL;                                    \
+       } while (0)
+
+#define SLIST_INSERT_AFTER(slistelm, elm, field)                               \
+       do {                                                                   \
+               SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field);      \
+               SLIST_NEXT((slistelm), field) = (elm);                         \
+       } while (0)
+
+#define SLIST_INSERT_HEAD(head, elm, field)                                    \
+       do {                                                                   \
+               SLIST_NEXT((elm), field) = SLIST_FIRST((head));                \
+               SLIST_FIRST((head)) = (elm);                                   \
+       } while (0)
+
+#define        SLIST_NEXT(elm, field)  ((elm)->field.sle_next)
+
+#define SLIST_REMOVE(head, elm, type, field)                                   \
+       do {                                                                   \
+               QMD_SAVELINK(oldnext, (elm)->field.sle_next);                  \
+               if (SLIST_FIRST((head)) == (elm)) {                            \
+                       SLIST_REMOVE_HEAD((head), field);                      \
+               } else {                                                       \
+                       struct type *curelm = SLIST_FIRST((head));             \
+                       while (SLIST_NEXT(curelm, field) != (elm))             \
+                               curelm = SLIST_NEXT(curelm, field);            \
+                       SLIST_REMOVE_AFTER(curelm, field);                     \
+               }                                                              \
+               TRASHIT(*oldnext);                                             \
+       } while (0)
+
+#define SLIST_REMOVE_AFTER(elm, field)                                         \
+       do {                                                                   \
+               SLIST_NEXT(elm, field) =                                       \
+                       SLIST_NEXT(SLIST_NEXT(elm, field), field);             \
+       } while (0)
+
+#define SLIST_REMOVE_HEAD(head, field)                                         \
+       do {                                                                   \
+               SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field);  \
+       } while (0)
+
+#define SLIST_SWAP(head1, head2, type)                                         \
+       do {                                                                   \
+               struct type *swap_first = SLIST_FIRST(head1);                  \
+               SLIST_FIRST(head1) = SLIST_FIRST(head2);                       \
+               SLIST_FIRST(head2) = swap_first;                               \
+       } while (0)
+
+/*
+ * Singly-linked Tail queue declarations.
+ */
+#define STAILQ_HEAD(name, type)                                                \
+       struct name {                                                          \
+               struct type *stqh_first; /* first element */                   \
+               struct type **stqh_last; /* addr of last next element */       \
+       }
+
+#define STAILQ_HEAD_INITIALIZER(head)                                          \
+       {                                                                      \
+               NULL, &(head).stqh_first                                       \
+       }
+
+#define STAILQ_ENTRY(type)                                                     \
+       struct {                                                               \
+               struct type *stqe_next; /* next element */                     \
+       }
+
+/*
+ * Singly-linked Tail queue functions.
+ */
+#define STAILQ_CONCAT(head1, head2)                                            \
+       do {                                                                   \
+               if (!STAILQ_EMPTY((head2))) {                                  \
+                       *(head1)->stqh_last = (head2)->stqh_first;             \
+                       (head1)->stqh_last = (head2)->stqh_last;               \
+                       STAILQ_INIT((head2));                                  \
+               }                                                              \
+       } while (0)
+
+#define        STAILQ_EMPTY(head)      ((head)->stqh_first == NULL)
+
+#define        STAILQ_FIRST(head)      ((head)->stqh_first)
+
+#define STAILQ_FOREACH(var, head, field)                                       \
+       for ((var) = STAILQ_FIRST((head)); (var);                              \
+            (var) = STAILQ_NEXT((var), field))
+
+
+#define STAILQ_FOREACH_SAFE(var, head, field, tvar)                            \
+       for ((var) = STAILQ_FIRST((head));                                     \
+            (var) && ((tvar) = STAILQ_NEXT((var), field), 1); (var) = (tvar))
+
+#define STAILQ_INIT(head)                                                      \
+       do {                                                                   \
+               STAILQ_FIRST((head)) = NULL;                                   \
+               (head)->stqh_last = &STAILQ_FIRST((head));                     \
+       } while (0)
+
+#define STAILQ_INSERT_AFTER(head, tqelm, elm, field)                           \
+       do {                                                                   \
+               if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field))  \
+                   == NULL)                                                   \
+                       (head)->stqh_last = &STAILQ_NEXT((elm), field);        \
+               STAILQ_NEXT((tqelm), field) = (elm);                           \
+       } while (0)
+
+#define STAILQ_INSERT_HEAD(head, elm, field)                                   \
+       do {                                                                   \
+               if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head)))         \
+                   == NULL)                                                   \
+                       (head)->stqh_last = &STAILQ_NEXT((elm), field);        \
+               STAILQ_FIRST((head)) = (elm);                                  \
+       } while (0)
+
+#define STAILQ_INSERT_TAIL(head, elm, field)                                   \
+       do {                                                                   \
+               STAILQ_NEXT((elm), field) = NULL;                              \
+               *(head)->stqh_last = (elm);                                    \
+               (head)->stqh_last = &STAILQ_NEXT((elm), field);                \
+       } while (0)
+
+#define STAILQ_LAST(head, type, field)                                         \
+       (STAILQ_EMPTY((head))                                                  \
+                ? NULL                                                        \
+                : ((struct type *)(void *)((char *)((head)->stqh_last)        \
+                                           - offsetof(struct type,            \
+                                                        field))))
+
+#define        STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
+
+#define STAILQ_REMOVE(head, elm, type, field)                                  \
+       do {                                                                   \
+               QMD_SAVELINK(oldnext, (elm)->field.stqe_next);                 \
+               if (STAILQ_FIRST((head)) == (elm)) {                           \
+                       STAILQ_REMOVE_HEAD((head), field);                     \
+               } else {                                                       \
+                       struct type *curelm = STAILQ_FIRST((head));            \
+                       while (STAILQ_NEXT(curelm, field) != (elm))            \
+                               curelm = STAILQ_NEXT(curelm, field);           \
+                       STAILQ_REMOVE_AFTER(head, curelm, field);              \
+               }                                                              \
+               TRASHIT(*oldnext);                                             \
+       } while (0)
+
+#define STAILQ_REMOVE_AFTER(head, elm, field)                                  \
+       do {                                                                   \
+               if ((STAILQ_NEXT(elm, field) =                                 \
+                            STAILQ_NEXT(STAILQ_NEXT(elm, field), field))      \
+                   == NULL)                                                   \
+                       (head)->stqh_last = &STAILQ_NEXT((elm), field);        \
+       } while (0)
+
+#define STAILQ_REMOVE_HEAD(head, field)                                        \
+       do {                                                                   \
+               if ((STAILQ_FIRST((head)) =                                    \
+                            STAILQ_NEXT(STAILQ_FIRST((head)), field))         \
+                   == NULL)                                                   \
+                       (head)->stqh_last = &STAILQ_FIRST((head));             \
+       } while (0)
+
+#define STAILQ_SWAP(head1, head2, type)                                        \
+       do {                                                                   \
+               struct type *swap_first = STAILQ_FIRST(head1);                 \
+               struct type **swap_last = (head1)->stqh_last;                  \
+               STAILQ_FIRST(head1) = STAILQ_FIRST(head2);                     \
+               (head1)->stqh_last = (head2)->stqh_last;                       \
+               STAILQ_FIRST(head2) = swap_first;                              \
+               (head2)->stqh_last = swap_last;                                \
+               if (STAILQ_EMPTY(head1))                                       \
+                       (head1)->stqh_last = &STAILQ_FIRST(head1);             \
+               if (STAILQ_EMPTY(head2))                                       \
+                       (head2)->stqh_last = &STAILQ_FIRST(head2);             \
+       } while (0)
+
+
+/*
+ * List declarations.
+ */
+#define LIST_HEAD(name, type)                                                  \
+       struct name {                                                          \
+               struct type *lh_first; /* first element */                     \
+       }
+
+#define LIST_HEAD_INITIALIZER(head)                                            \
+       {                                                                      \
+               NULL                                                           \
+       }
+
+#define LIST_ENTRY(type)                                                       \
+       struct {                                                               \
+               struct type *le_next;  /* next element */                      \
+               struct type **le_prev; /* address of previous next element */  \
+       }
+
+/*
+ * List functions.
+ */
+
+#if (defined(_KERNEL) && defined(INVARIANTS))
+#define QMD_LIST_CHECK_HEAD(head, field)                                       \
+       do {                                                                   \
+               if (LIST_FIRST((head)) != NULL                                 \
+                   && LIST_FIRST((head))->field.le_prev                       \
+                              != &LIST_FIRST((head)))                         \
+                       panic("Bad list head %p first->prev != head", (head)); \
+       } while (0)
+
+#define QMD_LIST_CHECK_NEXT(elm, field)                                        \
+       do {                                                                   \
+               if (LIST_NEXT((elm), field) != NULL                            \
+                   && LIST_NEXT((elm), field)->field.le_prev                  \
+                              != &((elm)->field.le_next))                     \
+                       panic("Bad link elm %p next->prev != elm", (elm));     \
+       } while (0)
+
+#define QMD_LIST_CHECK_PREV(elm, field)                                        \
+       do {                                                                   \
+               if (*(elm)->field.le_prev != (elm))                            \
+                       panic("Bad link elm %p prev->next != elm", (elm));     \
+       } while (0)
+#else
+#define        QMD_LIST_CHECK_HEAD(head, field)
+#define        QMD_LIST_CHECK_NEXT(elm, field)
+#define        QMD_LIST_CHECK_PREV(elm, field)
+#endif /* (_KERNEL && INVARIANTS) */
+
+#define        LIST_EMPTY(head)        ((head)->lh_first == NULL)
+
+#define        LIST_FIRST(head)        ((head)->lh_first)
+
+#define LIST_FOREACH(var, head, field)                                         \
+       for ((var) = LIST_FIRST((head)); (var); (var) = LIST_NEXT((var), field))
+
+#define LIST_FOREACH_SAFE(var, head, field, tvar)                              \
+       for ((var) = LIST_FIRST((head));                                       \
+            (var) && ((tvar) = LIST_NEXT((var), field), 1); (var) = (tvar))
+
+#define LIST_INIT(head)                                                        \
+       do {                                                                   \
+               LIST_FIRST((head)) = NULL;                                     \
+       } while (0)
+
+#define LIST_INSERT_AFTER(listelm, elm, field)                                 \
+       do {                                                                   \
+               QMD_LIST_CHECK_NEXT(listelm, field);                           \
+               if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field))    \
+                   != NULL)                                                   \
+                       LIST_NEXT((listelm), field)->field.le_prev =           \
+                               &LIST_NEXT((elm), field);                      \
+               LIST_NEXT((listelm), field) = (elm);                           \
+               (elm)->field.le_prev = &LIST_NEXT((listelm), field);           \
+       } while (0)
+
+#define LIST_INSERT_BEFORE(listelm, elm, field)                                \
+       do {                                                                   \
+               QMD_LIST_CHECK_PREV(listelm, field);                           \
+               (elm)->field.le_prev = (listelm)->field.le_prev;               \
+               LIST_NEXT((elm), field) = (listelm);                           \
+               *(listelm)->field.le_prev = (elm);                             \
+               (listelm)->field.le_prev = &LIST_NEXT((elm), field);           \
+       } while (0)
+
+#define LIST_INSERT_HEAD(head, elm, field)                                     \
+       do {                                                                   \
+               QMD_LIST_CHECK_HEAD((head), field);                            \
+               if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL)    \
+                       LIST_FIRST((head))->field.le_prev =                    \
+                               &LIST_NEXT((elm), field);                      \
+               LIST_FIRST((head)) = (elm);                                    \
+               (elm)->field.le_prev = &LIST_FIRST((head));                    \
+       } while (0)
+
+#define        LIST_NEXT(elm, field)   ((elm)->field.le_next)
+
+#define LIST_REMOVE(elm, field)                                                \
+       do {                                                                   \
+               QMD_SAVELINK(oldnext, (elm)->field.le_next);                   \
+               QMD_SAVELINK(oldprev, (elm)->field.le_prev);                   \
+               QMD_LIST_CHECK_NEXT(elm, field);                               \
+               QMD_LIST_CHECK_PREV(elm, field);                               \
+               if (LIST_NEXT((elm), field) != NULL)                           \
+                       LIST_NEXT((elm), field)->field.le_prev =               \
+                               (elm)->field.le_prev;                          \
+               *(elm)->field.le_prev = LIST_NEXT((elm), field);               \
+               TRASHIT(*oldnext);                                             \
+               TRASHIT(*oldprev);                                             \
+       } while (0)
+
+#define LIST_SWAP(head1, head2, type, field)                                   \
+       do {                                                                   \
+               struct type *swap_tmp = LIST_FIRST((head1));                   \
+               LIST_FIRST((head1)) = LIST_FIRST((head2));                     \
+               LIST_FIRST((head2)) = swap_tmp;                                \
+               if ((swap_tmp = LIST_FIRST((head1))) != NULL)                  \
+                       swap_tmp->field.le_prev = &LIST_FIRST((head1));        \
+               if ((swap_tmp = LIST_FIRST((head2))) != NULL)                  \
+                       swap_tmp->field.le_prev = &LIST_FIRST((head2));        \
+       } while (0)
+
+/*
+ * Tail queue declarations.
+ */
+#define TAILQ_HEAD(name, type)                                                 \
+       struct name {                                                          \
+               struct type *tqh_first; /* first element */                    \
+               struct type **tqh_last; /* addr of last next element */        \
+               TRACEBUF                                                       \
+       }
+
+#define TAILQ_HEAD_INITIALIZER(head)                                           \
+       {                                                                      \
+               NULL, &(head).tqh_first                                        \
+       }
+
+#define TAILQ_ENTRY(type)                                                      \
+       struct {                                                               \
+               struct type *tqe_next;  /* next element */                     \
+               struct type **tqe_prev; /* address of previous next element */ \
+               TRACEBUF                                                       \
+       }
+
+/*
+ * Tail queue functions.
+ */
+#if (defined(_KERNEL) && defined(INVARIANTS))
+#define QMD_TAILQ_CHECK_HEAD(head, field)                                      \
+       do {                                                                   \
+               if (!TAILQ_EMPTY(head)                                         \
+                   && TAILQ_FIRST((head))->field.tqe_prev                     \
+                              != &TAILQ_FIRST((head)))                        \
+                       panic("Bad tailq head %p first->prev != head",         \
+                             (head));                                         \
+       } while (0)
+
+#define QMD_TAILQ_CHECK_TAIL(head, field)                                      \
+       do {                                                                   \
+               if (*(head)->tqh_last != NULL)                                 \
+                       panic("Bad tailq NEXT(%p->tqh_last) != NULL", (head)); \
+       } while (0)
+
+#define QMD_TAILQ_CHECK_NEXT(elm, field)                                       \
+       do {                                                                   \
+               if (TAILQ_NEXT((elm), field) != NULL                           \
+                   && TAILQ_NEXT((elm), field)->field.tqe_prev                \
+                              != &((elm)->field.tqe_next))                    \
+                       panic("Bad link elm %p next->prev != elm", (elm));     \
+       } while (0)
+
+#define QMD_TAILQ_CHECK_PREV(elm, field)                                       \
+       do {                                                                   \
+               if (*(elm)->field.tqe_prev != (elm))                           \
+                       panic("Bad link elm %p prev->next != elm", (elm));     \
+       } while (0)
+#else
+#define        QMD_TAILQ_CHECK_HEAD(head, field)
+#define        QMD_TAILQ_CHECK_TAIL(head, headname)
+#define        QMD_TAILQ_CHECK_NEXT(elm, field)
+#define        QMD_TAILQ_CHECK_PREV(elm, field)
+#endif /* (_KERNEL && INVARIANTS) */
+
+#define TAILQ_CONCAT(head1, head2, field)                                      \
+       do {                                                                   \
+               if (!TAILQ_EMPTY(head2)) {                                     \
+                       *(head1)->tqh_last = (head2)->tqh_first;               \
+                       (head2)->tqh_first->field.tqe_prev =                   \
+                               (head1)->tqh_last;                             \
+                       (head1)->tqh_last = (head2)->tqh_last;                 \
+                       TAILQ_INIT((head2));                                   \
+                       QMD_TRACE_HEAD(head1);                                 \
+                       QMD_TRACE_HEAD(head2);                                 \
+               }                                                              \
+       } while (0)
+
+#define        TAILQ_EMPTY(head)       ((head)->tqh_first == NULL)
+
+#define        TAILQ_FIRST(head)       ((head)->tqh_first)
+
+#define TAILQ_FOREACH(var, head, field)                                        \
+       for ((var) = TAILQ_FIRST((head)); (var);                               \
+            (var) = TAILQ_NEXT((var), field))
+
+#define TAILQ_FOREACH_SAFE(var, head, field, tvar)                             \
+       for ((var) = TAILQ_FIRST((head));                                      \
+            (var) && ((tvar) = TAILQ_NEXT((var), field), 1); (var) = (tvar))
+
+#define TAILQ_FOREACH_REVERSE(var, head, headname, field)                      \
+       for ((var) = TAILQ_LAST((head), headname); (var);                      \
+            (var) = TAILQ_PREV((var), headname, field))
+
+#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar)           \
+       for ((var) = TAILQ_LAST((head), headname);                             \
+            (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1);        \
+            (var) = (tvar))
+
+#define TAILQ_INIT(head)                                                       \
+       do {                                                                   \
+               TAILQ_FIRST((head)) = NULL;                                    \
+               (head)->tqh_last = &TAILQ_FIRST((head));                       \
+               QMD_TRACE_HEAD(head);                                          \
+       } while (0)
+
+#define TAILQ_INSERT_AFTER(head, listelm, elm, field)                          \
+       do {                                                                   \
+               QMD_TAILQ_CHECK_NEXT(listelm, field);                          \
+               if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field))  \
+                   != NULL)                                                   \
+                       TAILQ_NEXT((elm), field)->field.tqe_prev =             \
+                               &TAILQ_NEXT((elm), field);                     \
+               else {                                                         \
+                       (head)->tqh_last = &TAILQ_NEXT((elm), field);          \
+                       QMD_TRACE_HEAD(head);                                  \
+               }                                                              \
+               TAILQ_NEXT((listelm), field) = (elm);                          \
+               (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field);         \
+               QMD_TRACE_ELEM(&(elm)->field);                                 \
+               QMD_TRACE_ELEM(&listelm->field);                               \
+       } while (0)
+
+#define TAILQ_INSERT_BEFORE(listelm, elm, field)                               \
+       do {                                                                   \
+               QMD_TAILQ_CHECK_PREV(listelm, field);                          \
+               (elm)->field.tqe_prev = (listelm)->field.tqe_prev;             \
+               TAILQ_NEXT((elm), field) = (listelm);                          \
+               *(listelm)->field.tqe_prev = (elm);                            \
+               (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field);         \
+               QMD_TRACE_ELEM(&(elm)->field);                                 \
+               QMD_TRACE_ELEM(&listelm->field);                               \
+       } while (0)
+
+#define TAILQ_INSERT_HEAD(head, elm, field)                                    \
+       do {                                                                   \
+               QMD_TAILQ_CHECK_HEAD(head, field);                             \
+               if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL)  \
+                       TAILQ_FIRST((head))->field.tqe_prev =                  \
+                               &TAILQ_NEXT((elm), field);                     \
+               else                                                           \
+                       (head)->tqh_last = &TAILQ_NEXT((elm), field);          \
+               TAILQ_FIRST((head)) = (elm);                                   \
+               (elm)->field.tqe_prev = &TAILQ_FIRST((head));                  \
+               QMD_TRACE_HEAD(head);                                          \
+               QMD_TRACE_ELEM(&(elm)->field);                                 \
+       } while (0)
+
+#define TAILQ_INSERT_TAIL(head, elm, field)                                    \
+       do {                                                                   \
+               QMD_TAILQ_CHECK_TAIL(head, field);                             \
+               TAILQ_NEXT((elm), field) = NULL;                               \
+               (elm)->field.tqe_prev = (head)->tqh_last;                      \
+               *(head)->tqh_last = (elm);                                     \
+               (head)->tqh_last = &TAILQ_NEXT((elm), field);                  \
+               QMD_TRACE_HEAD(head);                                          \
+               QMD_TRACE_ELEM(&(elm)->field);                                 \
+       } while (0)
+
+#define TAILQ_LAST(head, headname)                                             \
+       (*(((struct headname *)((head)->tqh_last))->tqh_last))
+
+#define        TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
+
+#define TAILQ_PREV(elm, headname, field)                                       \
+       (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
+
+#define TAILQ_REMOVE(head, elm, field)                                         \
+       do {                                                                   \
+               QMD_SAVELINK(oldnext, (elm)->field.tqe_next);                  \
+               QMD_SAVELINK(oldprev, (elm)->field.tqe_prev);                  \
+               QMD_TAILQ_CHECK_NEXT(elm, field);                              \
+               QMD_TAILQ_CHECK_PREV(elm, field);                              \
+               if ((TAILQ_NEXT((elm), field)) != NULL)                        \
+                       TAILQ_NEXT((elm), field)->field.tqe_prev =             \
+                               (elm)->field.tqe_prev;                         \
+               else {                                                         \
+                       (head)->tqh_last = (elm)->field.tqe_prev;              \
+                       QMD_TRACE_HEAD(head);                                  \
+               }                                                              \
+               *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field);             \
+               TRASHIT(*oldnext);                                             \
+               TRASHIT(*oldprev);                                             \
+               QMD_TRACE_ELEM(&(elm)->field);                                 \
+       } while (0)
+
+#define TAILQ_SWAP(head1, head2, type, field)                                  \
+       do {                                                                   \
+               struct type *swap_first = (head1)->tqh_first;                  \
+               struct type **swap_last = (head1)->tqh_last;                   \
+               (head1)->tqh_first = (head2)->tqh_first;                       \
+               (head1)->tqh_last = (head2)->tqh_last;                         \
+               (head2)->tqh_first = swap_first;                               \
+               (head2)->tqh_last = swap_last;                                 \
+               if ((swap_first = (head1)->tqh_first) != NULL)                 \
+                       swap_first->field.tqe_prev = &(head1)->tqh_first;      \
+               else                                                           \
+                       (head1)->tqh_last = &(head1)->tqh_first;               \
+               if ((swap_first = (head2)->tqh_first) != NULL)                 \
+                       swap_first->field.tqe_prev = &(head2)->tqh_first;      \
+               else                                                           \
+                       (head2)->tqh_last = &(head2)->tqh_first;               \
+       } while (0)
+
+#endif /* !_SYS_QUEUE_H_ */
diff --git a/lib/frr_zmq.c b/lib/frr_zmq.c
new file mode 100644 (file)
index 0000000..861f7a5
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+ * libzebra ZeroMQ bindings
+ * Copyright (C) 2015  David Lamparter
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <zebra.h>
+#include <zmq.h>
+
+#include "thread.h"
+#include "memory.h"
+#include "frr_zmq.h"
+#include "log.h"
+
+DEFINE_MTYPE_STATIC(LIB, ZEROMQ_CB, "ZeroMQ callback")
+
+/* libzmq's context */
+void *frrzmq_context = NULL;
+static unsigned frrzmq_initcount = 0;
+
+void frrzmq_init(void)
+{
+       if (frrzmq_initcount++ == 0) {
+               frrzmq_context = zmq_ctx_new();
+               zmq_ctx_set(frrzmq_context, ZMQ_IPV6, 1);
+       }
+}
+
+void frrzmq_finish(void)
+{
+       if (--frrzmq_initcount == 0) {
+               zmq_ctx_term(frrzmq_context);
+               frrzmq_context = NULL;
+       }
+}
+
+/* read callback integration */
+struct frrzmq_cb {
+       struct thread *thread;
+       void *zmqsock;
+       void *arg;
+       int fd;
+
+       bool cancelled;
+
+       void (*cb_msg)(void *arg, void *zmqsock);
+       void (*cb_part)(void *arg, void *zmqsock,
+                       zmq_msg_t *msg, unsigned partnum);
+};
+
+
+static int frrzmq_read_msg(struct thread *t)
+{
+       struct frrzmq_cb *cb = THREAD_ARG(t);
+       zmq_msg_t msg;
+       unsigned partno;
+       int ret, more;
+       size_t moresz;
+
+       while (1) {
+               zmq_pollitem_t polli = {
+                       .socket = cb->zmqsock,
+                       .events = ZMQ_POLLIN
+               };
+               ret = zmq_poll(&polli, 1, 0);
+
+               if (ret < 0)
+                       goto out_err;
+               if (!(polli.revents & ZMQ_POLLIN))
+                       break;
+
+               if (cb->cb_msg) {
+                       cb->cb_msg(cb->arg, cb->zmqsock);
+
+                       if (cb->cancelled) {
+                               XFREE(MTYPE_ZEROMQ_CB, cb);
+                               return 0;
+                       }
+                       continue;
+               }
+
+               partno = 0;
+               if (zmq_msg_init(&msg))
+                       goto out_err;
+               do {
+                       ret = zmq_msg_recv(&msg, cb->zmqsock, ZMQ_NOBLOCK);
+                       if (ret < 0) {
+                               if (errno == EAGAIN)
+                                       break;
+
+                               zmq_msg_close(&msg);
+                               goto out_err;
+                       }
+
+                       cb->cb_part(cb->arg, cb->zmqsock, &msg, partno);
+                       if (cb->cancelled) {
+                               zmq_msg_close(&msg);
+                               XFREE(MTYPE_ZEROMQ_CB, cb);
+                               return 0;
+                       }
+
+                       /* cb_part may have read additional parts of the
+                        * message; don't use zmq_msg_more here */
+                       moresz = sizeof(more);
+                       more = 0;
+                       ret = zmq_getsockopt(cb->zmqsock, ZMQ_RCVMORE,
+                                            &more, &moresz);
+                       if (ret < 0) {
+                               zmq_msg_close(&msg);
+                               goto out_err;
+                       }
+
+                       partno++;
+               } while (more);
+               zmq_msg_close(&msg);
+       }
+
+       funcname_thread_add_read_write(THREAD_READ, t->master, frrzmq_read_msg,
+                       cb, cb->fd, &cb->thread, t->funcname, t->schedfrom,
+                       t->schedfrom_line);
+       return 0;
+
+out_err:
+       zlog_err("ZeroMQ error: %s(%d)", strerror (errno), errno);
+       return 0;
+}
+
+struct frrzmq_cb *funcname_frrzmq_thread_add_read(
+               struct thread_master *master,
+               void (*msgfunc)(void *arg, void *zmqsock),
+               void (*partfunc)(void *arg, void *zmqsock,
+                                zmq_msg_t *msg, unsigned partnum),
+               void *arg, void *zmqsock, debugargdef)
+{
+       int fd, events;
+       size_t len;
+       struct frrzmq_cb *cb;
+
+       if (!(msgfunc || partfunc) || (msgfunc && partfunc))
+               return NULL;
+       len = sizeof(fd);
+       if (zmq_getsockopt(zmqsock, ZMQ_FD, &fd, &len))
+               return NULL;
+       len = sizeof(events);
+       if (zmq_getsockopt(zmqsock, ZMQ_EVENTS, &events, &len))
+               return NULL;
+
+       cb = XCALLOC(MTYPE_ZEROMQ_CB, sizeof(struct frrzmq_cb));
+       if (!cb)
+               return NULL;
+
+       cb->arg = arg;
+       cb->zmqsock = zmqsock;
+       cb->cb_msg = msgfunc;
+       cb->cb_part = partfunc;
+       cb->fd = fd;
+
+       if (events & ZMQ_POLLIN)
+               funcname_thread_add_event(master,
+                               frrzmq_read_msg, cb, fd, &cb->thread,
+                               funcname, schedfrom, fromln);
+       else
+               funcname_thread_add_read_write(THREAD_READ, master,
+                               frrzmq_read_msg, cb, fd, &cb->thread,
+                               funcname, schedfrom, fromln);
+       return cb;
+}
+
+void frrzmq_thread_cancel(struct frrzmq_cb *cb)
+{
+       if (!cb->thread) {
+               /* canceling from within callback */
+               cb->cancelled = 1;
+               return;
+       }
+       thread_cancel(cb->thread);
+       XFREE(MTYPE_ZEROMQ_CB, cb);
+}
diff --git a/lib/frr_zmq.h b/lib/frr_zmq.h
new file mode 100644 (file)
index 0000000..69c6f85
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * libzebra ZeroMQ bindings
+ * Copyright (C) 2015  David Lamparter
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _FRRZMQ_H
+#define _FRRZMQ_H
+
+#include "thread.h"
+#include <zmq.h>
+
+/* linking/packaging note:  this is a separate library that needs to be
+ * linked into any daemon/library/module that wishes to use its
+ * functionality.  The purpose of this is to encapsulate the libzmq
+ * dependency and not make libfrr/FRR itself depend on libzmq.
+ *
+ * libfrrzmq should be put in LDFLAGS/LIBADD *before* either libfrr or
+ * libzmq, and both of these should always be listed, e.g.
+ *   foo_LDFLAGS = libfrrzmq.la libfrr.la $(ZEROMQ_LIBS)
+ */
+
+/* libzmq's context
+ *
+ * this is mostly here as a convenience, it has IPv6 enabled but nothing
+ * else is tied to it;  you can use a separate context without problems
+ */
+extern void *frrzmq_context;
+
+extern void frrzmq_init (void);
+extern void frrzmq_finish (void);
+
+#define debugargdef const char *funcname, const char *schedfrom, int fromln
+
+/* core event registration, one of these 2 macros should be used */
+#define frrzmq_thread_add_read_msg(m,f,a,z) funcname_frrzmq_thread_add_read( \
+                               m,f,NULL,a,z,#f,__FILE__,__LINE__)
+#define frrzmq_thread_add_read_part(m,f,a,z) funcname_frrzmq_thread_add_read( \
+                               m,NULL,f,a,z,#f,__FILE__,__LINE__)
+
+struct frrzmq_cb;
+
+/* Set up a POLLIN notification to be called from the libfrr main loop.
+ * This has the following properties:
+ *
+ * - since ZeroMQ works with edge triggered notifications, it will loop and
+ *   dispatch as many events as ZeroMQ has pending at the time libfrr calls
+ *   into this code
+ * - due to this looping (which means it non-single-issue), the callback is
+ *   also persistent.  Do _NOT_ re-register the event inside of your
+ *   callback function.
+ * - either msgfunc or partfunc will be called (only one can be specified)
+ *   - msgfunc is called once for each incoming message
+ *   - if partfunc is specified, the message is read and partfunc is called
+ *     for each ZeroMQ multi-part subpart.  Note that you can't send replies
+ *     before all parts have been read because that violates the ZeroMQ FSM.
+ * - you can safely cancel the callback from within itself
+ * - installing a callback will check for pending events (ZMQ_EVENTS) and
+ *   may schedule the event to run as soon as libfrr is back in its main
+ *   loop.
+ *
+ * TODO #1: add ZMQ_POLLERR / error callback
+ * TODO #2: add frrzmq_check_events() function to check for edge triggered
+ *          things that may have happened after a zmq_send() call or so
+ */
+extern struct frrzmq_cb *funcname_frrzmq_thread_add_read(
+               struct thread_master *master,
+               void (*msgfunc)(void *arg, void *zmqsock),
+               void (*partfunc)(void *arg, void *zmqsock,
+                                zmq_msg_t *msg, unsigned partnum),
+               void *arg, void *zmqsock, debugargdef);
+
+extern void frrzmq_thread_cancel(struct frrzmq_cb *cb);
+
+#endif /* _FRRZMQ_H */
index 96ecfa44d385d7f090217c9f0ecb4952c74390e8..3c6396f3470494204b03f286eb1e1a2062105b97 100644 (file)
@@ -404,7 +404,8 @@ DEFUN (grammar_findambig,
                        nodegraph = cnode->cmdgraph;
                        if (!nodegraph)
                                continue;
-                       vty_out(vty, "scanning node %d\n", scannode - 1);
+                       vty_out(vty, "scanning node %d (%s)\n",
+                               scannode - 1, node_names[scannode - 1]);
                }
 
                commands = cmd_graph_permutations(nodegraph);
index 66341cf2f1af68e9258225d28140aecc66417460..243521bef7cc7201efda7a1b4bd06d3174eeae9d 100644 (file)
@@ -335,12 +335,13 @@ void hash_free(struct hash *hash)
 
 /* CLI commands ------------------------------------------------------------ */
 
-DEFUN(show_hash_stats,
-      show_hash_stats_cmd,
-      "show hashtable [statistics]",
-      SHOW_STR
-      "Statistics about hash tables\n"
-      "Statistics about hash tables\n")
+DEFUN_NOSH(show_hash_stats,
+           show_hash_stats_cmd,
+           "show debugging hashtable [statistics]",
+           SHOW_STR
+           DEBUG_STR
+           "Statistics about hash tables\n"
+           "Statistics about hash tables\n")
 {
        struct hash *h;
        struct listnode *ln;
index 2c877cbf451e64402644088c26ee58268e4b213c..1468c4d3291f15ca00769d0eaab2eb7fb6a6ee91 100644 (file)
 DEFINE_MTYPE_STATIC(LIB, HOOK_ENTRY, "Hook entry")
 
 void _hook_register(struct hook *hook, void *funcptr, void *arg, bool has_arg,
-                   struct frrmod_runtime *module, const char *funcname)
+                   struct frrmod_runtime *module, const char *funcname,
+                   int priority)
 {
-       struct hookent *he = XCALLOC(MTYPE_HOOK_ENTRY, sizeof(*he));
+       struct hookent *he = XCALLOC(MTYPE_HOOK_ENTRY, sizeof(*he)), **pos;
        he->hookfn = funcptr;
        he->hookarg = arg;
        he->has_arg = has_arg;
        he->module = module;
        he->fnname = funcname;
+       he->priority = priority;
 
-       he->next = hook->entries;
-       hook->entries = he;
+       for (pos = &hook->entries; *pos; pos = &(*pos)->next)
+               if (hook->reverse
+                   ? (*pos)->priority < priority
+                   : (*pos)->priority >= priority)
+                       break;
+
+       he->next = *pos;
+       *pos = he;
 }
 
 void _hook_unregister(struct hook *hook, void *funcptr, void *arg, bool has_arg)
index 4a5cee2fd394ea1783cfc0c5f33c6869101ba2e9..5f45e113e75cbca264159b7d023c3d51735190e3 100644 (file)
  *     hook_register_arg (some_update_event, event_handler, addonptr);
  *
  *   (addonptr isn't typesafe, but that should be manageable.)
+ *
+ * Hooks also support a "priority" value for ordering registered calls
+ * relative to each other.  The priority is a signed integer where lower
+ * values are called earlier.  There is also "Koohs", which is hooks with
+ * reverse priority ordering (for cleanup/deinit hooks, so you can use the
+ * same priority value).
+ *
+ * Recommended priority value ranges are:
+ *
+ *  -999 ...     0 ...  999 - main executable / daemon, or library
+ * -1999 ... -1000          - modules registering calls that should run before
+ *                            the daemon's bits
+ *            1000 ... 1999 - modules calls that should run after daemon's
+ *
+ * Note: the default value is 1000, based on the following 2 expectations:
+ * - most hook_register() usage will be in loadable modules
+ * - usage of hook_register() in the daemon itself may need relative ordering
+ *   to itself, making an explicit value the expected case
+ *
+ * The priority value is passed as extra argument on hook_register_prio() /
+ * hook_register_arg_prio().  Whether a hook runs in reverse is determined
+ * solely by the code defining / calling the hook.  (DECLARE_KOOH is actually
+ * the same thing as DECLARE_HOOK, it's just there to make it obvious.)
  */
 
 /* TODO:
@@ -94,6 +117,7 @@ struct hookent {
        void *hookfn; /* actually a function pointer */
        void *hookarg;
        bool has_arg;
+       int priority;
        struct frrmod_runtime *module;
        const char *fnname;
 };
@@ -101,8 +125,11 @@ struct hookent {
 struct hook {
        const char *name;
        struct hookent *entries;
+       bool reverse;
 };
 
+#define HOOK_DEFAULT_PRIORITY 1000
+
 /* subscribe/add callback function to a hook
  *
  * always use hook_register(), which uses the static inline helper from
@@ -110,14 +137,21 @@ struct hook {
  */
 extern void _hook_register(struct hook *hook, void *funcptr, void *arg,
                           bool has_arg, struct frrmod_runtime *module,
-                          const char *funcname);
+                          const char *funcname, int priority);
 #define hook_register(hookname, func)                                          \
        _hook_register(&_hook_##hookname, _hook_typecheck_##hookname(func),    \
-                      NULL, false, THIS_MODULE, #func)
+                      NULL, false, THIS_MODULE, #func, HOOK_DEFAULT_PRIORITY)
 #define hook_register_arg(hookname, func, arg)                                 \
        _hook_register(&_hook_##hookname,                                      \
                       _hook_typecheck_arg_##hookname(func), arg, true,        \
-                      THIS_MODULE, #func)
+                      THIS_MODULE, #func, HOOK_DEFAULT_PRIORITY)
+#define hook_register_prio(hookname, prio, func)                               \
+       _hook_register(&_hook_##hookname, _hook_typecheck_##hookname(func),    \
+                      NULL, false, THIS_MODULE, #func, prio)
+#define hook_register_arg_prio(hookname, prio, func, arg)                      \
+       _hook_register(&_hook_##hookname,                                      \
+                      _hook_typecheck_arg_##hookname(func),                   \
+                      arg, true, THIS_MODULE, #func, prio)
 
 extern void _hook_unregister(struct hook *hook, void *funcptr, void *arg,
                             bool has_arg);
@@ -156,12 +190,14 @@ extern void _hook_unregister(struct hook *hook, void *funcptr, void *arg,
        {                                                                      \
                return (void *)funcptr;                                        \
        }
+#define DECLARE_KOOH(hookname, arglist, passlist) \
+       DECLARE_HOOK(hookname, arglist, passlist)
 
 /* use in source file - contains hook-related definitions.
  */
-#define DEFINE_HOOK(hookname, arglist, passlist)                               \
+#define DEFINE_HOOK_INT(hookname, arglist, passlist, rev)                      \
        struct hook _hook_##hookname = {                                       \
-               .name = #hookname, .entries = NULL,                            \
+               .name = #hookname, .entries = NULL, .reverse = rev,            \
        };                                                                     \
        static int hook_call_##hookname arglist                                \
        {                                                                      \
@@ -184,4 +220,9 @@ extern void _hook_unregister(struct hook *hook, void *funcptr, void *arg,
                return hooksum;                                                \
        }
 
+#define DEFINE_HOOK(hookname, arglist, passlist) \
+       DEFINE_HOOK_INT(hookname, arglist, passlist, false)
+#define DEFINE_KOOH(hookname, arglist, passlist) \
+       DEFINE_HOOK_INT(hookname, arglist, passlist, true)
+
 #endif /* _FRR_HOOK_H */
index 4e4534851cccd28d31c5c54d5c52c2f6d7de325f..43c382beaaa4cb7107720553d5a19b3acc066463 100644 (file)
--- a/lib/if.c
+++ b/lib/if.c
@@ -42,17 +42,12 @@ DEFINE_MTYPE_STATIC(LIB, IF_LINK_PARAMS, "Informational Link Parameters")
 
 DEFINE_QOBJ_TYPE(interface)
 
+DEFINE_HOOK(if_add, (struct interface *ifp), (ifp))
+DEFINE_KOOH(if_del, (struct interface *ifp), (ifp))
+
 /* List of interfaces in only the default VRF */
 int ptm_enable = 0;
 
-/* One for each program.  This structure is needed to store hooks. */
-struct if_master {
-       int (*if_new_hook)(struct interface *);
-       int (*if_delete_hook)(struct interface *);
-} if_master = {
-       0,
-};
-
 /* Compare interface names, returning an integer greater than, equal to, or
  * less than 0, (following the strcmp convention), according to the
  * relationship between ifp1 and ifp2.  Interface names consist of an
@@ -150,10 +145,7 @@ struct interface *if_create(const char *name, int namelen, vrf_id_t vrf_id)
        SET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION);
 
        QOBJ_REG(ifp, interface);
-
-       if (if_master.if_new_hook)
-               (*if_master.if_new_hook)(ifp);
-
+        hook_call(if_add, ifp);
        return ifp;
 }
 
@@ -182,9 +174,7 @@ void if_update_to_new_vrf(struct interface *ifp, vrf_id_t vrf_id)
 /* Delete interface structure. */
 void if_delete_retain(struct interface *ifp)
 {
-       if (if_master.if_delete_hook)
-               (*if_master.if_delete_hook)(ifp);
-
+        hook_call(if_del, ifp);
        QOBJ_UNREG(ifp);
 
        /* Free connected address list */
@@ -209,21 +199,6 @@ void if_delete(struct interface *ifp)
        XFREE(MTYPE_IF, ifp);
 }
 
-/* Add hook to interface master. */
-void if_add_hook(int type, int (*func)(struct interface *ifp))
-{
-       switch (type) {
-       case IF_NEW_HOOK:
-               if_master.if_new_hook = func;
-               break;
-       case IF_DELETE_HOOK:
-               if_master.if_delete_hook = func;
-               break;
-       default:
-               break;
-       }
-}
-
 /* Interface existance check by index. */
 struct interface *if_lookup_by_index(ifindex_t ifindex, vrf_id_t vrf_id)
 {
index f80ac19179527e2bf57da2d165cd6c1d90f2a06d..a592e0ff857d25ebfd34b6f8c655ecf4fe7919b0 100644 (file)
--- a/lib/if.h
+++ b/lib/if.h
@@ -25,6 +25,7 @@
 #include "linklist.h"
 #include "memory.h"
 #include "qobj.h"
+#include "hook.h"
 
 DECLARE_MTYPE(IF)
 DECLARE_MTYPE(CONNECTED_LABEL)
@@ -283,6 +284,17 @@ struct interface {
 };
 DECLARE_QOBJ_TYPE(interface)
 
+/* called from the library code whenever interfaces are created/deleted
+ * note: interfaces may not be fully realized at that point; also they
+ * may not exist in the system (ifindex = IFINDEX_INTERNAL)
+ *
+ * priority values are important here, daemons should be at 0 while modules
+ * can use 1000+ so they run after the daemon has initialised daemon-specific
+ * interface data
+ */
+DECLARE_HOOK(if_add, (struct interface *ifp), (ifp))
+DECLARE_KOOH(if_del, (struct interface *ifp), (ifp))
+
 /* Connected address structure. */
 struct connected {
        /* Attached interface. */
@@ -355,10 +367,6 @@ struct nbr_connected {
                 ? (C)->destination                                            \
                 : (C)->address)
 
-/* Interface hook sort. */
-#define IF_NEW_HOOK   0
-#define IF_DELETE_HOOK 1
-
 /* There are some interface flags which are only supported by some
    operating system. */
 
@@ -442,7 +450,6 @@ extern int if_is_loopback(struct interface *);
 extern int if_is_broadcast(struct interface *);
 extern int if_is_pointopoint(struct interface *);
 extern int if_is_multicast(struct interface *);
-extern void if_add_hook(int, int (*)(struct interface *));
 extern void if_init(struct list **);
 extern void if_cmd_init(void);
 extern void if_terminate(struct list **);
index a486fc17c18d35329eb245ca2d4a051ba3e3fb03..ae660504e41ddc3e8c0552962ca088100fc0428a 100644 (file)
@@ -18,7 +18,7 @@
 
 #include <zebra.h>
 
-#include "openbsd-queue.h"
+#include "queue.h"
 #include "imsg.h"
 
 int    ibuf_realloc(struct ibuf *, size_t);
index fc62c13734a8bbf036580cdc84f75b108f6d770e..999ab679b8a29cd945b20e3e902574bdd4b1f2e0 100644 (file)
@@ -18,7 +18,7 @@
 
 #include <zebra.h>
 
-#include "openbsd-queue.h"
+#include "queue.h"
 #include "imsg.h"
 
 int     imsg_fd_overhead = 0;
index a5c87e6edc6d6d5f003ed2731108ca9491f542f0..9944fdd1e163ad6ab8bad34a3f43efb95ede36dd 100644 (file)
@@ -37,6 +37,8 @@
 #include "network.h"
 
 DEFINE_HOOK(frr_late_init, (struct thread_master * tm), (tm))
+DEFINE_KOOH(frr_early_fini, (), ())
+DEFINE_KOOH(frr_fini, (), ())
 
 const char frr_sysconfdir[] = SYSCONFDIR;
 const char frr_vtydir[] = DAEMON_VTY_DIR;
@@ -50,6 +52,8 @@ char frr_zclientpath[256];
 static char pidfile_default[256];
 static char vtypath_default[256];
 
+bool debug_memstats_at_exit = 0;
+
 static char comb_optstr[256];
 static struct option comb_lo[64];
 static struct option *comb_next_lo = &comb_lo[0];
@@ -637,7 +641,10 @@ static void frr_daemon_wait(int fd)
                exit(0);
 
        /* child failed one way or another ... */
-       if (WIFEXITED(exitstat))
+       if (WIFEXITED(exitstat) && WEXITSTATUS(exitstat) == 0)
+               /* can happen in --terminal case if exit is fast enough */
+               (void)0;
+       else if (WIFEXITED(exitstat))
                fprintf(stderr, "%s failed to start, exited %d\n", di->name,
                        WEXITSTATUS(exitstat));
        else if (WIFSIGNALED(exitstat))
@@ -831,3 +838,50 @@ void frr_run(struct thread_master *master)
        while (thread_fetch(master, &thread))
                thread_call(&thread);
 }
+
+void frr_early_fini(void)
+{
+       hook_call(frr_early_fini);
+}
+
+void frr_fini(void)
+{
+       FILE *fp;
+       char filename[128];
+       int have_leftovers;
+
+       hook_call(frr_fini);
+
+       /* memory_init -> nothing needed */
+       vty_terminate();
+       cmd_terminate();
+       zprivs_terminate(di->privs);
+       /* signal_init -> nothing needed */
+       thread_master_free(master);
+       closezlog();
+       /* frrmod_init -> nothing needed / hooks */
+
+       if (!debug_memstats_at_exit)
+               return;
+
+       have_leftovers = log_memstats(stderr, di->name);
+
+       /* in case we decide at runtime that we want exit-memstats for
+        * a daemon, but it has no stderr because it's daemonized
+        * (only do this if we actually have something to print though)
+        */
+       if (!have_leftovers)
+               return;
+
+       snprintf(filename, sizeof(filename),
+                "/tmp/frr-memstats-%s-%llu-%llu",
+                di->name,
+                (unsigned long long)getpid(),
+                (unsigned long long)time(NULL));
+
+       fp = fopen(filename, "w");
+       if (fp) {
+               log_memstats(fp, di->name);
+               fclose(fp);
+       }
+}
index 1710fc9a846ea0a69e4fa42355f84f6a37a55ac3..f7d69eecb3fbe004f8df52210fdc64d68cb5f0cb 100644 (file)
@@ -104,6 +104,14 @@ extern void frr_run(struct thread_master *master);
 extern bool frr_zclient_addr(struct sockaddr_storage *sa, socklen_t *sa_len,
                             const char *path);
 
+/* these two are before the protocol daemon does its own shutdown
+ * it's named this way being the counterpart to frr_late_init */
+DECLARE_KOOH(frr_early_fini, (), ())
+extern void frr_early_fini(void);
+/* and these two are after the daemon did its own cleanup */
+DECLARE_KOOH(frr_fini, (), ())
+extern void frr_fini(void);
+
 extern char config_default[256];
 extern char frr_zclientpath[256];
 extern const char frr_sysconfdir[];
@@ -113,4 +121,6 @@ extern const char frr_moduledir[];
 extern char frr_protoname[];
 extern char frr_protonameinst[];
 
+extern bool debug_memstats_at_exit;
+
 #endif /* _ZEBRA_FRR_H */
index 5c89e7080eafaef5b5955b2374028f20567a8228..ea2e804cda7f62c0a7697ed45669899ee1a5315b 100644 (file)
--- a/lib/log.c
+++ b/lib/log.c
@@ -701,7 +701,7 @@ void _zlog_assert_failed(const char *assertion, const char *file,
             assertion, file, line, (function ? function : "?"));
        zlog_backtrace(LOG_CRIT);
        zlog_thread_info(LOG_CRIT);
-       log_memstats_stderr("log");
+       log_memstats(stderr, "log");
        abort();
 }
 
@@ -867,6 +867,8 @@ static const struct zebra_desc_table command_types[] = {
        DESC_ENTRY(ZEBRA_INTERFACE_UP),
        DESC_ENTRY(ZEBRA_INTERFACE_DOWN),
        DESC_ENTRY(ZEBRA_INTERFACE_SET_MASTER),
+       DESC_ENTRY(ZEBRA_ROUTE_ADD),
+       DESC_ENTRY(ZEBRA_ROUTE_DELETE),
        DESC_ENTRY(ZEBRA_IPV4_ROUTE_ADD),
        DESC_ENTRY(ZEBRA_IPV4_ROUTE_DELETE),
        DESC_ENTRY(ZEBRA_IPV6_ROUTE_ADD),
@@ -893,10 +895,8 @@ static const struct zebra_desc_table command_types[] = {
        DESC_ENTRY(ZEBRA_BFD_DEST_DEREGISTER),
        DESC_ENTRY(ZEBRA_BFD_DEST_UPDATE),
        DESC_ENTRY(ZEBRA_BFD_DEST_REPLAY),
-       DESC_ENTRY(ZEBRA_REDISTRIBUTE_IPV4_ADD),
-       DESC_ENTRY(ZEBRA_REDISTRIBUTE_IPV4_DEL),
-       DESC_ENTRY(ZEBRA_REDISTRIBUTE_IPV6_ADD),
-       DESC_ENTRY(ZEBRA_REDISTRIBUTE_IPV6_DEL),
+       DESC_ENTRY(ZEBRA_REDISTRIBUTE_ROUTE_ADD),
+       DESC_ENTRY(ZEBRA_REDISTRIBUTE_ROUTE_DEL),
        DESC_ENTRY(ZEBRA_VRF_UNREGISTER),
        DESC_ENTRY(ZEBRA_VRF_ADD),
        DESC_ENTRY(ZEBRA_VRF_DELETE),
@@ -908,10 +908,6 @@ static const struct zebra_desc_table command_types[] = {
        DESC_ENTRY(ZEBRA_INTERFACE_LINK_PARAMS),
        DESC_ENTRY(ZEBRA_MPLS_LABELS_ADD),
        DESC_ENTRY(ZEBRA_MPLS_LABELS_DELETE),
-       DESC_ENTRY(ZEBRA_IPV4_NEXTHOP_ADD),
-       DESC_ENTRY(ZEBRA_IPV4_NEXTHOP_DELETE),
-       DESC_ENTRY(ZEBRA_IPV6_NEXTHOP_ADD),
-       DESC_ENTRY(ZEBRA_IPV6_NEXTHOP_DELETE),
        DESC_ENTRY(ZEBRA_IPMR_ROUTE_STATS),
        DESC_ENTRY(ZEBRA_LABEL_MANAGER_CONNECT),
        DESC_ENTRY(ZEBRA_GET_LABEL_CHUNK),
index 0ccc2040023c26d71453a2270d75280743971bc6..c684c7605c00b9063b9390fbc45adb89ecb41e49 100644 (file)
@@ -104,6 +104,7 @@ int qmem_walk(qmem_walk_fn *func, void *arg)
 }
 
 struct exit_dump_args {
+       FILE *fp;
        const char *prefix;
        int error;
 };
@@ -113,7 +114,7 @@ static int qmem_exit_walker(void *arg, struct memgroup *mg, struct memtype *mt)
        struct exit_dump_args *eda = arg;
 
        if (!mt) {
-               fprintf(stderr,
+               fprintf(eda->fp,
                        "%s: showing active allocations in "
                        "memory group %s\n",
                        eda->prefix, mg->name);
@@ -122,15 +123,16 @@ static int qmem_exit_walker(void *arg, struct memgroup *mg, struct memtype *mt)
                char size[32];
                eda->error++;
                snprintf(size, sizeof(size), "%10zu", mt->size);
-               fprintf(stderr, "%s: memstats:  %-30s: %6zu * %s\n",
+               fprintf(eda->fp, "%s: memstats:  %-30s: %6zu * %s\n",
                        eda->prefix, mt->name, mt->n_alloc,
                        mt->size == SIZE_VAR ? "(variably sized)" : size);
        }
        return 0;
 }
 
-void log_memstats_stderr(const char *prefix)
+int log_memstats(FILE *fp, const char *prefix)
 {
-       struct exit_dump_args eda = {.prefix = prefix, .error = 0};
+       struct exit_dump_args eda = { .fp = fp, .prefix = prefix, .error = 0 };
        qmem_walk(qmem_exit_walker, &eda);
+       return eda.error;
 }
index d5facad583363030caf0f641bd0f4fec48e2ed5c..6de370514abe47c361cbebdfa3e144cb6fd89c36 100644 (file)
@@ -18,7 +18,9 @@
 #define _QUAGGA_MEMORY_H
 
 #include <stdlib.h>
+#include <stdio.h>
 #include <frratomic.h>
+#include "compiler.h"
 
 #define array_size(ar) (sizeof(ar) / sizeof(ar[0]))
 
@@ -36,41 +38,6 @@ struct memgroup {
        const char *name;
 };
 
-#if defined(__clang__)
-#if __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 5)
-#  define _RET_NONNULL  , returns_nonnull
-#endif
-# define _CONSTRUCTOR(x) constructor(x)
-#elif defined(__GNUC__)
-#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
-#  define _RET_NONNULL  , returns_nonnull
-#endif
-#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)
-#  define _CONSTRUCTOR(x) constructor(x)
-#  define _DESTRUCTOR(x)  destructor(x)
-#  define _ALLOC_SIZE(x)  alloc_size(x)
-#endif
-#endif
-
-#ifdef __sun
-/* Solaris doesn't do constructor priorities due to linker restrictions */
-#undef _CONSTRUCTOR
-#undef _DESTRUCTOR
-#endif
-
-#ifndef _RET_NONNULL
-# define _RET_NONNULL
-#endif
-#ifndef _CONSTRUCTOR
-# define _CONSTRUCTOR(x) constructor
-#endif
-#ifndef _DESTRUCTOR
-# define _DESTRUCTOR(x) destructor
-#endif
-#ifndef _ALLOC_SIZE
-# define _ALLOC_SIZE(x)
-#endif
-
 /* macro usage:
  *
  *  mydaemon.h
@@ -194,7 +161,8 @@ static inline size_t mtype_stats_alloc(struct memtype *mt)
  * last value from qmem_walk_fn. */
 typedef int qmem_walk_fn(void *arg, struct memgroup *mg, struct memtype *mt);
 extern int qmem_walk(qmem_walk_fn *func, void *arg);
-extern void log_memstats_stderr(const char *);
+extern int log_memstats(FILE *fp, const char *);
+#define log_memstats_stderr(prefix) log_memstats(stderr, prefix)
 
 extern void memory_oom(size_t size, const char *name);
 
index beef79109302b80a539b1e38103116b44d870764..b3ab91c4ea326952e22ba8edd132d23e94150207 100644 (file)
@@ -42,8 +42,10 @@ static struct frrmod_info frrmod_default_info = {
        .description = "libfrr core module",
 };
 union _frrmod_runtime_u frrmod_default = {
-       .r.info = &frrmod_default_info,
-       .r.finished_loading = 1,
+       .r = {
+               .info = &frrmod_default_info,
+               .finished_loading = 1,
+       },
 };
 
 // if defined(HAVE_SYS_WEAK_ALIAS_ATTRIBUTE)
index 025770d479645bebc23d826cd96ba15d63dbbecd..bf98eecd81615adafe8b22f4002579a3610ba18a 100644 (file)
@@ -44,6 +44,9 @@
 #define MPLS_DEFAULT_MIN_SRGB_LABEL        16000
 #define MPLS_DEFAULT_MAX_SRGB_LABEL        23999
 
+/* Maximum # labels that can be pushed. */
+#define MPLS_MAX_LABELS                    16
+
 #define IS_MPLS_RESERVED_LABEL(label)                                          \
        (label >= MPLS_MIN_RESERVED_LABEL && label <= MPLS_MAX_RESERVED_LABEL)
 
index b0cf42ca49980c38c58aa2103953707d863d8910..ebd628d7249cfcc448b34fadf3b76bb5bab441b7 100644 (file)
@@ -122,6 +122,14 @@ const char *prefix_list_name(struct prefix_list *plist)
        return plist->name;
 }
 
+afi_t prefix_list_afi(struct prefix_list *plist)
+{
+       if (plist->master == &prefix_master_ipv4
+           || plist->master == &prefix_master_orf_v4)
+               return AFI_IP;
+       return AFI_IP6;
+}
+
 /* Lookup prefix_list from list of prefix_list by name. */
 static struct prefix_list *prefix_list_lookup_do(afi_t afi, int orf,
                                                 const char *name)
index 73d8da509afdd445b4d97228c7631677856ea40a..3eba3046ae6b269f0a690b1a6c0635ea77b162d5 100644 (file)
@@ -48,6 +48,7 @@ extern void prefix_list_add_hook(void (*func)(struct prefix_list *));
 extern void prefix_list_delete_hook(void (*func)(struct prefix_list *));
 
 extern const char *prefix_list_name(struct prefix_list *);
+extern afi_t prefix_list_afi(struct prefix_list *);
 extern struct prefix_list *prefix_list_lookup(afi_t, const char *);
 extern enum prefix_list_type prefix_list_apply(struct prefix_list *, void *);
 
index de521b2e3e0949ec7a0e5f4f91a1508f2e86c8fd..10f77bda875ad4c2d58dd2837592e25b595b1ed7 100644 (file)
@@ -497,8 +497,7 @@ int prefix_same(const struct prefix *p1, const struct prefix *p2)
 
        if (p1->family == p2->family && p1->prefixlen == p2->prefixlen) {
                if (p1->family == AF_INET)
-                       if (IPV4_ADDR_SAME(&p1->u.prefix4.s_addr,
-                                          &p2->u.prefix4.s_addr))
+                       if (IPV4_ADDR_SAME(&p1->u.prefix4, &p2->u.prefix4))
                                return 1;
                if (p1->family == AF_INET6)
                        if (IPV6_ADDR_SAME(&p1->u.prefix6.s6_addr,
@@ -1264,5 +1263,6 @@ unsigned prefix_hash_key(void *pp)
         * padding and unused prefix bytes. */
        memset(&copy, 0, sizeof(copy));
        prefix_copy(&copy, (struct prefix *)pp);
-       return jhash(&copy, sizeof(copy), 0x55aa5a5a);
+       return jhash(&copy, offsetof(struct prefix, u.prefix)
+                    + PSIZE(copy.prefixlen), 0x55aa5a5a);
 }
index f0644ea88e9dbb238e4900dc012ffe938b464603..a27f46ba0a4e223d65227a0494c8546824f649ae 100644 (file)
 #endif
 #include "sockunion.h"
 #include "ipaddr.h"
+#include "compiler.h"
 
 #ifndef ETH_ALEN
 #define ETH_ALEN 6
 #endif
 
 /* for compatibility */
-#if defined(__ICC)
-#define CPP_WARN_STR(X) #X
-#define CPP_WARN(text) _Pragma(CPP_WARN_STR(message __FILE__ ": " text))
-
-#elif (defined(__GNUC__)                                                       \
-       && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)))           \
-       || (defined(__clang__)                                                 \
-           && (__clang_major__ >= 4                                           \
-               || (__clang_major__ == 3 && __clang_minor__ >= 5)))
-#define CPP_WARN_STR(X) #X
-#define CPP_WARN(text) _Pragma(CPP_WARN_STR(GCC warning text))
-
-#else
-#define CPP_WARN(text)
-#endif
-
 #ifdef ETHER_ADDR_LEN
 #undef ETHER_ADDR_LEN
 #endif
@@ -140,7 +125,7 @@ struct prefix {
                        struct in_addr adv_router;
                } lp;
                struct ethaddr prefix_eth; /* AF_ETHERNET */
-               u_char val[8];
+               u_char val[16];
                uintptr_t ptr;
                struct evpn_addr prefix_evpn; /* AF_EVPN */
        } u __attribute__((aligned(8)));
@@ -241,8 +226,20 @@ union prefixconstptr {
 #define IPV4_MAX_BITLEN    32
 #define IPV4_MAX_PREFIXLEN 32
 #define IPV4_ADDR_CMP(D,S)   memcmp ((D), (S), IPV4_MAX_BYTELEN)
-#define IPV4_ADDR_SAME(D,S)  (memcmp ((D), (S), IPV4_MAX_BYTELEN) == 0)
-#define IPV4_ADDR_COPY(D,S)  memcpy ((D), (S), IPV4_MAX_BYTELEN)
+
+static inline bool ipv4_addr_same(const struct in_addr *a,
+                                 const struct in_addr *b)
+{
+       return (a->s_addr == b->s_addr);
+}
+#define IPV4_ADDR_SAME(A,B)  ipv4_addr_same((A), (B))
+
+static inline void ipv4_addr_copy(struct in_addr *dst,
+                                 const struct in_addr *src)
+{
+       dst->s_addr = src->s_addr;
+}
+#define IPV4_ADDR_COPY(D,S)  ipv4_addr_copy((D), (S))
 
 #define IPV4_NET0(a)    ((((u_int32_t) (a)) & 0xff000000) == 0x00000000)
 #define IPV4_NET127(a)  ((((u_int32_t) (a)) & 0xff000000) == 0x7f000000)
index eda3fb02d4c0b72a7ea33b6504210107e256b9ea..cfe7d6d6f81bdf802191e2559f1438ab7c985e98 100644 (file)
@@ -856,7 +856,9 @@ void zprivs_terminate(struct zebra_privs_t *zprivs)
        }
 
 #ifdef HAVE_CAPABILITIES
-       zprivs_caps_terminate();
+       if (zprivs->user || zprivs->group || zprivs->cap_num_p
+           || zprivs->cap_num_i)
+               zprivs_caps_terminate();
 #else  /* !HAVE_CAPABILITIES */
        /* only change uid if we don't have the correct one */
        if ((zprivs_state.zuid) && (zprivs_state.zsuid != zprivs_state.zuid)) {
index 658b602ba3f740d4a2672f6c633dc0e36ac9e746..29b67a26e65639b993757e84983a2aadc8c66278 100644 (file)
-/*-
- * Copyright (c) 1991, 1993
- *     The Regents of the University of California.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- *     @(#)queue.h     8.5 (Berkeley) 8/20/94
- * $FreeBSD$
- */
-
-#ifndef _SYS_QUEUE_H_
-#define        _SYS_QUEUE_H_
-
 /*
- * This file defines four types of data structures: singly-linked lists,
- * singly-linked tail queues, lists and tail queues.
+ * lists and queues implementations
  *
- * A singly-linked list is headed by a single forward pointer. The elements
- * are singly linked for minimum space and pointer manipulation overhead at
- * the expense of O(n) removal for arbitrary elements. New elements can be
- * added to the list after an existing element or at the head of the list.
- * Elements being removed from the head of the list should use the explicit
- * macro for this purpose for optimum efficiency. A singly-linked list may
- * only be traversed in the forward direction.  Singly-linked lists are ideal
- * for applications with large datasets and few or no removals or for
- * implementing a LIFO queue.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
  *
- * A singly-linked tail queue is headed by a pair of pointers, one to the
- * head of the list and the other to the tail of the list. The elements are
- * singly linked for minimum space and pointer manipulation overhead at the
- * expense of O(n) removal for arbitrary elements. New elements can be added
- * to the list after an existing element, at the head of the list, or at the
- * end of the list. Elements being removed from the head of the tail queue
- * should use the explicit macro for this purpose for optimum efficiency.
- * A singly-linked tail queue may only be traversed in the forward direction.
- * Singly-linked tail queues are ideal for applications with large datasets
- * and few or no removals or for implementing a FIFO queue.
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
  *
- * A list is headed by a single forward pointer (or an array of forward
- * pointers for a hash table header). The elements are doubly linked
- * so that an arbitrary element can be removed without a need to
- * traverse the list. New elements can be added to the list before
- * or after an existing element or at the head of the list. A list
- * may only be traversed in the forward direction.
- *
- * A tail queue is headed by a pair of pointers, one to the head of the
- * list and the other to the tail of the list. The elements are doubly
- * linked so that an arbitrary element can be removed without a need to
- * traverse the list. New elements can be added to the list before or
- * after an existing element, at the head of the list, or at the end of
- * the list. A tail queue may be traversed in either direction.
- *
- * For details on the use of these macros, see the queue(3) manual page.
- *
- *
- *                             SLIST   LIST    STAILQ  TAILQ
- * _HEAD                       +       +       +       +
- * _HEAD_INITIALIZER           +       +       +       +
- * _ENTRY                      +       +       +       +
- * _INIT                       +       +       +       +
- * _EMPTY                      +       +       +       +
- * _FIRST                      +       +       +       +
- * _NEXT                       +       +       +       +
- * _PREV                       -       -       -       +
- * _LAST                       -       -       +       +
- * _FOREACH                    +       +       +       +
- * _FOREACH_SAFE               +       +       +       +
- * _FOREACH_REVERSE            -       -       -       +
- * _FOREACH_REVERSE_SAFE       -       -       -       +
- * _INSERT_HEAD                        +       +       +       +
- * _INSERT_BEFORE              -       +       -       +
- * _INSERT_AFTER               +       +       +       +
- * _INSERT_TAIL                        -       -       +       +
- * _CONCAT                     -       -       +       +
- * _REMOVE_AFTER               +       -       +       -
- * _REMOVE_HEAD                        +       -       +       -
- * _REMOVE                     +       +       +       +
- * _SWAP                       +       +       +       +
- *
- */
-#ifdef QUEUE_MACRO_DEBUG
-/* Store the last 2 places the queue element or head was altered */
-struct qm_trace {
-       char *lastfile;
-       int lastline;
-       char *prevfile;
-       int prevline;
-};
-
-#define        TRACEBUF        struct qm_trace trace;
-#define        TRASHIT(x)      do {(x) = (void *)-1;} while (0)
-#define        QMD_SAVELINK(name, link)        void **name = (void *)&(link)
-
-#define QMD_TRACE_HEAD(head)                                                   \
-       do {                                                                   \
-               (head)->trace.prevline = (head)->trace.lastline;               \
-               (head)->trace.prevfile = (head)->trace.lastfile;               \
-               (head)->trace.lastline = __LINE__;                             \
-               (head)->trace.lastfile = __FILE__;                             \
-       } while (0)
-
-#define QMD_TRACE_ELEM(elem)                                                   \
-       do {                                                                   \
-               (elem)->trace.prevline = (elem)->trace.lastline;               \
-               (elem)->trace.prevfile = (elem)->trace.lastfile;               \
-               (elem)->trace.lastline = __LINE__;                             \
-               (elem)->trace.lastfile = __FILE__;                             \
-       } while (0)
-
-#else
-#define        QMD_TRACE_ELEM(elem)
-#define        QMD_TRACE_HEAD(head)
-#define        QMD_SAVELINK(name, link)
-#define        TRACEBUF
-#define        TRASHIT(x)
-#endif /* QUEUE_MACRO_DEBUG */
-
-/*
- * Singly-linked List declarations.
- */
-#define SLIST_HEAD(name, type)                                                 \
-       struct name {                                                          \
-               struct type *slh_first; /* first element */                    \
-       }
-
-#define SLIST_HEAD_INITIALIZER(head)                                           \
-       {                                                                      \
-               NULL                                                           \
-       }
-
-#define SLIST_ENTRY(type)                                                      \
-       struct {                                                               \
-               struct type *sle_next; /* next element */                      \
-       }
-
-/*
- * Singly-linked List functions.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  */
-#define        SLIST_EMPTY(head)       ((head)->slh_first == NULL)
-
-#define        SLIST_FIRST(head)       ((head)->slh_first)
-
-#define SLIST_FOREACH(var, head, field)                                        \
-       for ((var) = SLIST_FIRST((head)); (var);                               \
-            (var) = SLIST_NEXT((var), field))
-
-#define SLIST_FOREACH_SAFE(var, head, field, tvar)                             \
-       for ((var) = SLIST_FIRST((head));                                      \
-            (var) && ((tvar) = SLIST_NEXT((var), field), 1); (var) = (tvar))
-
-#define SLIST_FOREACH_PREVPTR(var, varp, head, field)                          \
-       for ((varp) = &SLIST_FIRST((head)); ((var) = *(varp)) != NULL;         \
-            (varp) = &SLIST_NEXT((var), field))
-
-#define SLIST_INIT(head)                                                       \
-       do {                                                                   \
-               SLIST_FIRST((head)) = NULL;                                    \
-       } while (0)
-
-#define SLIST_INSERT_AFTER(slistelm, elm, field)                               \
-       do {                                                                   \
-               SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field);      \
-               SLIST_NEXT((slistelm), field) = (elm);                         \
-       } while (0)
-
-#define SLIST_INSERT_HEAD(head, elm, field)                                    \
-       do {                                                                   \
-               SLIST_NEXT((elm), field) = SLIST_FIRST((head));                \
-               SLIST_FIRST((head)) = (elm);                                   \
-       } while (0)
-
-#define        SLIST_NEXT(elm, field)  ((elm)->field.sle_next)
-
-#define SLIST_REMOVE(head, elm, type, field)                                   \
-       do {                                                                   \
-               QMD_SAVELINK(oldnext, (elm)->field.sle_next);                  \
-               if (SLIST_FIRST((head)) == (elm)) {                            \
-                       SLIST_REMOVE_HEAD((head), field);                      \
-               } else {                                                       \
-                       struct type *curelm = SLIST_FIRST((head));             \
-                       while (SLIST_NEXT(curelm, field) != (elm))             \
-                               curelm = SLIST_NEXT(curelm, field);            \
-                       SLIST_REMOVE_AFTER(curelm, field);                     \
-               }                                                              \
-               TRASHIT(*oldnext);                                             \
-       } while (0)
-
-#define SLIST_REMOVE_AFTER(elm, field)                                         \
-       do {                                                                   \
-               SLIST_NEXT(elm, field) =                                       \
-                       SLIST_NEXT(SLIST_NEXT(elm, field), field);             \
-       } while (0)
-
-#define SLIST_REMOVE_HEAD(head, field)                                         \
-       do {                                                                   \
-               SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field);  \
-       } while (0)
-
-#define SLIST_SWAP(head1, head2, type)                                         \
-       do {                                                                   \
-               struct type *swap_first = SLIST_FIRST(head1);                  \
-               SLIST_FIRST(head1) = SLIST_FIRST(head2);                       \
-               SLIST_FIRST(head2) = swap_first;                               \
-       } while (0)
-
-/*
- * Singly-linked Tail queue declarations.
- */
-#define STAILQ_HEAD(name, type)                                                \
-       struct name {                                                          \
-               struct type *stqh_first; /* first element */                   \
-               struct type **stqh_last; /* addr of last next element */       \
-       }
-
-#define STAILQ_HEAD_INITIALIZER(head)                                          \
-       {                                                                      \
-               NULL, &(head).stqh_first                                       \
-       }
-
-#define STAILQ_ENTRY(type)                                                     \
-       struct {                                                               \
-               struct type *stqe_next; /* next element */                     \
-       }
-
-/*
- * Singly-linked Tail queue functions.
- */
-#define STAILQ_CONCAT(head1, head2)                                            \
-       do {                                                                   \
-               if (!STAILQ_EMPTY((head2))) {                                  \
-                       *(head1)->stqh_last = (head2)->stqh_first;             \
-                       (head1)->stqh_last = (head2)->stqh_last;               \
-                       STAILQ_INIT((head2));                                  \
-               }                                                              \
-       } while (0)
-
-#define        STAILQ_EMPTY(head)      ((head)->stqh_first == NULL)
-
-#define        STAILQ_FIRST(head)      ((head)->stqh_first)
-
-#define STAILQ_FOREACH(var, head, field)                                       \
-       for ((var) = STAILQ_FIRST((head)); (var);                              \
-            (var) = STAILQ_NEXT((var), field))
-
-
-#define STAILQ_FOREACH_SAFE(var, head, field, tvar)                            \
-       for ((var) = STAILQ_FIRST((head));                                     \
-            (var) && ((tvar) = STAILQ_NEXT((var), field), 1); (var) = (tvar))
-
-#define STAILQ_INIT(head)                                                      \
-       do {                                                                   \
-               STAILQ_FIRST((head)) = NULL;                                   \
-               (head)->stqh_last = &STAILQ_FIRST((head));                     \
-       } while (0)
-
-#define STAILQ_INSERT_AFTER(head, tqelm, elm, field)                           \
-       do {                                                                   \
-               if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field))  \
-                   == NULL)                                                   \
-                       (head)->stqh_last = &STAILQ_NEXT((elm), field);        \
-               STAILQ_NEXT((tqelm), field) = (elm);                           \
-       } while (0)
-
-#define STAILQ_INSERT_HEAD(head, elm, field)                                   \
-       do {                                                                   \
-               if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head)))         \
-                   == NULL)                                                   \
-                       (head)->stqh_last = &STAILQ_NEXT((elm), field);        \
-               STAILQ_FIRST((head)) = (elm);                                  \
-       } while (0)
-
-#define STAILQ_INSERT_TAIL(head, elm, field)                                   \
-       do {                                                                   \
-               STAILQ_NEXT((elm), field) = NULL;                              \
-               *(head)->stqh_last = (elm);                                    \
-               (head)->stqh_last = &STAILQ_NEXT((elm), field);                \
-       } while (0)
 
+#ifndef _FRR_QUEUE_H
+#define _FRR_QUEUE_H
+
+#if defined(__OpenBSD__) && !defined(STAILQ_HEAD)
+#include "openbsd-queue.h"
+
+/* Try to map FreeBSD implementation to OpenBSD one. */
+#define STAILQ_HEAD(name, type)                                SIMPLEQ_HEAD(name, type)
+#define STAILQ_HEAD_INITIALIZER(head)                  SIMPLEQ_HEAD_INITIALIZER(head)
+#define STAILQ_ENTRY(entry)                            SIMPLEQ_ENTRY(entry)
+
+#define STAILQ_CONCAT(head1, head2)                    SIMPLEQ_CONCAT(head1, head2)
+#define STAILQ_EMPTY(head)                             SIMPLEQ_EMPTY(head)
+#define STAILQ_FIRST(head)                             SIMPLEQ_FIRST(head)
+#define STAILQ_FOREACH(var, head, field)               SIMPLEQ_FOREACH(var, head, field)
+#define STAILQ_FOREACH_SAFE(var, head, field, tvar)    SIMPLEQ_FOREACH_SAFE(var, head, field, tvar)
+#define STAILQ_INIT(head)                              SIMPLEQ_INIT(head)
+#define STAILQ_INSERT_AFTER(head, tqelm, elm, field)   SIMPLEQ_INSERT_AFTER(head, tqelm, elm, field)
+#define STAILQ_INSERT_HEAD(head, elm, field)           SIMPLEQ_INSERT_HEAD(head, elm, field)
+#define STAILQ_INSERT_TAIL(head, elm, field)           SIMPLEQ_INSERT_TAIL(head, elm, field)
 #define STAILQ_LAST(head, type, field)                                         \
-       (STAILQ_EMPTY((head))                                                  \
+       (SIMPLEQ_EMPTY((head))                                                 \
                 ? NULL                                                        \
-                : ((struct type *)(void *)((char *)((head)->stqh_last)        \
-                                           - __offsetof(struct type,          \
+                : ((struct type *)(void *)((char *)((head)->sqh_last)         \
+                                           - offsetof(struct type,            \
                                                         field))))
-
-#define        STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
-
+#define STAILQ_NEXT(elm, field)                                SIMPLEQ_NEXT(elm, field)
 #define STAILQ_REMOVE(head, elm, type, field)                                  \
        do {                                                                   \
-               QMD_SAVELINK(oldnext, (elm)->field.stqe_next);                 \
-               if (STAILQ_FIRST((head)) == (elm)) {                           \
-                       STAILQ_REMOVE_HEAD((head), field);                     \
+               if (SIMPLEQ_FIRST((head)) == (elm)) {                          \
+                       SIMPLEQ_REMOVE_HEAD((head), field);                    \
                } else {                                                       \
-                       struct type *curelm = STAILQ_FIRST((head));            \
-                       while (STAILQ_NEXT(curelm, field) != (elm))            \
-                               curelm = STAILQ_NEXT(curelm, field);           \
-                       STAILQ_REMOVE_AFTER(head, curelm, field);              \
+                       struct type *curelm = SIMPLEQ_FIRST((head));           \
+                       while (SIMPLEQ_NEXT(curelm, field) != (elm))           \
+                               curelm = SIMPLEQ_NEXT(curelm, field);          \
+                       SIMPLEQ_REMOVE_AFTER(head, curelm, field);             \
                }                                                              \
-               TRASHIT(*oldnext);                                             \
-       } while (0)
-
-#define STAILQ_REMOVE_AFTER(head, elm, field)                                  \
-       do {                                                                   \
-               if ((STAILQ_NEXT(elm, field) =                                 \
-                            STAILQ_NEXT(STAILQ_NEXT(elm, field), field))      \
-                   == NULL)                                                   \
-                       (head)->stqh_last = &STAILQ_NEXT((elm), field);        \
        } while (0)
-
-#define STAILQ_REMOVE_HEAD(head, field)                                        \
-       do {                                                                   \
-               if ((STAILQ_FIRST((head)) =                                    \
-                            STAILQ_NEXT(STAILQ_FIRST((head)), field))         \
-                   == NULL)                                                   \
-                       (head)->stqh_last = &STAILQ_FIRST((head));             \
-       } while (0)
-
+#define STAILQ_REMOVE_AFTER(head, elm, field)          SIMPLEQ_REMOVE_AFTER(head, elm, field)
+#define STAILQ_REMOVE_HEAD(head, field)                        SIMPLEQ_REMOVE_HEAD(head, field)
 #define STAILQ_SWAP(head1, head2, type)                                        \
        do {                                                                   \
                struct type *swap_first = STAILQ_FIRST(head1);                 \
-               struct type **swap_last = (head1)->stqh_last;                  \
+               struct type **swap_last = (head1)->sqh_last;                   \
                STAILQ_FIRST(head1) = STAILQ_FIRST(head2);                     \
-               (head1)->stqh_last = (head2)->stqh_last;                       \
+               (head1)->sqh_last = (head2)->sqh_last;                         \
                STAILQ_FIRST(head2) = swap_first;                              \
-               (head2)->stqh_last = swap_last;                                \
+               (head2)->sqh_last = swap_last;                                 \
                if (STAILQ_EMPTY(head1))                                       \
-                       (head1)->stqh_last = &STAILQ_FIRST(head1);             \
+                       (head1)->sqh_last = &STAILQ_FIRST(head1);              \
                if (STAILQ_EMPTY(head2))                                       \
-                       (head2)->stqh_last = &STAILQ_FIRST(head2);             \
-       } while (0)
-
-
-/*
- * List declarations.
- */
-#define LIST_HEAD(name, type)                                                  \
-       struct name {                                                          \
-               struct type *lh_first; /* first element */                     \
-       }
-
-#define LIST_HEAD_INITIALIZER(head)                                            \
-       {                                                                      \
-               NULL                                                           \
-       }
-
-#define LIST_ENTRY(type)                                                       \
-       struct {                                                               \
-               struct type *le_next;  /* next element */                      \
-               struct type **le_prev; /* address of previous next element */  \
-       }
-
-/*
- * List functions.
- */
-
-#if (defined(_KERNEL) && defined(INVARIANTS))
-#define QMD_LIST_CHECK_HEAD(head, field)                                       \
-       do {                                                                   \
-               if (LIST_FIRST((head)) != NULL                                 \
-                   && LIST_FIRST((head))->field.le_prev                       \
-                              != &LIST_FIRST((head)))                         \
-                       panic("Bad list head %p first->prev != head", (head)); \
-       } while (0)
-
-#define QMD_LIST_CHECK_NEXT(elm, field)                                        \
-       do {                                                                   \
-               if (LIST_NEXT((elm), field) != NULL                            \
-                   && LIST_NEXT((elm), field)->field.le_prev                  \
-                              != &((elm)->field.le_next))                     \
-                       panic("Bad link elm %p next->prev != elm", (elm));     \
-       } while (0)
-
-#define QMD_LIST_CHECK_PREV(elm, field)                                        \
-       do {                                                                   \
-               if (*(elm)->field.le_prev != (elm))                            \
-                       panic("Bad link elm %p prev->next != elm", (elm));     \
+                       (head2)->sqh_last = &STAILQ_FIRST(head2);              \
        } while (0)
 #else
-#define        QMD_LIST_CHECK_HEAD(head, field)
-#define        QMD_LIST_CHECK_NEXT(elm, field)
-#define        QMD_LIST_CHECK_PREV(elm, field)
-#endif /* (_KERNEL && INVARIANTS) */
-
-#define        LIST_EMPTY(head)        ((head)->lh_first == NULL)
-
-#define        LIST_FIRST(head)        ((head)->lh_first)
-
-#define LIST_FOREACH(var, head, field)                                         \
-       for ((var) = LIST_FIRST((head)); (var); (var) = LIST_NEXT((var), field))
-
-#define LIST_FOREACH_SAFE(var, head, field, tvar)                              \
-       for ((var) = LIST_FIRST((head));                                       \
-            (var) && ((tvar) = LIST_NEXT((var), field), 1); (var) = (tvar))
-
-#define LIST_INIT(head)                                                        \
-       do {                                                                   \
-               LIST_FIRST((head)) = NULL;                                     \
-       } while (0)
-
-#define LIST_INSERT_AFTER(listelm, elm, field)                                 \
-       do {                                                                   \
-               QMD_LIST_CHECK_NEXT(listelm, field);                           \
-               if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field))    \
-                   != NULL)                                                   \
-                       LIST_NEXT((listelm), field)->field.le_prev =           \
-                               &LIST_NEXT((elm), field);                      \
-               LIST_NEXT((listelm), field) = (elm);                           \
-               (elm)->field.le_prev = &LIST_NEXT((listelm), field);           \
-       } while (0)
-
-#define LIST_INSERT_BEFORE(listelm, elm, field)                                \
-       do {                                                                   \
-               QMD_LIST_CHECK_PREV(listelm, field);                           \
-               (elm)->field.le_prev = (listelm)->field.le_prev;               \
-               LIST_NEXT((elm), field) = (listelm);                           \
-               *(listelm)->field.le_prev = (elm);                             \
-               (listelm)->field.le_prev = &LIST_NEXT((elm), field);           \
-       } while (0)
-
-#define LIST_INSERT_HEAD(head, elm, field)                                     \
-       do {                                                                   \
-               QMD_LIST_CHECK_HEAD((head), field);                            \
-               if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL)    \
-                       LIST_FIRST((head))->field.le_prev =                    \
-                               &LIST_NEXT((elm), field);                      \
-               LIST_FIRST((head)) = (elm);                                    \
-               (elm)->field.le_prev = &LIST_FIRST((head));                    \
-       } while (0)
-
-#define        LIST_NEXT(elm, field)   ((elm)->field.le_next)
-
-#define LIST_REMOVE(elm, field)                                                \
-       do {                                                                   \
-               QMD_SAVELINK(oldnext, (elm)->field.le_next);                   \
-               QMD_SAVELINK(oldprev, (elm)->field.le_prev);                   \
-               QMD_LIST_CHECK_NEXT(elm, field);                               \
-               QMD_LIST_CHECK_PREV(elm, field);                               \
-               if (LIST_NEXT((elm), field) != NULL)                           \
-                       LIST_NEXT((elm), field)->field.le_prev =               \
-                               (elm)->field.le_prev;                          \
-               *(elm)->field.le_prev = LIST_NEXT((elm), field);               \
-               TRASHIT(*oldnext);                                             \
-               TRASHIT(*oldprev);                                             \
-       } while (0)
-
-#define LIST_SWAP(head1, head2, type, field)                                   \
-       do {                                                                   \
-               struct type *swap_tmp = LIST_FIRST((head1));                   \
-               LIST_FIRST((head1)) = LIST_FIRST((head2));                     \
-               LIST_FIRST((head2)) = swap_tmp;                                \
-               if ((swap_tmp = LIST_FIRST((head1))) != NULL)                  \
-                       swap_tmp->field.le_prev = &LIST_FIRST((head1));        \
-               if ((swap_tmp = LIST_FIRST((head2))) != NULL)                  \
-                       swap_tmp->field.le_prev = &LIST_FIRST((head2));        \
-       } while (0)
-
-/*
- * Tail queue declarations.
- */
-#define TAILQ_HEAD(name, type)                                                 \
-       struct name {                                                          \
-               struct type *tqh_first; /* first element */                    \
-               struct type **tqh_last; /* addr of last next element */        \
-               TRACEBUF                                                       \
-       }
-
-#define TAILQ_HEAD_INITIALIZER(head)                                           \
-       {                                                                      \
-               NULL, &(head).tqh_first                                        \
-       }
-
-#define TAILQ_ENTRY(type)                                                      \
-       struct {                                                               \
-               struct type *tqe_next;  /* next element */                     \
-               struct type **tqe_prev; /* address of previous next element */ \
-               TRACEBUF                                                       \
-       }
-
-/*
- * Tail queue functions.
- */
-#if (defined(_KERNEL) && defined(INVARIANTS))
-#define QMD_TAILQ_CHECK_HEAD(head, field)                                      \
-       do {                                                                   \
-               if (!TAILQ_EMPTY(head)                                         \
-                   && TAILQ_FIRST((head))->field.tqe_prev                     \
-                              != &TAILQ_FIRST((head)))                        \
-                       panic("Bad tailq head %p first->prev != head",         \
-                             (head));                                         \
-       } while (0)
-
-#define QMD_TAILQ_CHECK_TAIL(head, field)                                      \
-       do {                                                                   \
-               if (*(head)->tqh_last != NULL)                                 \
-                       panic("Bad tailq NEXT(%p->tqh_last) != NULL", (head)); \
-       } while (0)
-
-#define QMD_TAILQ_CHECK_NEXT(elm, field)                                       \
-       do {                                                                   \
-               if (TAILQ_NEXT((elm), field) != NULL                           \
-                   && TAILQ_NEXT((elm), field)->field.tqe_prev                \
-                              != &((elm)->field.tqe_next))                    \
-                       panic("Bad link elm %p next->prev != elm", (elm));     \
-       } while (0)
-
-#define QMD_TAILQ_CHECK_PREV(elm, field)                                       \
-       do {                                                                   \
-               if (*(elm)->field.tqe_prev != (elm))                           \
-                       panic("Bad link elm %p prev->next != elm", (elm));     \
-       } while (0)
-#else
-#define        QMD_TAILQ_CHECK_HEAD(head, field)
-#define        QMD_TAILQ_CHECK_TAIL(head, headname)
-#define        QMD_TAILQ_CHECK_NEXT(elm, field)
-#define        QMD_TAILQ_CHECK_PREV(elm, field)
-#endif /* (_KERNEL && INVARIANTS) */
-
-#define TAILQ_CONCAT(head1, head2, field)                                      \
-       do {                                                                   \
-               if (!TAILQ_EMPTY(head2)) {                                     \
-                       *(head1)->tqh_last = (head2)->tqh_first;               \
-                       (head2)->tqh_first->field.tqe_prev =                   \
-                               (head1)->tqh_last;                             \
-                       (head1)->tqh_last = (head2)->tqh_last;                 \
-                       TAILQ_INIT((head2));                                   \
-                       QMD_TRACE_HEAD(head1);                                 \
-                       QMD_TRACE_HEAD(head2);                                 \
-               }                                                              \
-       } while (0)
-
-#define        TAILQ_EMPTY(head)       ((head)->tqh_first == NULL)
-
-#define        TAILQ_FIRST(head)       ((head)->tqh_first)
-
-#define TAILQ_FOREACH(var, head, field)                                        \
-       for ((var) = TAILQ_FIRST((head)); (var);                               \
-            (var) = TAILQ_NEXT((var), field))
-
-#define TAILQ_FOREACH_SAFE(var, head, field, tvar)                             \
-       for ((var) = TAILQ_FIRST((head));                                      \
-            (var) && ((tvar) = TAILQ_NEXT((var), field), 1); (var) = (tvar))
-
-#define TAILQ_FOREACH_REVERSE(var, head, headname, field)                      \
-       for ((var) = TAILQ_LAST((head), headname); (var);                      \
-            (var) = TAILQ_PREV((var), headname, field))
-
-#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar)           \
-       for ((var) = TAILQ_LAST((head), headname);                             \
-            (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1);        \
-            (var) = (tvar))
-
-#define TAILQ_INIT(head)                                                       \
-       do {                                                                   \
-               TAILQ_FIRST((head)) = NULL;                                    \
-               (head)->tqh_last = &TAILQ_FIRST((head));                       \
-               QMD_TRACE_HEAD(head);                                          \
-       } while (0)
-
-#define TAILQ_INSERT_AFTER(head, listelm, elm, field)                          \
-       do {                                                                   \
-               QMD_TAILQ_CHECK_NEXT(listelm, field);                          \
-               if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field))  \
-                   != NULL)                                                   \
-                       TAILQ_NEXT((elm), field)->field.tqe_prev =             \
-                               &TAILQ_NEXT((elm), field);                     \
-               else {                                                         \
-                       (head)->tqh_last = &TAILQ_NEXT((elm), field);          \
-                       QMD_TRACE_HEAD(head);                                  \
-               }                                                              \
-               TAILQ_NEXT((listelm), field) = (elm);                          \
-               (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field);         \
-               QMD_TRACE_ELEM(&(elm)->field);                                 \
-               QMD_TRACE_ELEM(&listelm->field);                               \
-       } while (0)
-
-#define TAILQ_INSERT_BEFORE(listelm, elm, field)                               \
-       do {                                                                   \
-               QMD_TAILQ_CHECK_PREV(listelm, field);                          \
-               (elm)->field.tqe_prev = (listelm)->field.tqe_prev;             \
-               TAILQ_NEXT((elm), field) = (listelm);                          \
-               *(listelm)->field.tqe_prev = (elm);                            \
-               (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field);         \
-               QMD_TRACE_ELEM(&(elm)->field);                                 \
-               QMD_TRACE_ELEM(&listelm->field);                               \
-       } while (0)
-
-#define TAILQ_INSERT_HEAD(head, elm, field)                                    \
-       do {                                                                   \
-               QMD_TAILQ_CHECK_HEAD(head, field);                             \
-               if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL)  \
-                       TAILQ_FIRST((head))->field.tqe_prev =                  \
-                               &TAILQ_NEXT((elm), field);                     \
-               else                                                           \
-                       (head)->tqh_last = &TAILQ_NEXT((elm), field);          \
-               TAILQ_FIRST((head)) = (elm);                                   \
-               (elm)->field.tqe_prev = &TAILQ_FIRST((head));                  \
-               QMD_TRACE_HEAD(head);                                          \
-               QMD_TRACE_ELEM(&(elm)->field);                                 \
-       } while (0)
-
-#define TAILQ_INSERT_TAIL(head, elm, field)                                    \
-       do {                                                                   \
-               QMD_TAILQ_CHECK_TAIL(head, field);                             \
-               TAILQ_NEXT((elm), field) = NULL;                               \
-               (elm)->field.tqe_prev = (head)->tqh_last;                      \
-               *(head)->tqh_last = (elm);                                     \
-               (head)->tqh_last = &TAILQ_NEXT((elm), field);                  \
-               QMD_TRACE_HEAD(head);                                          \
-               QMD_TRACE_ELEM(&(elm)->field);                                 \
-       } while (0)
-
-#define TAILQ_LAST(head, headname)                                             \
-       (*(((struct headname *)((head)->tqh_last))->tqh_last))
-
-#define        TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
-
-#define TAILQ_PREV(elm, headname, field)                                       \
-       (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
-
-#define TAILQ_REMOVE(head, elm, field)                                         \
-       do {                                                                   \
-               QMD_SAVELINK(oldnext, (elm)->field.tqe_next);                  \
-               QMD_SAVELINK(oldprev, (elm)->field.tqe_prev);                  \
-               QMD_TAILQ_CHECK_NEXT(elm, field);                              \
-               QMD_TAILQ_CHECK_PREV(elm, field);                              \
-               if ((TAILQ_NEXT((elm), field)) != NULL)                        \
-                       TAILQ_NEXT((elm), field)->field.tqe_prev =             \
-                               (elm)->field.tqe_prev;                         \
-               else {                                                         \
-                       (head)->tqh_last = (elm)->field.tqe_prev;              \
-                       QMD_TRACE_HEAD(head);                                  \
-               }                                                              \
-               *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field);             \
-               TRASHIT(*oldnext);                                             \
-               TRASHIT(*oldprev);                                             \
-               QMD_TRACE_ELEM(&(elm)->field);                                 \
-       } while (0)
-
-#define TAILQ_SWAP(head1, head2, type, field)                                  \
-       do {                                                                   \
-               struct type *swap_first = (head1)->tqh_first;                  \
-               struct type **swap_last = (head1)->tqh_last;                   \
-               (head1)->tqh_first = (head2)->tqh_first;                       \
-               (head1)->tqh_last = (head2)->tqh_last;                         \
-               (head2)->tqh_first = swap_first;                               \
-               (head2)->tqh_last = swap_last;                                 \
-               if ((swap_first = (head1)->tqh_first) != NULL)                 \
-                       swap_first->field.tqe_prev = &(head1)->tqh_first;      \
-               else                                                           \
-                       (head1)->tqh_last = &(head1)->tqh_first;               \
-               if ((swap_first = (head2)->tqh_first) != NULL)                 \
-                       swap_first->field.tqe_prev = &(head2)->tqh_first;      \
-               else                                                           \
-                       (head2)->tqh_last = &(head2)->tqh_first;               \
-       } while (0)
+#include "freebsd-queue.h"
+#endif /* defined(__OpenBSD__) && !defined(STAILQ_HEAD) */
 
-#endif /* !_SYS_QUEUE_H_ */
+#endif /* _FRR_QUEUE_H */
index 2a04fa23cb793f00fab46b7f05a5a97a221f47a8..d55f368dfb7f4cf0763d43a10dce400bab7d3d2a 100644 (file)
@@ -245,7 +245,7 @@ core_handler(int signo
 #endif
                            );
        /* dump memory stats on core */
-       log_memstats_stderr("core_handler");
+       log_memstats(stderr, "core_handler");
        abort();
 }
 
index d075e70d4e53bdc052b5676ca591ba21c1cdd492..92b7620edac5cd3ab3f76bb7f8dc379b93722557 100644 (file)
@@ -226,8 +226,9 @@ void spf_backoff_show(struct spf_backoff *backoff, struct vty *vty,
        if (backoff->t_holddown) {
                struct timeval remain =
                        thread_timer_remain(backoff->t_holddown);
-               vty_out(vty, "%s                   Still runs for %ld msec\n",
-                       prefix, remain.tv_sec * 1000 + remain.tv_usec / 1000);
+               vty_out(vty, "%s                   Still runs for %lld msec\n",
+                       prefix, (long long)remain.tv_sec * 1000
+                               + remain.tv_usec / 1000);
        } else {
                vty_out(vty, "%s                   Inactive\n", prefix);
        }
@@ -237,8 +238,9 @@ void spf_backoff_show(struct spf_backoff *backoff, struct vty *vty,
        if (backoff->t_timetolearn) {
                struct timeval remain =
                        thread_timer_remain(backoff->t_timetolearn);
-               vty_out(vty, "%s                   Still runs for %ld msec\n",
-                       prefix, remain.tv_sec * 1000 + remain.tv_usec / 1000);
+               vty_out(vty, "%s                   Still runs for %lld msec\n",
+                       prefix, (long long)remain.tv_sec * 1000
+                               + remain.tv_usec / 1000);
        } else {
                vty_out(vty, "%s                   Inactive\n", prefix);
        }
index 6a62cbb67856b2d823051a144b5332feef0f0f2f..5f38cc7a14f123c0efd83efcc17a245d78d87fee 100644 (file)
@@ -85,11 +85,13 @@ pkginclude_HEADERS += \
        lib/command.h \
        lib/command_graph.h \
        lib/command_match.h \
+       lib/compiler.h \
        lib/csv.h \
        lib/distribute.h \
        lib/event_counter.h \
        lib/fifo.h \
        lib/filter.h \
+       lib/freebsd-queue.h \
        lib/frr_pthread.h \
        lib/frratomic.h \
        lib/getopt.h \
@@ -125,6 +127,7 @@ pkginclude_HEADERS += \
        lib/ptm_lib.h \
        lib/pw.h \
        lib/qobj.h \
+       lib/queue.h \
        lib/routemap.h \
        lib/sbuf.h \
        lib/sha256.h \
@@ -180,6 +183,21 @@ lib_libfrrsnmp_la_SOURCES = \
        lib/snmp.c \
        # end
 
+#
+# ZeroMQ support
+#
+if ZEROMQ
+lib_LTLIBRARIES += lib/libfrrzmq.la
+pkginclude_HEADERS += lib/frr_zmq.h
+endif
+
+lib_libfrrzmq_la_CFLAGS = $(WERROR) $(ZEROMQ_CFLAGS)
+lib_libfrrzmq_la_LDFLAGS = -version-info 0:0:0
+lib_libfrrzmq_la_LIBADD = lib/libfrr.la $(ZEROMQ_LIBS)
+lib_libfrrzmq_la_SOURCES = \
+       lib/frr_zmq.c \
+       #end
+
 #
 # CLI utilities
 #
@@ -222,7 +240,6 @@ EXTRA_DIST += \
        lib/command_lex.h \
        lib/command_parse.h \
        lib/gitversion.pl \
-       lib/queue.h \
        lib/route_types.pl \
        lib/route_types.txt \
        # end
index 833adb9a3702de80abf67d53b6caef039d101066..67cf6aeec3481b7fcac2d1e49d2589b8777bcae1 100644 (file)
@@ -31,7 +31,6 @@
 DEFINE_MTYPE(LIB, ROUTE_TABLE, "Route table")
 DEFINE_MTYPE(LIB, ROUTE_NODE, "Route node")
 
-static void route_node_delete(struct route_node *);
 static void route_table_free(struct route_table *);
 
 static int route_table_hash_cmp(const void *a, const void *b)
@@ -187,23 +186,6 @@ static void set_link(struct route_node *node, struct route_node *new)
        new->parent = node;
 }
 
-/* Lock node. */
-struct route_node *route_lock_node(struct route_node *node)
-{
-       node->lock++;
-       return node;
-}
-
-/* Unlock node. */
-void route_unlock_node(struct route_node *node)
-{
-       assert(node->lock > 0);
-       node->lock--;
-
-       if (node->lock == 0)
-               route_node_delete(node);
-}
-
 /* Find matched prefix. */
 struct route_node *route_node_match(const struct route_table *table,
                                    union prefixconstptr pu)
@@ -348,7 +330,7 @@ struct route_node *route_node_get(struct route_table *const table,
 }
 
 /* Delete node from the routing table. */
-static void route_node_delete(struct route_node *node)
+void route_node_delete(struct route_node *node)
 {
        struct route_node *child;
        struct route_node *parent;
index b7b402a5914135a99a42b03a955b2d3d2d42dc31..9637fec1499ccb2e07a916cbab5e870adeaf0ded 100644 (file)
@@ -182,7 +182,6 @@ route_table_init_with_delegate(route_table_delegate_t *);
 extern route_table_delegate_t *route_table_get_default_delegate(void);
 
 extern void route_table_finish(struct route_table *);
-extern void route_unlock_node(struct route_node *node);
 extern struct route_node *route_top(struct route_table *);
 extern struct route_node *route_next(struct route_node *);
 extern struct route_node *route_next_until(struct route_node *,
@@ -193,7 +192,6 @@ extern struct route_node *route_node_lookup(const struct route_table *,
                                            union prefixconstptr);
 extern struct route_node *route_node_lookup_maynull(const struct route_table *,
                                                    union prefixconstptr);
-extern struct route_node *route_lock_node(struct route_node *node);
 extern struct route_node *route_node_match(const struct route_table *,
                                           union prefixconstptr);
 extern struct route_node *route_node_match_ipv4(const struct route_table *,
@@ -205,6 +203,7 @@ extern unsigned long route_table_count(const struct route_table *);
 
 extern struct route_node *route_node_create(route_table_delegate_t *,
                                            struct route_table *);
+extern void route_node_delete(struct route_node *);
 extern void route_node_destroy(route_table_delegate_t *, struct route_table *,
                               struct route_node *);
 
@@ -225,6 +224,23 @@ extern void route_table_iter_cleanup(route_table_iter_t *iter);
  * Inline functions.
  */
 
+/* Lock node. */
+static inline struct route_node *route_lock_node(struct route_node *node)
+{
+       (*(unsigned *)&node->lock)++;
+       return node;
+}
+
+/* Unlock node. */
+static inline void route_unlock_node(struct route_node *node)
+{
+       assert(node->lock > 0);
+       (*(unsigned *)&node->lock)--;
+
+       if (node->lock == 0)
+               route_node_delete(node);
+}
+
 /*
  * route_table_iter_next
  *
index f7aec431181263517c865edd06c77b4ab8abce39..ba85962cc92c0fc4d9ac864dcb8073f24b270d75 100644 (file)
@@ -31,48 +31,60 @@ struct ttable_style ttable_styles[] = {
                .corner = '+',
                .rownums_on = false,
                .indent = 1,
-               .border.top = '-',
-               .border.bottom = '-',
-               .border.left = '|',
-               .border.right = '|',
-               .border.top_on = true,
-               .border.bottom_on = true,
-               .border.left_on = true,
-               .border.right_on = true,
-               .cell.lpad = 1,
-               .cell.rpad = 1,
-               .cell.align = LEFT,
-               .cell.border.bottom = '-',
-               .cell.border.bottom_on = true,
-               .cell.border.top = '-',
-               .cell.border.top_on = false,
-               .cell.border.right = '|',
-               .cell.border.right_on = true,
-               .cell.border.left = '|',
-               .cell.border.left_on = false,
+               .border = {
+                       .top = '-',
+                       .bottom = '-',
+                       .left = '|',
+                       .right = '|',
+                       .top_on = true,
+                       .bottom_on = true,
+                       .left_on = true,
+                       .right_on = true,
+               },
+               .cell = {
+                       .lpad = 1,
+                       .rpad = 1,
+                       .align = LEFT,
+                       .border = {
+                               .bottom = '-',
+                               .bottom_on = true,
+                               .top = '-',
+                               .top_on = false,
+                               .right = '|',
+                               .right_on = true,
+                               .left = '|',
+                               .left_on = false,
+                       },
+               },
        }, {    // blank, suitable for plaintext alignment
                .corner = ' ',
                .rownums_on = false,
                .indent = 1,
-               .border.top = ' ',
-               .border.bottom = ' ',
-               .border.left = ' ',
-               .border.right = ' ',
-               .border.top_on = false,
-               .border.bottom_on = false,
-               .border.left_on = false,
-               .border.right_on = false,
-               .cell.lpad = 0,
-               .cell.rpad = 3,
-               .cell.align = LEFT,
-               .cell.border.bottom = ' ',
-               .cell.border.bottom_on = false,
-               .cell.border.top = ' ',
-               .cell.border.top_on = false,
-               .cell.border.right = ' ',
-               .cell.border.right_on = false,
-               .cell.border.left = ' ',
-               .cell.border.left_on = false,
+               .border = {
+                       .top = ' ',
+                       .bottom = ' ',
+                       .left = ' ',
+                       .right = ' ',
+                       .top_on = false,
+                       .bottom_on = false,
+                       .left_on = false,
+                       .right_on = false,
+               },
+               .cell = {
+                       .lpad = 0,
+                       .rpad = 3,
+                       .align = LEFT,
+                       .border = {
+                               .bottom = ' ',
+                               .bottom_on = false,
+                               .top = ' ',
+                               .top_on = false,
+                               .right = ' ',
+                               .right_on = false,
+                               .left = ' ',
+                               .left_on = false,
+                       },
+               }
    }
 };
 /* clang-format on */
index dcb8da225d2fadede770f699831dc5bbd64a3147..9acd62af3cb1a6268cff82bef12495d42e2af73a 100644 (file)
--- a/lib/vty.h
+++ b/lib/vty.h
@@ -25,6 +25,7 @@
 #include "log.h"
 #include "sockunion.h"
 #include "qobj.h"
+#include "compiler.h"
 
 #define VTY_BUFSIZ 4096
 #define VTY_MAXHIST 20
@@ -182,23 +183,11 @@ struct vty_arg {
 /* Integrated configuration file. */
 #define INTEGRATE_DEFAULT_CONFIG "frr.conf"
 
-/* for compatibility */
-#if defined(__ICC)
-#define CPP_WARN_STR(X) #X
-#define CPP_WARN(text) _Pragma(CPP_WARN_STR(message __FILE__ ": " text))
-
-#elif (defined(__GNUC__)                                                       \
-       && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)))           \
-       || (defined(__clang__)                                                 \
-           && (__clang_major__ >= 4                                           \
-               || (__clang_major__ == 3 && __clang_minor__ >= 5)))
-#define CPP_WARN_STR(X) #X
-#define CPP_WARN(text) _Pragma(CPP_WARN_STR(GCC warning text))
-
-#else
-#define CPP_WARN(text)
+#if CONFDATE > 20180401
+CPP_NOTICE("It's probably time to remove VTY_NEWLINE compatibility foo.")
 #endif
 
+/* for compatibility */
 #define VNL "\n" CPP_WARN("VNL has been replaced with \\n.")
 #define VTYNL "\n" CPP_WARN("VTYNL has been replaced with \\n.")
 #define VTY_NEWLINE "\n" CPP_WARN("VTY_NEWLINE has been replaced with \\n.")
index 612421c80b5fd723696fcdbf5d67d0f9956222f0..b76b73b367b5484379f0be7fa4b60fa53f576b01 100644 (file)
@@ -72,14 +72,7 @@ struct work_queue *work_queue_new(struct thread_master *m,
        new->master = m;
        SET_FLAG(new->flags, WQ_UNPLUGGED);
 
-       if ((new->items = list_new()) == NULL) {
-               XFREE(MTYPE_WORK_QUEUE_NAME, new->name);
-               XFREE(MTYPE_WORK_QUEUE, new);
-
-               return NULL;
-       }
-
-       new->items->del = (void (*)(void *))work_queue_item_free;
+       STAILQ_INIT(&new->items);
 
        listnode_add(work_queues, new);
 
@@ -97,8 +90,6 @@ void work_queue_free(struct work_queue *wq)
        if (wq->thread != NULL)
                thread_cancel(wq->thread);
 
-       /* list_delete frees items via callback */
-       list_delete(wq->items);
        listnode_delete(work_queues, wq);
 
        XFREE(MTYPE_WORK_QUEUE_NAME, wq->name);
@@ -114,8 +105,8 @@ bool work_queue_is_scheduled(struct work_queue *wq)
 static int work_queue_schedule(struct work_queue *wq, unsigned int delay)
 {
        /* if appropriate, schedule work queue thread */
-       if (CHECK_FLAG(wq->flags, WQ_UNPLUGGED) && (wq->thread == NULL)
-           && (listcount(wq->items) > 0)) {
+       if (CHECK_FLAG(wq->flags, WQ_UNPLUGGED) && (wq->thread == NULL) &&
+           !work_queue_empty(wq)) {
                wq->thread = NULL;
                thread_add_timer_msec(wq->master, work_queue_run, wq, delay,
                                      &wq->thread);
@@ -139,33 +130,35 @@ void work_queue_add(struct work_queue *wq, void *data)
        }
 
        item->data = data;
-       listnode_add(wq->items, item);
+       work_queue_item_enqueue(wq, item);
 
        work_queue_schedule(wq, wq->spec.hold);
 
        return;
 }
 
-static void work_queue_item_remove(struct work_queue *wq, struct listnode *ln)
+static void work_queue_item_remove(struct work_queue *wq,
+                                  struct work_queue_item *item)
 {
-       struct work_queue_item *item = listgetdata(ln);
-
        assert(item && item->data);
 
        /* call private data deletion callback if needed */
        if (wq->spec.del_item_data)
                wq->spec.del_item_data(wq, item->data);
 
-       list_delete_node(wq->items, ln);
+       work_queue_item_dequeue(wq, item);
+
        work_queue_item_free(item);
 
        return;
 }
 
-static void work_queue_item_requeue(struct work_queue *wq, struct listnode *ln)
+static void work_queue_item_requeue(struct work_queue *wq, struct work_queue_item *item)
 {
-       LISTNODE_DETACH(wq->items, ln);
-       LISTNODE_ATTACH(wq->items, ln); /* attach to end of list */
+       work_queue_item_dequeue(wq, item);
+
+       /* attach to end of list */
+       work_queue_item_enqueue(wq, item);
 }
 
 DEFUN (show_work_queues,
@@ -186,7 +179,7 @@ DEFUN (show_work_queues,
        for (ALL_LIST_ELEMENTS_RO(work_queues, node, wq)) {
                vty_out(vty, "%c %8d %5d %8ld %8ld %7d %6d %8ld %6u %s\n",
                        (CHECK_FLAG(wq->flags, WQ_UNPLUGGED) ? ' ' : 'P'),
-                       listcount(wq->items), wq->spec.hold, wq->runs,
+                       work_queue_item_count(wq), wq->spec.hold, wq->runs,
                        wq->yields, wq->cycles.best, wq->cycles.granularity,
                        wq->cycles.total,
                        (wq->runs) ? (unsigned int)(wq->cycles.total / wq->runs)
@@ -233,16 +226,15 @@ void work_queue_unplug(struct work_queue *wq)
 int work_queue_run(struct thread *thread)
 {
        struct work_queue *wq;
-       struct work_queue_item *item;
+       struct work_queue_item *item, *titem;
        wq_item_status ret;
        unsigned int cycles = 0;
-       struct listnode *node, *nnode;
        char yielded = 0;
 
        wq = THREAD_ARG(thread);
        wq->thread = NULL;
 
-       assert(wq && wq->items);
+       assert(wq);
 
        /* calculate cycle granularity:
         * list iteration == 1 run
@@ -266,7 +258,7 @@ int work_queue_run(struct thread *thread)
        if (wq->cycles.granularity == 0)
                wq->cycles.granularity = WORK_QUEUE_MIN_GRANULARITY;
 
-       for (ALL_LIST_ELEMENTS(wq->items, node, nnode, item)) {
+       STAILQ_FOREACH_SAFE(item, &wq->items, wq, titem) {
                assert(item && item->data);
 
                /* dont run items which are past their allowed retries */
@@ -274,7 +266,7 @@ int work_queue_run(struct thread *thread)
                        /* run error handler, if any */
                        if (wq->spec.errorfunc)
                                wq->spec.errorfunc(wq, item->data);
-                       work_queue_item_remove(wq, node);
+                       work_queue_item_remove(wq, item);
                        continue;
                }
 
@@ -298,7 +290,7 @@ int work_queue_run(struct thread *thread)
                }
                case WQ_REQUEUE: {
                        item->ran--;
-                       work_queue_item_requeue(wq, node);
+                       work_queue_item_requeue(wq, item);
                        /* If a single node is being used with a meta-queue
                         * (e.g., zebra),
                         * update the next node as we don't want to exit the
@@ -309,8 +301,8 @@ int work_queue_run(struct thread *thread)
                         * will kick in
                         * to terminate the thread when time has exceeded.
                         */
-                       if (nnode == NULL)
-                               nnode = node;
+                       if (titem == NULL)
+                               titem = item;
                        break;
                }
                case WQ_RETRY_NOW:
@@ -323,7 +315,7 @@ int work_queue_run(struct thread *thread)
                /* fallthru */
                case WQ_SUCCESS:
                default: {
-                       work_queue_item_remove(wq, node);
+                       work_queue_item_remove(wq, item);
                        break;
                }
                }
@@ -376,7 +368,7 @@ stats:
 #endif
 
        /* Is the queue done yet? If it is, call the completion callback. */
-       if (listcount(wq->items) > 0)
+       if (!work_queue_empty(wq))
                work_queue_schedule(wq, 0);
        else if (wq->spec.completion_func)
                wq->spec.completion_func(wq);
index ff7f57690dd93721be68b5964fbe149508e0d1a1..df35d44fbcb9a67d48c33c9cf01e77992e8afbb0 100644 (file)
@@ -24,6 +24,7 @@
 #define _QUAGGA_WORK_QUEUE_H
 
 #include "memory.h"
+#include "queue.h"
 DECLARE_MTYPE(WORK_QUEUE)
 
 /* Hold time for the initial schedule of a queue run, in  millisec */
@@ -43,6 +44,7 @@ typedef enum {
 
 /* A single work queue item, unsurprisingly */
 struct work_queue_item {
+       STAILQ_ENTRY(work_queue_item) wq;
        void *data;      /* opaque data */
        unsigned short ran; /* # of times item has been run */
 };
@@ -91,7 +93,8 @@ struct work_queue {
        } spec;
 
        /* remaining fields should be opaque to users */
-       struct list *items;   /* queue item list */
+       STAILQ_HEAD(work_queue_items, work_queue_item) items; /* queue item list */
+       int item_count; /* queued items */
        unsigned long runs;   /* runs count */
        unsigned long yields; /* yields count */
 
@@ -107,6 +110,37 @@ struct work_queue {
 
 /* User API */
 
+static inline int work_queue_item_count(struct work_queue *wq)
+{
+       return wq->item_count;
+}
+
+static inline bool work_queue_empty(struct work_queue *wq)
+{
+       return (wq->item_count == 0) ? true : false;
+}
+
+static inline struct work_queue_item *work_queue_last_item(struct work_queue *wq)
+{
+       return STAILQ_LAST(&wq->items, work_queue_item, wq);
+}
+
+static inline void work_queue_item_enqueue(struct work_queue *wq,
+                                          struct work_queue_item *item)
+{
+       STAILQ_INSERT_TAIL(&wq->items, item, wq);
+       wq->item_count++;
+}
+
+static inline void work_queue_item_dequeue(struct work_queue *wq,
+                                          struct work_queue_item *item)
+{
+       assert(wq->item_count > 0);
+
+       wq->item_count--;
+       STAILQ_REMOVE(&wq->items, item, work_queue_item, wq);
+}
+
 /* create a new work queue, of given name.
  * user must fill in the spec of the returned work queue before adding
  * anything to it
index 24cb69919649d805be3cdf35c58ce7ea939145e1..72fa2679b320a7f1b1f3ee47270493af5cac24b0 100644 (file)
@@ -352,10 +352,6 @@ void zclient_send_reg_requests(struct zclient *zclient, vrf_id_t vrf_id)
        int i;
        afi_t afi;
 
-       /* zclient is disabled. */
-       if (!zclient->enable)
-               return;
-
        /* If not connected to the zebra yet. */
        if (zclient->sock < 0)
                return;
@@ -418,10 +414,6 @@ void zclient_send_dereg_requests(struct zclient *zclient, vrf_id_t vrf_id)
        int i;
        afi_t afi;
 
-       /* zclient is disabled. */
-       if (!zclient->enable)
-               return;
-
        /* If not connected to the zebra yet. */
        if (zclient->sock < 0)
                return;
@@ -485,10 +477,6 @@ void zclient_send_interface_radv_req(struct zclient *zclient, vrf_id_t vrf_id,
 {
        struct stream *s;
 
-       /* zclient is disabled. */
-       if (!zclient->enable)
-               return;
-
        /* If not connected to the zebra yet. */
        if (zclient->sock < 0)
                return;
@@ -516,10 +504,6 @@ int zclient_start(struct zclient *zclient)
        if (zclient_debug)
                zlog_info("zclient_start is called");
 
-       /* zclient is disabled. */
-       if (!zclient->enable)
-               return 0;
-
        /* If already connected to the zebra. */
        if (zclient->sock >= 0)
                return 0;
@@ -564,9 +548,6 @@ void zclient_init(struct zclient *zclient, int redist_default, u_short instance)
 {
        int afi, i;
 
-       /* Enable zebra client connection by default. */
-       zclient->enable = 1;
-
        /* Set -1 to the default socket value. */
        zclient->sock = -1;
 
@@ -911,24 +892,23 @@ int zapi_ipv6_route(u_char cmd, struct zclient *zclient, struct prefix_ipv6 *p,
        return zclient_send_message(zclient);
 }
 
-int zapi_route(u_char cmd, struct zclient *zclient, struct prefix *p,
-              struct prefix_ipv6 *src_p, struct zapi_route *api)
+int zclient_route_send(u_char cmd, struct zclient *zclient,
+                      struct zapi_route *api)
 {
+       if (zapi_route_encode(cmd, zclient->obuf, api) < 0)
+               return -1;
+       return zclient_send_message(zclient);
+}
+
+int zapi_route_encode(u_char cmd, struct stream *s, struct zapi_route *api)
+{
+       struct zapi_nexthop *api_nh;
        int i;
        int psize;
-       struct stream *s;
 
-       /* either we have !SRCPFX && src_p == NULL, or SRCPFX && src_p != NULL
-        */
-       assert(!(api->message & ZAPI_MESSAGE_SRCPFX) == !src_p);
-
-       /* Reset stream. */
-       s = zclient->obuf;
        stream_reset(s);
-
        zclient_create_header(s, cmd, api->vrf_id);
 
-       /* Put type and nexthop. */
        stream_putc(s, api->type);
        stream_putw(s, api->instance);
        stream_putl(s, api->flags);
@@ -936,72 +916,84 @@ int zapi_route(u_char cmd, struct zclient *zclient, struct prefix *p,
        stream_putw(s, api->safi);
 
        /* Put prefix information. */
-       psize = PSIZE(p->prefixlen);
-       stream_putc(s, p->prefixlen);
-       stream_write(s, (u_char *)&p->u.prefix, psize);
+       stream_putc(s, api->prefix.family);
+       psize = PSIZE(api->prefix.prefixlen);
+       stream_putc(s, api->prefix.prefixlen);
+       stream_write(s, (u_char *)&api->prefix.u.prefix, psize);
 
        if (CHECK_FLAG(api->message, ZAPI_MESSAGE_SRCPFX)) {
-               psize = PSIZE(src_p->prefixlen);
-               stream_putc(s, src_p->prefixlen);
-               stream_write(s, (u_char *)&src_p->prefix, psize);
+               psize = PSIZE(api->src_prefix.prefixlen);
+               stream_putc(s, api->src_prefix.prefixlen);
+               stream_write(s, (u_char *)&api->src_prefix.prefix, psize);
        }
 
-       /* Nexthop, ifindex, distance and metric information. */
+       /* Nexthops.  */
        if (CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) {
-               stream_putc(s, api->nexthop_num);
+               /* limit the number of nexthops if necessary */
+               if (api->nexthop_num > MULTIPATH_NUM) {
+                       char buf[PREFIX2STR_BUFFER];
+
+                       prefix2str(&api->prefix, buf, sizeof(buf));
+                       zlog_warn(
+                               "%s: prefix %s: encoding %u nexthops out of %u",
+                               __func__, buf, MULTIPATH_NUM, api->nexthop_num);
+                       api->nexthop_num = MULTIPATH_NUM;
+               }
+
+               stream_putw(s, api->nexthop_num);
 
                for (i = 0; i < api->nexthop_num; i++) {
-                       stream_putc(s, api->nexthop[i]->type);
-                       switch (api->nexthop[i]->type) {
+                       api_nh = &api->nexthops[i];
+
+                       stream_putc(s, api_nh->type);
+                       switch (api_nh->type) {
                        case NEXTHOP_TYPE_BLACKHOLE:
                                break;
                        case NEXTHOP_TYPE_IPV4:
-                               stream_put_in_addr(s,
-                                                  &api->nexthop[i]->gate.ipv4);
-
-                               /* For labeled-unicast, each nexthop is followed
-                                * by label. */
-                               if (CHECK_FLAG(api->message,
-                                              ZAPI_MESSAGE_LABEL))
-                                       stream_putl(
-                                               s,
-                                               api->nexthop[i]
-                                                       ->nh_label->label[0]);
+                               stream_put_in_addr(s, &api_nh->gate.ipv4);
                                break;
                        case NEXTHOP_TYPE_IPV4_IFINDEX:
-                               stream_put_in_addr(s,
-                                                  &api->nexthop[i]->gate.ipv4);
-                               stream_putl(s, api->nexthop[i]->ifindex);
+                               stream_put_in_addr(s, &api_nh->gate.ipv4);
+                               stream_putl(s, api_nh->ifindex);
                                break;
                        case NEXTHOP_TYPE_IFINDEX:
-                               stream_putl(s, api->nexthop[i]->ifindex);
+                               stream_putl(s, api_nh->ifindex);
                                break;
                        case NEXTHOP_TYPE_IPV6:
-                               stream_write(
-                                       s,
-                                       (u_char *)&api->nexthop[i]->gate.ipv6,
-                                       16);
-
-                               /* For labeled-unicast, each nexthop is followed
-                                * by label. */
-                               if (CHECK_FLAG(api->message,
-                                              ZAPI_MESSAGE_LABEL))
-                                       stream_putl(
-                                               s,
-                                               api->nexthop[i]
-                                                       ->nh_label->label[0]);
+                               stream_write(s, (u_char *)&api_nh->gate.ipv6,
+                                            16);
                                break;
                        case NEXTHOP_TYPE_IPV6_IFINDEX:
-                               stream_write(
-                                       s,
-                                       (u_char *)&api->nexthop[i]->gate.ipv6,
-                                       16);
-                               stream_putl(s, api->nexthop[i]->ifindex);
+                               stream_write(s, (u_char *)&api_nh->gate.ipv6,
+                                            16);
+                               stream_putl(s, api_nh->ifindex);
                                break;
                        }
+
+                       /* MPLS labels for BGP-LU or Segment Routing */
+                       if (CHECK_FLAG(api->message, ZAPI_MESSAGE_LABEL)) {
+                               if (api_nh->label_num > MPLS_MAX_LABELS) {
+                                       char buf[PREFIX2STR_BUFFER];
+                                       prefix2str(&api->prefix, buf,
+                                                  sizeof(buf));
+                                       zlog_err(
+                                               "%s: prefix %s: can't encode "
+                                               "%u labels (maximum is %u)",
+                                               __func__, buf,
+                                               api_nh->label_num,
+                                               MPLS_MAX_LABELS);
+                                       return -1;
+                               }
+
+                               stream_putc(s, api_nh->label_num);
+                               stream_put(s, &api_nh->labels[0],
+                                          api_nh->label_num
+                                                  * sizeof(mpls_label_t));
+                       }
                }
        }
 
+       /* Attributes. */
        if (CHECK_FLAG(api->message, ZAPI_MESSAGE_DISTANCE))
                stream_putc(s, api->distance);
        if (CHECK_FLAG(api->message, ZAPI_MESSAGE_METRIC))
@@ -1014,7 +1006,110 @@ int zapi_route(u_char cmd, struct zclient *zclient, struct prefix *p,
        /* Put length at the first point of the stream. */
        stream_putw_at(s, 0, stream_get_endp(s));
 
-       return zclient_send_message(zclient);
+       return 0;
+}
+
+int zapi_route_decode(struct stream *s, struct zapi_route *api)
+{
+       struct zapi_nexthop *api_nh;
+       int i;
+
+       memset(api, 0, sizeof(*api));
+
+       /* Type, flags, message. */
+       api->type = stream_getc(s);
+       api->instance = stream_getw(s);
+       api->flags = stream_getl(s);
+       api->message = stream_getc(s);
+       api->safi = stream_getw(s);
+
+       /* Prefix. */
+       api->prefix.family = stream_getc(s);
+       switch (api->prefix.family) {
+       case AF_INET:
+               api->prefix.prefixlen = MIN(IPV4_MAX_PREFIXLEN, stream_getc(s));
+               break;
+       case AF_INET6:
+               api->prefix.prefixlen = MIN(IPV6_MAX_PREFIXLEN, stream_getc(s));
+               break;
+       }
+       stream_get(&api->prefix.u.prefix, s, PSIZE(api->prefix.prefixlen));
+       if (CHECK_FLAG(api->message, ZAPI_MESSAGE_SRCPFX)) {
+               api->src_prefix.family = AF_INET6;
+               api->src_prefix.prefixlen = stream_getc(s);
+               stream_get(&api->src_prefix.prefix, s,
+                          PSIZE(api->src_prefix.prefixlen));
+
+               if (api->prefix.family != AF_INET6
+                   || api->src_prefix.prefixlen == 0)
+                       UNSET_FLAG(api->message, ZAPI_MESSAGE_SRCPFX);
+       }
+
+       /* Nexthops. */
+       if (CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) {
+               api->nexthop_num = stream_getw(s);
+               if (api->nexthop_num > MULTIPATH_NUM) {
+                       zlog_warn("%s: invalid number of nexthops (%u)",
+                                 __func__, api->nexthop_num);
+                       return -1;
+               }
+
+               for (i = 0; i < api->nexthop_num; i++) {
+                       api_nh = &api->nexthops[i];
+
+                       api_nh->type = stream_getc(s);
+                       switch (api_nh->type) {
+                       case NEXTHOP_TYPE_BLACKHOLE:
+                               break;
+                       case NEXTHOP_TYPE_IPV4:
+                               api_nh->gate.ipv4.s_addr = stream_get_ipv4(s);
+                               break;
+                       case NEXTHOP_TYPE_IPV4_IFINDEX:
+                               api_nh->gate.ipv4.s_addr = stream_get_ipv4(s);
+                               api_nh->ifindex = stream_getl(s);
+                               break;
+                       case NEXTHOP_TYPE_IFINDEX:
+                               api_nh->ifindex = stream_getl(s);
+                               break;
+                       case NEXTHOP_TYPE_IPV6:
+                               stream_get(&api_nh->gate.ipv6, s, 16);
+                               break;
+                       case NEXTHOP_TYPE_IPV6_IFINDEX:
+                               stream_get(&api_nh->gate.ipv6, s, 16);
+                               api_nh->ifindex = stream_getl(s);
+                               break;
+                       }
+
+                       /* MPLS labels for BGP-LU or Segment Routing */
+                       if (CHECK_FLAG(api->message, ZAPI_MESSAGE_LABEL)) {
+                               api_nh->label_num = stream_getc(s);
+
+                               if (api_nh->label_num > MPLS_MAX_LABELS) {
+                                       zlog_warn(
+                                               "%s: invalid number of MPLS "
+                                               "labels (%u)",
+                                               __func__, api_nh->label_num);
+                                       return -1;
+                               }
+
+                               stream_get(&api_nh->labels[0], s,
+                                          api_nh->label_num
+                                                  * sizeof(mpls_label_t));
+                       }
+               }
+       }
+
+       /* Attributes. */
+       if (CHECK_FLAG(api->message, ZAPI_MESSAGE_DISTANCE))
+               api->distance = stream_getc(s);
+       if (CHECK_FLAG(api->message, ZAPI_MESSAGE_METRIC))
+               api->metric = stream_getl(s);
+       if (CHECK_FLAG(api->message, ZAPI_MESSAGE_TAG))
+               api->tag = stream_getl(s);
+       if (CHECK_FLAG(api->message, ZAPI_MESSAGE_MTU))
+               api->mtu = stream_getl(s);
+
+       return 0;
 }
 
 /*
@@ -2017,25 +2112,15 @@ static int zclient_read(struct thread *thread)
                        (*zclient->bfd_dest_replay)(command, zclient, length,
                                                    vrf_id);
                break;
-       case ZEBRA_REDISTRIBUTE_IPV4_ADD:
-               if (zclient->redistribute_route_ipv4_add)
-                       (*zclient->redistribute_route_ipv4_add)(
-                               command, zclient, length, vrf_id);
+       case ZEBRA_REDISTRIBUTE_ROUTE_ADD:
+               if (zclient->redistribute_route_add)
+                       (*zclient->redistribute_route_add)(command, zclient,
+                                                          length, vrf_id);
                break;
-       case ZEBRA_REDISTRIBUTE_IPV4_DEL:
-               if (zclient->redistribute_route_ipv4_del)
-                       (*zclient->redistribute_route_ipv4_del)(
-                               command, zclient, length, vrf_id);
-               break;
-       case ZEBRA_REDISTRIBUTE_IPV6_ADD:
-               if (zclient->redistribute_route_ipv6_add)
-                       (*zclient->redistribute_route_ipv6_add)(
-                               command, zclient, length, vrf_id);
-               break;
-       case ZEBRA_REDISTRIBUTE_IPV6_DEL:
-               if (zclient->redistribute_route_ipv6_del)
-                       (*zclient->redistribute_route_ipv6_del)(
-                               command, zclient, length, vrf_id);
+       case ZEBRA_REDISTRIBUTE_ROUTE_DEL:
+               if (zclient->redistribute_route_del)
+                       (*zclient->redistribute_route_del)(command, zclient,
+                                                          length, vrf_id);
                break;
        case ZEBRA_INTERFACE_LINK_PARAMS:
                if (zclient->interface_link_params)
index 15d1858d84aea8d4c5cd5269c13cb112955a8510..7c4780201e07a434c9856779448d05b61b875e29 100644 (file)
@@ -21,7 +21,7 @@
 #ifndef _ZEBRA_ZCLIENT_H
 #define _ZEBRA_ZCLIENT_H
 
-/* For struct zapi_ipv{4,6}. */
+/* For struct zapi_route. */
 #include "prefix.h"
 
 /* For struct interface and struct connected. */
@@ -59,6 +59,8 @@ typedef enum {
        ZEBRA_INTERFACE_UP,
        ZEBRA_INTERFACE_DOWN,
        ZEBRA_INTERFACE_SET_MASTER,
+       ZEBRA_ROUTE_ADD,
+       ZEBRA_ROUTE_DELETE,
        ZEBRA_IPV4_ROUTE_ADD,
        ZEBRA_IPV4_ROUTE_DELETE,
        ZEBRA_IPV6_ROUTE_ADD,
@@ -85,10 +87,8 @@ typedef enum {
        ZEBRA_BFD_DEST_DEREGISTER,
        ZEBRA_BFD_DEST_UPDATE,
        ZEBRA_BFD_DEST_REPLAY,
-       ZEBRA_REDISTRIBUTE_IPV4_ADD,
-       ZEBRA_REDISTRIBUTE_IPV4_DEL,
-       ZEBRA_REDISTRIBUTE_IPV6_ADD,
-       ZEBRA_REDISTRIBUTE_IPV6_DEL,
+       ZEBRA_REDISTRIBUTE_ROUTE_ADD,
+       ZEBRA_REDISTRIBUTE_ROUTE_DEL,
        ZEBRA_VRF_UNREGISTER,
        ZEBRA_VRF_ADD,
        ZEBRA_VRF_DELETE,
@@ -100,10 +100,6 @@ typedef enum {
        ZEBRA_INTERFACE_LINK_PARAMS,
        ZEBRA_MPLS_LABELS_ADD,
        ZEBRA_MPLS_LABELS_DELETE,
-       ZEBRA_IPV4_NEXTHOP_ADD,
-       ZEBRA_IPV4_NEXTHOP_DELETE,
-       ZEBRA_IPV6_NEXTHOP_ADD,
-       ZEBRA_IPV6_NEXTHOP_DELETE,
        ZEBRA_IPMR_ROUTE_STATS,
        ZEBRA_LABEL_MANAGER_CONNECT,
        ZEBRA_GET_LABEL_CHUNK,
@@ -141,10 +137,6 @@ struct zclient {
        /* Socket to zebra daemon. */
        int sock;
 
-       /* Flag of communication to zebra is enabled or not.  Default is on.
-          This flag is disabled by `no router zebra' statement. */
-       int enable;
-
        /* Connection failure count. */
        int fail;
 
@@ -194,14 +186,10 @@ struct zclient {
        int (*nexthop_update)(int, struct zclient *, uint16_t, vrf_id_t);
        int (*import_check_update)(int, struct zclient *, uint16_t, vrf_id_t);
        int (*bfd_dest_replay)(int, struct zclient *, uint16_t, vrf_id_t);
-       int (*redistribute_route_ipv4_add)(int, struct zclient *, uint16_t,
-                                          vrf_id_t);
-       int (*redistribute_route_ipv4_del)(int, struct zclient *, uint16_t,
-                                          vrf_id_t);
-       int (*redistribute_route_ipv6_add)(int, struct zclient *, uint16_t,
-                                          vrf_id_t);
-       int (*redistribute_route_ipv6_del)(int, struct zclient *, uint16_t,
-                                          vrf_id_t);
+       int (*redistribute_route_add)(int, struct zclient *, uint16_t,
+                                     vrf_id_t);
+       int (*redistribute_route_del)(int, struct zclient *, uint16_t,
+                                     vrf_id_t);
        int (*fec_update)(int, struct zclient *, uint16_t);
        int (*local_vni_add)(int, struct zclient *, uint16_t, vrf_id_t);
        int (*local_vni_del)(int, struct zclient *, uint16_t, vrf_id_t);
@@ -212,13 +200,12 @@ struct zclient {
 
 /* Zebra API message flag. */
 #define ZAPI_MESSAGE_NEXTHOP  0x01
-#define ZAPI_MESSAGE_IFINDEX  0x02
-#define ZAPI_MESSAGE_DISTANCE 0x04
-#define ZAPI_MESSAGE_METRIC   0x08
-#define ZAPI_MESSAGE_TAG      0x10
-#define ZAPI_MESSAGE_MTU      0x20
-#define ZAPI_MESSAGE_SRCPFX   0x40
-#define ZAPI_MESSAGE_LABEL    0x80
+#define ZAPI_MESSAGE_DISTANCE 0x02
+#define ZAPI_MESSAGE_METRIC   0x04
+#define ZAPI_MESSAGE_TAG      0x08
+#define ZAPI_MESSAGE_MTU      0x10
+#define ZAPI_MESSAGE_SRCPFX   0x20
+#define ZAPI_MESSAGE_LABEL    0x40
 
 /* Zserv protocol message header */
 struct zserv_header {
@@ -232,6 +219,16 @@ struct zserv_header {
        uint16_t command;
 };
 
+struct zapi_nexthop {
+       enum nexthop_types_t type;
+       ifindex_t ifindex;
+       union g_addr gate;
+
+       /* MPLS labels for BGP-LU or Segment Routing */
+       uint8_t label_num;
+       mpls_label_t labels[MPLS_MAX_LABELS];
+};
+
 struct zapi_route {
        u_char type;
        u_short instance;
@@ -242,8 +239,11 @@ struct zapi_route {
 
        safi_t safi;
 
-       u_char nexthop_num;
-       struct nexthop **nexthop;
+       struct prefix prefix;
+       struct prefix_ipv6 src_prefix;
+
+       u_int16_t nexthop_num;
+       struct zapi_nexthop nexthops[MULTIPATH_NUM];
 
        u_char distance;
 
@@ -369,7 +369,7 @@ extern struct interface *zebra_interface_vrf_update_read(struct stream *s,
 extern void zebra_interface_if_set_value(struct stream *, struct interface *);
 extern void zebra_router_id_update_read(struct stream *s, struct prefix *rid);
 extern int zapi_ipv4_route(u_char, struct zclient *, struct prefix_ipv4 *,
-                          struct zapi_ipv4 *);
+                          struct zapi_ipv4 *) __attribute__((deprecated));
 
 extern struct interface *zebra_interface_link_params_read(struct stream *);
 extern size_t zebra_interface_link_params_write(struct stream *,
@@ -420,11 +420,13 @@ struct zapi_ipv6 {
 
 extern int zapi_ipv6_route(u_char cmd, struct zclient *zclient,
                           struct prefix_ipv6 *p, struct prefix_ipv6 *src_p,
-                          struct zapi_ipv6 *api);
+                          struct zapi_ipv6 *api) __attribute__((deprecated));
 extern int zapi_ipv4_route_ipv6_nexthop(u_char, struct zclient *,
                                        struct prefix_ipv4 *,
-                                       struct zapi_ipv6 *);
-extern int zapi_route(u_char cmd, struct zclient *zclient, struct prefix *p,
-                     struct prefix_ipv6 *src_p, struct zapi_route *api);
+                                       struct zapi_ipv6 *)
+       __attribute__((deprecated));
+extern int zclient_route_send(u_char, struct zclient *, struct zapi_route *);
+extern int zapi_route_encode(u_char, struct stream *, struct zapi_route *);
+extern int zapi_route_decode(struct stream *, struct zapi_route *);
 
 #endif /* _ZEBRA_ZCLIENT_H */
index 58ad1675498da2c1af91be0fb8d0b584ea17eb3b..a46962c91af37a41e073e3e91d2eab1fe344ad49 100644 (file)
@@ -48,8 +48,8 @@ static int nhrp_if_delete_hook(struct interface *ifp)
 
 void nhrp_interface_init(void)
 {
-       if_add_hook(IF_NEW_HOOK,    nhrp_if_new_hook);
-       if_add_hook(IF_DELETE_HOOK, nhrp_if_delete_hook);
+       hook_register_prio(if_add, 0, nhrp_if_new_hook);
+       hook_register_prio(if_del, 0, nhrp_if_delete_hook);
 }
 
 void nhrp_interface_update_mtu(struct interface *ifp, afi_t afi)
index 012d5cd87c0d143a10a9615f2b9fb2a4217634f3..3a7186c1d799dfcce0d315d258d11087c8be530f 100644 (file)
@@ -81,6 +81,7 @@ static void nhrp_sigusr1(void)
 static void nhrp_request_stop(void)
 {
        debugf(NHRP_DEBUG_COMMON, "Exiting...");
+       frr_early_fini();
 
        nhrp_shortcut_terminate();
        nhrp_nhs_terminate();
@@ -89,15 +90,9 @@ static void nhrp_request_stop(void)
        evmgr_terminate();
        nhrp_vc_terminate();
        vrf_terminate();
-       /* memory_terminate(); */
-       /* vty_terminate(); */
-       cmd_terminate();
-       /* signal_terminate(); */
-       zprivs_terminate(&nhrpd_privs);
 
        debugf(NHRP_DEBUG_COMMON, "Done.");
-
-       closezlog();
+       frr_fini();
 
        exit(0);
 }
index 76c591fd7997a0c11152acbbfe5f4b5f69ad00c8..0bada33502b073b4d0e66cc21c9428feb26cf608 100644 (file)
@@ -171,7 +171,7 @@ static int nhrp_reg_send_req(struct thread *t)
 
        zb = zbuf_alloc(1400);
        hdr = nhrp_packet_push(zb, NHRP_PACKET_REGISTRATION_REQUEST, &nifp->nbma, &if_ad->addr, dst_proto);
-       hdr->hop_count = 0;
+       hdr->hop_count = 1;
        if (!(if_ad->flags & NHRP_IFF_REG_NO_UNIQUE))
                hdr->flags |= htons(NHRP_FLAG_REGISTRATION_UNIQUE);
 
index c8a608c657e2887efab8c0e98964b566f6bb77a4..4b86bca5f75b1dbd311cf8a9c9bb08a25931a7e7 100644 (file)
@@ -86,14 +86,20 @@ void nhrp_route_update_nhrp(const struct prefix *p, struct interface *ifp)
 
 void nhrp_route_announce(int add, enum nhrp_cache_type type, const struct prefix *p, struct interface *ifp, const union sockunion *nexthop, uint32_t mtu)
 {
-       int flags = 0;
+       struct zapi_route api;
+       struct zapi_nexthop *api_nh;
 
        if (zclient->sock < 0)
                return;
 
+       memset(&api, 0, sizeof(api));
+       api.type = ZEBRA_ROUTE_NHRP;
+       api.safi = SAFI_UNICAST;
+       api.prefix = *p;
+
        switch (type) {
        case NHRP_CACHE_NEGATIVE:
-               SET_FLAG(flags, ZEBRA_FLAG_REJECT);
+               SET_FLAG(api.flags, ZEBRA_FLAG_REJECT);
                break;
        case NHRP_CACHE_DYNAMIC:
        case NHRP_CACHE_NHS:
@@ -102,158 +108,106 @@ void nhrp_route_announce(int add, enum nhrp_cache_type type, const struct prefix
                 * to other routing daemons */
                break;
        default:
-               SET_FLAG(flags, ZEBRA_FLAG_FIB_OVERRIDE);
+               SET_FLAG(api.flags, ZEBRA_FLAG_FIB_OVERRIDE);
                break;
        }
-       SET_FLAG(flags, ZEBRA_FLAG_INTERNAL);
-
-       if (p->family == AF_INET) {
-               struct in_addr *nexthop_ipv4;
-               struct zapi_ipv4 api;
+       SET_FLAG(api.flags, ZEBRA_FLAG_INTERNAL);
 
-               memset(&api, 0, sizeof(api));
-               api.flags = flags;
-               api.type = ZEBRA_ROUTE_NHRP;
-               api.safi = SAFI_UNICAST;
+       SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
+       api.nexthop_num = 1;
+       api_nh = &api.nexthops[0];
 
-               SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
+       switch (api.prefix.family) {
+       case AF_INET:
                if (nexthop) {
-                       nexthop_ipv4 = (struct in_addr *) sockunion_get_addr(nexthop);
-                       api.nexthop_num = 1;
-                       api.nexthop = &nexthop_ipv4;
+                       api_nh->gate.ipv4 = nexthop->sin.sin_addr;
+                       api_nh->type = NEXTHOP_TYPE_IPV4;
                }
                if (ifp) {
-                       SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX);
-                       api.ifindex_num = 1;
-                       api.ifindex = &ifp->ifindex;
+                       api_nh->ifindex = ifp->ifindex;
+                       if (api_nh->type == NEXTHOP_TYPE_IPV4)
+                               api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX;
+                       else
+                               api_nh->type = NEXTHOP_TYPE_IFINDEX;
                }
-               if (mtu) {
-                       SET_FLAG(api.message, ZAPI_MESSAGE_MTU);
-                       api.mtu = mtu;
-               }
-
-               if (unlikely(debug_flags & NHRP_DEBUG_ROUTE)) {
-                       char buf[2][INET_ADDRSTRLEN];
-                       zlog_debug("Zebra send: IPv4 route %s %s/%d nexthop %s metric %u"
-                               " count %d dev %s",
-                               add ? "add" : "del",
-                               inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])),
-                               p->prefixlen,
-                               nexthop ? inet_ntop(AF_INET, api.nexthop[0], buf[1], sizeof(buf[1])) : "<onlink>",
-                               api.metric, api.nexthop_num, ifp->name);
-               }
-
-               zapi_ipv4_route(
-                       add ? ZEBRA_IPV4_ROUTE_ADD : ZEBRA_IPV4_ROUTE_DELETE,
-                       zclient, (struct prefix_ipv4 *) p, &api);
-       } else if (p->family == AF_INET6) {
-               struct in6_addr *nexthop_ipv6;
-               struct zapi_ipv6 api;
-
-               memset(&api, 0, sizeof(api));
-               api.flags = flags;
-               api.type = ZEBRA_ROUTE_NHRP;
-               api.safi = SAFI_UNICAST;
-
-               SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
+               break;
+       case AF_INET6:
                if (nexthop) {
-                       nexthop_ipv6 = (struct in6_addr *) sockunion_get_addr(nexthop);
-                       api.nexthop_num = 1;
-                       api.nexthop = &nexthop_ipv6;
+                       api_nh->gate.ipv6 = nexthop->sin6.sin6_addr;
+                       api_nh->type = NEXTHOP_TYPE_IPV6;
                }
                if (ifp) {
-                       SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX);
-                       api.ifindex_num = 1;
-                       api.ifindex = &ifp->ifindex;
-               }
-               if (mtu) {
-                       SET_FLAG(api.message, ZAPI_MESSAGE_MTU);
-                       api.mtu = mtu;
+                       api_nh->ifindex = ifp->ifindex;
+                       if (api_nh->type == NEXTHOP_TYPE_IPV6)
+                               api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
+                       else
+                               api_nh->type = NEXTHOP_TYPE_IFINDEX;
                }
+               break;
+       }
+       if (mtu) {
+               SET_FLAG(api.message, ZAPI_MESSAGE_MTU);
+               api.mtu = mtu;
+       }
 
-               if (unlikely(debug_flags & NHRP_DEBUG_ROUTE)) {
-                       char buf[2][INET6_ADDRSTRLEN];
-                       zlog_debug("Zebra send: IPv6 route %s %s/%d nexthop %s metric %u"
-                               " count %d dev %s",
-                               add ? "add" : "del",
-                               inet_ntop(AF_INET6, &p->u.prefix6, buf[0], sizeof(buf[0])),
-                               p->prefixlen,
-                               nexthop ? inet_ntop(AF_INET6, api.nexthop[0], buf[1], sizeof(buf[1])) : "<onlink>",
-                               api.metric, api.nexthop_num, ifp->name);
-               }
+       if (unlikely(debug_flags & NHRP_DEBUG_ROUTE)) {
+               char buf[2][PREFIX_STRLEN];
 
-               zapi_ipv6_route(
-                       add ? ZEBRA_IPV6_ROUTE_ADD : ZEBRA_IPV6_ROUTE_DELETE,
-                       zclient, (struct prefix_ipv6 *) p, NULL, &api);
+               prefix2str(&api.prefix, buf[0], sizeof(buf[0]));
+               zlog_debug("Zebra send: route %s %s nexthop %s metric %u"
+                       " count %d dev %s",
+                       add ? "add" : "del", buf[0],
+                       nexthop ? inet_ntop(api.prefix.family, &api_nh->gate, buf[1], sizeof(buf[1])) : "<onlink>",
+                       api.metric, api.nexthop_num, ifp->name);
        }
+
+       zclient_route_send(add ? ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE, zclient,
+                          &api);
 }
 
 int nhrp_route_read(int cmd, struct zclient *zclient, zebra_size_t length, vrf_id_t vrf_id)
 {
-       struct stream *s;
+       struct zapi_route api;
+       struct zapi_nexthop *api_nh;
        struct interface *ifp = NULL;
-       struct prefix prefix;
        union sockunion nexthop_addr;
-       unsigned char message, nexthop_num, ifindex_num;
-       unsigned ifindex;
        char buf[2][PREFIX_STRLEN];
-       int i, afaddrlen, added;
+       int added;
+
+       if (zapi_route_decode(zclient->ibuf, &api) < 0)
+               return -1;
+
+       /* we completely ignore srcdest routes for now. */
+       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
+               return 0;
 
-       s = zclient->ibuf;
-       memset(&prefix, 0, sizeof(prefix));
        sockunion_family(&nexthop_addr) = AF_UNSPEC;
+       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) {
+               api_nh = &api.nexthops[0];
 
-       /* Type, flags, message. */
-       /*type =*/ stream_getc(s);
-       /*instance =*/ stream_getw(s);
-       /*flags =*/ stream_getl(s);
-       message = stream_getc(s);
-
-       /* Prefix */
-       switch (cmd) {
-       case ZEBRA_REDISTRIBUTE_IPV4_ADD:
-       case ZEBRA_REDISTRIBUTE_IPV4_DEL:
-               prefix.family = AF_INET;
-               break;
-       case ZEBRA_REDISTRIBUTE_IPV6_ADD:
-       case ZEBRA_REDISTRIBUTE_IPV6_DEL:
-               prefix.family = AF_INET6;
-               break;
-       default:
-               return -1;
-       }
-       afaddrlen = family2addrsize(prefix.family);
-       prefix.prefixlen = stream_getc(s);
-       stream_get(&prefix.u.val, s, PSIZE(prefix.prefixlen));
-
-       /* Nexthop, ifindex, distance, metric. */
-       if (CHECK_FLAG(message, ZAPI_MESSAGE_NEXTHOP|ZAPI_MESSAGE_IFINDEX)) {
-               nexthop_num = stream_getc(s);
-               for (i = 0; i < nexthop_num; i++) {
-                       stream_get(buf[0], s, afaddrlen);
-                       if (i == 0) sockunion_set(&nexthop_addr, prefix.family, (u_char*) buf[0], afaddrlen);
-               }
-               ifindex_num = stream_getc(s);
-               for (i = 0; i < ifindex_num; i++) {
-                       ifindex = stream_getl(s);
-                       if (i == 0 && ifindex != IFINDEX_INTERNAL)
-                          ifp = if_lookup_by_index(ifindex, VRF_DEFAULT);
+               nexthop_addr.sa.sa_family = api.prefix.family;
+               switch (nexthop_addr.sa.sa_family) {
+               case AF_INET:
+                       nexthop_addr.sin.sin_addr = api_nh->gate.ipv4;
+                       break;
+               case AF_INET6:
+                       nexthop_addr.sin6.sin6_addr = api_nh->gate.ipv6;
+                       break;
                }
+
+               if (api_nh->ifindex != IFINDEX_INTERNAL)
+                               ifp = if_lookup_by_index(api_nh->ifindex, VRF_DEFAULT);
        }
-       if (CHECK_FLAG(message, ZAPI_MESSAGE_DISTANCE))
-               /*distance =*/ stream_getc(s);
-       if (CHECK_FLAG(message, ZAPI_MESSAGE_METRIC))
-               /*metric =*/ stream_getl(s);
 
-       added = (cmd == ZEBRA_REDISTRIBUTE_IPV4_ADD || cmd == ZEBRA_REDISTRIBUTE_IPV6_ADD);
+       added = (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD);
        debugf(NHRP_DEBUG_ROUTE, "if-route-%s: %s via %s dev %s",
                added ? "add" : "del",
-               prefix2str(&prefix, buf[0], sizeof buf[0]),
+               prefix2str(&api.prefix, buf[0], sizeof buf[0]),
                sockunion2str(&nexthop_addr, buf[1], sizeof buf[1]),
                ifp ? ifp->name : "(none)");
 
-       nhrp_route_update_zebra(&prefix, &nexthop_addr, ifp);
-       nhrp_shortcut_prefix_change(&prefix, !added);
+       nhrp_route_update_zebra(&api.prefix, &nexthop_addr, ifp);
+       nhrp_shortcut_prefix_change(&api.prefix, !added);
 
        return 0;
 }
@@ -366,10 +320,8 @@ void nhrp_zebra_init(void)
        zclient->interface_down = nhrp_interface_down;
        zclient->interface_address_add = nhrp_interface_address_add;
        zclient->interface_address_delete = nhrp_interface_address_delete;
-       zclient->redistribute_route_ipv4_add = nhrp_route_read;
-       zclient->redistribute_route_ipv4_del = nhrp_route_read;
-       zclient->redistribute_route_ipv6_add = nhrp_route_read;
-       zclient->redistribute_route_ipv6_del = nhrp_route_read;
+       zclient->redistribute_route_add = nhrp_route_read;
+       zclient->redistribute_route_del = nhrp_route_read;
 
        zclient_init(zclient, ZEBRA_ROUTE_NHRP, 0);
 }
@@ -381,4 +333,3 @@ void nhrp_zebra_terminate(void)
        route_table_finish(zebra_rib[AFI_IP]);
        route_table_finish(zebra_rib[AFI_IP6]);
 }
-
index 20ef17de00bfb9993e8653e7b1f791e58c076411..6d78fc1d2b25f37cc52dda164251a8f4dca79491 100644 (file)
@@ -110,11 +110,11 @@ static int toggle_flag(
 
 #ifndef NO_DEBUG
 
-DEFUN(show_debugging_nhrp, show_debugging_nhrp_cmd,
-       "show debugging nhrp",
-       SHOW_STR
-       "Debugging information\n"
-       "NHRP configuration\n")
+DEFUN_NOSH(show_debugging_nhrp, show_debugging_nhrp_cmd,
+          "show debugging [nhrp]",
+          SHOW_STR
+          "Debugging information\n"
+          "NHRP configuration\n")
 {
        int i;
 
index f198ac4af695266205e1ad68a1656ff65a01f6cf..36528d063ca52f609df83ba94eaa8b3f2cad29a1 100644 (file)
@@ -386,27 +386,20 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route,
        }
 
        /* Check filter-list */
-       if (PREFIX_NAME_OUT(area)) {
-               if (PREFIX_LIST_OUT(area) == NULL)
-                       PREFIX_LIST_OUT(area) = prefix_list_lookup(
-                               AFI_IP6, PREFIX_NAME_OUT(area));
-
-               if (PREFIX_LIST_OUT(area))
-                       if (prefix_list_apply(PREFIX_LIST_OUT(area),
-                                             &route->prefix)
-                           != PREFIX_PERMIT) {
-                               if (is_debug) {
-                                       inet_ntop(AF_INET,
-                                                 &(ADV_ROUTER_IN_PREFIX(
-                                                         &route->prefix)),
-                                                 buf, sizeof(buf));
-                                       zlog_debug(
-                                               "prefix %s was denied by filter-list out",
-                                               buf);
-                               }
-                               return 0;
+       if (PREFIX_LIST_OUT(area))
+               if (prefix_list_apply(PREFIX_LIST_OUT(area), &route->prefix)
+                   != PREFIX_PERMIT) {
+                       if (is_debug) {
+                               inet_ntop(AF_INET,
+                                         &(ADV_ROUTER_IN_PREFIX(
+                                                 &route->prefix)),
+                                         buf, sizeof(buf));
+                               zlog_debug(
+                                       "prefix %s was denied by filter-list out",
+                                       buf);
                        }
-       }
+                       return 0;
+               }
 
        /* the route is going to be originated. store it in area's summary_table
         */
@@ -873,22 +866,16 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa)
        }
 
        /* Check input prefix-list */
-       if (PREFIX_NAME_IN(oa)) {
-               if (PREFIX_LIST_IN(oa) == NULL)
-                       PREFIX_LIST_IN(oa) =
-                               prefix_list_lookup(AFI_IP6, PREFIX_NAME_IN(oa));
-
-               if (PREFIX_LIST_IN(oa))
-                       if (prefix_list_apply(PREFIX_LIST_IN(oa), &prefix)
-                           != PREFIX_PERMIT) {
-                               if (is_debug)
-                                       zlog_debug(
-                                               "Prefix was denied by prefix-list");
-                               if (old)
-                                       ospf6_route_remove(old, table);
-                               return;
-                       }
-       }
+       if (PREFIX_LIST_IN(oa))
+               if (prefix_list_apply(PREFIX_LIST_IN(oa), &prefix)
+                   != PREFIX_PERMIT) {
+                       if (is_debug)
+                               zlog_debug(
+                                       "Prefix was denied by prefix-list");
+                       if (old)
+                               ospf6_route_remove(old, table);
+                       return;
+               }
 
        /* (5),(6): the path preference is handled by the sorting
           in the routing table. Always install the path by substituting
index a4cc0bf42052cbaf8b7e352b97d9d82f8cfb9770..649d7a100041346fba7cb346fa9a53ddf092f6ba 100644 (file)
@@ -45,6 +45,8 @@
 #include "ospf6_asbr.h"
 #include "ospf6d.h"
 
+DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_PLISTNAME, "Prefix list name")
+
 int ospf6_area_cmp(void *va, void *vb)
 {
        struct ospf6_area *oa = (struct ospf6_area *)va;
@@ -579,17 +581,15 @@ DEFUN (area_filter_list,
        plist = prefix_list_lookup(AFI_IP6, plistname);
        if (strmatch(inout, "in")) {
                PREFIX_LIST_IN(area) = plist;
-               if (PREFIX_NAME_IN(area))
-                       free(PREFIX_NAME_IN(area));
-
-               PREFIX_NAME_IN(area) = strdup(plistname);
+               XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_IN(area));
+               PREFIX_NAME_IN(area) = XSTRDUP(MTYPE_OSPF6_PLISTNAME,
+                                              plistname);
                ospf6_abr_reimport(area);
        } else {
                PREFIX_LIST_OUT(area) = plist;
-               if (PREFIX_NAME_OUT(area))
-                       free(PREFIX_NAME_OUT(area));
-
-               PREFIX_NAME_OUT(area) = strdup(plistname);
+               XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_OUT(area));
+               PREFIX_NAME_OUT(area) = XSTRDUP(MTYPE_OSPF6_PLISTNAME,
+                                               plistname);
                ospf6_abr_enable_area(area);
        }
 
@@ -622,27 +622,34 @@ DEFUN (no_area_filter_list,
                                return CMD_SUCCESS;
 
                PREFIX_LIST_IN(area) = NULL;
-               if (PREFIX_NAME_IN(area))
-                       free(PREFIX_NAME_IN(area));
-
-               PREFIX_NAME_IN(area) = NULL;
+               XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_IN(area));
                ospf6_abr_reimport(area);
        } else {
                if (PREFIX_NAME_OUT(area))
                        if (!strmatch(PREFIX_NAME_OUT(area), plistname))
                                return CMD_SUCCESS;
 
-               PREFIX_LIST_OUT(area) = NULL;
-               if (PREFIX_NAME_OUT(area))
-                       free(PREFIX_NAME_OUT(area));
-
-               PREFIX_NAME_OUT(area) = NULL;
+               XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_OUT(area));
                ospf6_abr_enable_area(area);
        }
 
        return CMD_SUCCESS;
 }
 
+void ospf6_area_plist_update(struct prefix_list *plist, int add)
+{
+       struct ospf6_area *oa;
+       struct listnode *n;
+       const char *name = prefix_list_name(plist);
+
+       for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, n, oa)) {
+               if (!strcmp(PREFIX_NAME_IN(oa), name))
+                       PREFIX_LIST_IN(oa) = add ? plist : NULL;
+               if (!strcmp(PREFIX_NAME_OUT(oa), name))
+                       PREFIX_LIST_OUT(oa) = add ? plist : NULL;
+       }
+}
+
 DEFUN (area_import_list,
        area_import_list_cmd,
        "area A.B.C.D import-list NAME",
index 4bc24a6dd8327fa4a4c5f6a9cd6210bdb6ff318d..d212d9238726971f2e5f2e533aa21aedd189d99a 100644 (file)
@@ -122,6 +122,7 @@ extern void ospf6_area_disable(struct ospf6_area *);
 
 extern void ospf6_area_show(struct vty *, struct ospf6_area *);
 
+extern void ospf6_area_plist_update(struct prefix_list *plist, int add);
 extern void ospf6_area_config_write(struct vty *vty);
 extern void ospf6_area_init(void);
 
index 1d17a1c233ffd59f3ef856efe4bbe7d530f7aa25..bb63fb966ed8b6c7e868a1188dbbb39d7bd9dd79 100644 (file)
@@ -1171,8 +1171,7 @@ DEFUN (ipv6_ospf6_cost,
        IP6_STR
        OSPF6_STR
        "Interface cost\n"
-       "Outgoing metric of this interface\n"
-       )
+       "Outgoing metric of this interface\n")
 {
        VTY_DECLVAR_CONTEXT(interface, ifp);
        int idx_number = 3;
@@ -1206,12 +1205,12 @@ DEFUN (ipv6_ospf6_cost,
 
 DEFUN (no_ipv6_ospf6_cost,
        no_ipv6_ospf6_cost_cmd,
-       "no ipv6 ospf6 cost",
+       "no ipv6 ospf6 cost [(1-65535)]",
        NO_STR
        IP6_STR
        OSPF6_STR
        "Calculate interface cost from bandwidth\n"
-       )
+       "Outgoing metric of this interface\n")
 {
        VTY_DECLVAR_CONTEXT(interface, ifp);
        struct ospf6_interface *oi;
@@ -1292,8 +1291,7 @@ DEFUN (ipv6_ospf6_hellointerval,
        IP6_STR
        OSPF6_STR
        "Time between HELLO packets\n"
-       SECONDS_STR
-       )
+       SECONDS_STR)
 {
        VTY_DECLVAR_CONTEXT(interface, ifp);
        int idx_number = 3;
@@ -1305,10 +1303,21 @@ DEFUN (ipv6_ospf6_hellointerval,
                oi = ospf6_interface_create(ifp);
        assert(oi);
 
-       oi->hello_interval = strtol(argv[idx_number]->arg, NULL, 10);
+       oi->hello_interval = strmatch(argv[0]->text, "no")
+                                    ? OSPF_HELLO_INTERVAL_DEFAULT
+                                    : strtoul(argv[idx_number]->arg, NULL, 10);
        return CMD_SUCCESS;
 }
 
+ALIAS (ipv6_ospf6_hellointerval,
+       no_ipv6_ospf6_hellointerval_cmd,
+       "no ipv6 ospf6 hello-interval [(1-65535)]",
+       NO_STR
+       IP6_STR
+       OSPF6_STR
+       "Time between HELLO packets\n"
+       SECONDS_STR)
+
 /* interface variable set command */
 DEFUN (ipv6_ospf6_deadinterval,
        ipv6_ospf6_deadinterval_cmd,
@@ -1316,8 +1325,7 @@ DEFUN (ipv6_ospf6_deadinterval,
        IP6_STR
        OSPF6_STR
        "Interval time after which a neighbor is declared down\n"
-       SECONDS_STR
-       )
+       SECONDS_STR)
 {
        VTY_DECLVAR_CONTEXT(interface, ifp);
        int idx_number = 3;
@@ -1329,10 +1337,21 @@ DEFUN (ipv6_ospf6_deadinterval,
                oi = ospf6_interface_create(ifp);
        assert(oi);
 
-       oi->dead_interval = strtol(argv[idx_number]->arg, NULL, 10);
+       oi->dead_interval = strmatch(argv[0]->arg, "no")
+                                   ? OSPF_ROUTER_DEAD_INTERVAL_DEFAULT
+                                   : strtoul(argv[idx_number]->arg, NULL, 10);
        return CMD_SUCCESS;
 }
 
+ALIAS (ipv6_ospf6_deadinterval,
+       no_ipv6_ospf6_deadinterval_cmd,
+       "no ipv6 ospf6 dead-interval [(1-65535)]",
+       NO_STR
+       IP6_STR
+       OSPF6_STR
+       "Interval time after which a neighbor is declared down\n"
+       SECONDS_STR)
+
 /* interface variable set command */
 DEFUN (ipv6_ospf6_transmitdelay,
        ipv6_ospf6_transmitdelay_cmd,
@@ -1352,10 +1371,21 @@ DEFUN (ipv6_ospf6_transmitdelay,
                oi = ospf6_interface_create(ifp);
        assert(oi);
 
-       oi->transdelay = strtol(argv[idx_number]->arg, NULL, 10);
+       oi->transdelay = strmatch(argv[0]->text, "no")
+                                ? OSPF6_INTERFACE_TRANSDELAY
+                                : strtoul(argv[idx_number]->arg, NULL, 10);
        return CMD_SUCCESS;
 }
 
+ALIAS (ipv6_ospf6_transmitdelay,
+       no_ipv6_ospf6_transmitdelay_cmd,
+       "no ipv6 ospf6 transmit-delay [(1-3600)]",
+       NO_STR
+       IP6_STR
+       OSPF6_STR
+       "Link state transmit delay\n"
+       SECONDS_STR)
+
 /* interface variable set command */
 DEFUN (ipv6_ospf6_retransmitinterval,
        ipv6_ospf6_retransmitinterval_cmd,
@@ -1363,8 +1393,7 @@ DEFUN (ipv6_ospf6_retransmitinterval,
        IP6_STR
        OSPF6_STR
        "Time between retransmitting lost link state advertisements\n"
-       SECONDS_STR
-       )
+       SECONDS_STR)
 {
        VTY_DECLVAR_CONTEXT(interface, ifp);
        int idx_number = 3;
@@ -1376,10 +1405,21 @@ DEFUN (ipv6_ospf6_retransmitinterval,
                oi = ospf6_interface_create(ifp);
        assert(oi);
 
-       oi->rxmt_interval = strtol(argv[idx_number]->arg, NULL, 10);
+       oi->rxmt_interval = strmatch(argv[0]->text, "no")
+                                   ? OSPF_RETRANSMIT_INTERVAL_DEFAULT
+                                   : strtoul(argv[idx_number]->arg, NULL, 10);
        return CMD_SUCCESS;
 }
 
+ALIAS (ipv6_ospf6_retransmitinterval,
+       no_ipv6_ospf6_retransmitinterval_cmd,
+       "no ipv6 ospf6 retransmit-interval [(1-65535)]",
+       NO_STR
+       IP6_STR
+       OSPF6_STR
+       "Time between retransmitting lost link state advertisements\n"
+       SECONDS_STR)
+
 /* interface variable set command */
 DEFUN (ipv6_ospf6_priority,
        ipv6_ospf6_priority_cmd,
@@ -1387,8 +1427,7 @@ DEFUN (ipv6_ospf6_priority,
        IP6_STR
        OSPF6_STR
        "Router priority\n"
-       "Priority value\n"
-       )
+       "Priority value\n")
 {
        VTY_DECLVAR_CONTEXT(interface, ifp);
        int idx_number = 3;
@@ -1400,7 +1439,9 @@ DEFUN (ipv6_ospf6_priority,
                oi = ospf6_interface_create(ifp);
        assert(oi);
 
-       oi->priority = strtol(argv[idx_number]->arg, NULL, 10);
+       oi->priority = strmatch(argv[0]->text, "no")
+                              ? OSPF6_INTERFACE_PRIORITY
+                              : strtoul(argv[idx_number]->arg, NULL, 10);
 
        if (oi->area && (oi->state == OSPF6_INTERFACE_DROTHER
                         || oi->state == OSPF6_INTERFACE_BDR
@@ -1410,14 +1451,22 @@ DEFUN (ipv6_ospf6_priority,
        return CMD_SUCCESS;
 }
 
+ALIAS (ipv6_ospf6_priority,
+       no_ipv6_ospf6_priority_cmd,
+       "no ipv6 ospf6 priority [(0-255)]",
+       NO_STR
+       IP6_STR
+       OSPF6_STR
+       "Router priority\n"
+       "Priority value\n")
+
 DEFUN (ipv6_ospf6_instance,
        ipv6_ospf6_instance_cmd,
        "ipv6 ospf6 instance-id (0-255)",
        IP6_STR
        OSPF6_STR
        "Instance ID for this interface\n"
-       "Instance ID value\n"
-       )
+       "Instance ID value\n")
 {
        VTY_DECLVAR_CONTEXT(interface, ifp);
        int idx_number = 3;
@@ -1429,10 +1478,21 @@ DEFUN (ipv6_ospf6_instance,
                oi = ospf6_interface_create(ifp);
        assert(oi);
 
-       oi->instance_id = strtol(argv[idx_number]->arg, NULL, 10);
+       oi->instance_id = strmatch(argv[0]->text, "no")
+                                 ? OSPF6_INTERFACE_INSTANCE_ID
+                                 : strtoul(argv[idx_number]->arg, NULL, 10);
        return CMD_SUCCESS;
 }
 
+ALIAS (ipv6_ospf6_instance,
+       no_ipv6_ospf6_instance_cmd,
+       "no ipv6 ospf6 instance-id [(0-255)]",
+       NO_STR
+       IP6_STR
+       OSPF6_STR
+       "Instance ID for this interface\n"
+       "Instance ID value\n")
+
 DEFUN (ipv6_ospf6_passive,
        ipv6_ospf6_passive_cmd,
        "ipv6 ospf6 passive",
@@ -1576,13 +1636,13 @@ DEFUN (ipv6_ospf6_advertise_prefix_list,
 
 DEFUN (no_ipv6_ospf6_advertise_prefix_list,
        no_ipv6_ospf6_advertise_prefix_list_cmd,
-       "no ipv6 ospf6 advertise prefix-list",
+       "no ipv6 ospf6 advertise prefix-list [WORD]",
        NO_STR
        IP6_STR
        OSPF6_STR
        "Advertising options\n"
        "Filter prefix using prefix-list\n"
-       )
+       "Prefix list name\n")
 {
        VTY_DECLVAR_CONTEXT(interface, ifp);
        struct ospf6_interface *oi;
@@ -1593,10 +1653,8 @@ DEFUN (no_ipv6_ospf6_advertise_prefix_list,
                oi = ospf6_interface_create(ifp);
        assert(oi);
 
-       if (oi->plist_name) {
+       if (oi->plist_name)
                XFREE(MTYPE_CFG_PLIST_NAME, oi->plist_name);
-               oi->plist_name = NULL;
-       }
 
        ospf6_interface_connected_route_update(oi->interface);
 
@@ -1654,11 +1712,13 @@ DEFUN (ipv6_ospf6_network,
 
 DEFUN (no_ipv6_ospf6_network,
        no_ipv6_ospf6_network_cmd,
-       "no ipv6 ospf6 network",
+       "no ipv6 ospf6 network [<broadcast|point-to-point>]",
        NO_STR
        IP6_STR
        OSPF6_STR
-       "Set default network type\n")
+       "Set default network type\n"
+       "Specify OSPF6 broadcast network\n"
+       "Specify OSPF6 point-to-point network\n")
 {
        VTY_DECLVAR_CONTEXT(interface, ifp);
        struct ospf6_interface *oi;
@@ -1772,12 +1832,19 @@ void ospf6_interface_init(void)
        install_element(INTERFACE_NODE, &no_ipv6_ospf6_cost_cmd);
        install_element(INTERFACE_NODE, &ipv6_ospf6_ifmtu_cmd);
        install_element(INTERFACE_NODE, &no_ipv6_ospf6_ifmtu_cmd);
+
        install_element(INTERFACE_NODE, &ipv6_ospf6_deadinterval_cmd);
        install_element(INTERFACE_NODE, &ipv6_ospf6_hellointerval_cmd);
        install_element(INTERFACE_NODE, &ipv6_ospf6_priority_cmd);
        install_element(INTERFACE_NODE, &ipv6_ospf6_retransmitinterval_cmd);
        install_element(INTERFACE_NODE, &ipv6_ospf6_transmitdelay_cmd);
        install_element(INTERFACE_NODE, &ipv6_ospf6_instance_cmd);
+       install_element(INTERFACE_NODE, &no_ipv6_ospf6_deadinterval_cmd);
+       install_element(INTERFACE_NODE, &no_ipv6_ospf6_hellointerval_cmd);
+       install_element(INTERFACE_NODE, &no_ipv6_ospf6_priority_cmd);
+       install_element(INTERFACE_NODE, &no_ipv6_ospf6_retransmitinterval_cmd);
+       install_element(INTERFACE_NODE, &no_ipv6_ospf6_transmitdelay_cmd);
+       install_element(INTERFACE_NODE, &no_ipv6_ospf6_instance_cmd);
 
        install_element(INTERFACE_NODE, &ipv6_ospf6_passive_cmd);
        install_element(INTERFACE_NODE, &no_ipv6_ospf6_passive_cmd);
index 28bb956c403d819328bbd03b27fd2931249c6495..e582737f940e9f16c1ca2a2b702b72e7352cf5f0 100644 (file)
@@ -82,6 +82,8 @@ static void __attribute__((noreturn)) ospf6_exit(int status)
        struct listnode *node;
        struct interface *ifp;
 
+       frr_early_fini();
+
        if (ospf6)
                ospf6_delete(ospf6);
 
@@ -96,19 +98,13 @@ static void __attribute__((noreturn)) ospf6_exit(int status)
        ospf6_lsa_terminate();
 
        vrf_terminate();
-       vty_terminate();
-       cmd_terminate();
 
        if (zclient) {
                zclient_stop(zclient);
                zclient_free(zclient);
        }
 
-       if (master)
-               thread_master_free(master);
-
-       closezlog();
-
+       frr_fini();
        exit(status);
 }
 
index bfe583a91149755bf16139c025659e5d9a06120e..e58eab2b156d52d9ced1476fb532d37d6d9464a4 100644 (file)
@@ -285,8 +285,7 @@ void ospf6_add_nexthop(struct list *nh_list, int ifindex, struct in6_addr *addr)
 }
 
 void ospf6_route_zebra_copy_nexthops(struct ospf6_route *route,
-                                    ifindex_t *ifindexes,
-                                    struct in6_addr **nexthop_addr,
+                                    struct zapi_nexthop nexthops[],
                                     int entries)
 {
        struct ospf6_nexthop *nh;
@@ -306,13 +305,16 @@ void ospf6_route_zebra_copy_nexthops(struct ospf6_route *route,
                                zlog_debug("  nexthop: %s%%%.*s(%d)", buf,
                                           IFNAMSIZ, ifname, nh->ifindex);
                        }
-                       if (i < entries) {
-                               nexthop_addr[i] = &nh->address;
-                               ifindexes[i] = nh->ifindex;
-                               i++;
-                       } else {
+                       if (i >= entries)
                                return;
-                       }
+
+                       nexthops[i].ifindex = nh->ifindex;
+                       if (!IN6_IS_ADDR_UNSPECIFIED(&nh->address)) {
+                               nexthops[i].gate.ipv6 = nh->address;
+                               nexthops[i].type = NEXTHOP_TYPE_IPV6_IFINDEX;
+                       } else
+                               nexthops[i].type = NEXTHOP_TYPE_IFINDEX;
+                       i++;
                }
        }
 }
index 166074fb705c5c2d239dac829eb5a07cf8f6d2d8..9eacadbdb7dee68e0254b84230965d369beb1b72 100644 (file)
@@ -22,6 +22,7 @@
 #define OSPF6_ROUTE_H
 
 #include "command.h"
+#include "zclient.h"
 
 #define OSPF6_MULTI_PATH_LIMIT    4
 
@@ -266,8 +267,7 @@ extern int ospf6_num_nexthops(struct list *nh_list);
 extern int ospf6_route_cmp_nexthops(struct ospf6_route *a,
                                    struct ospf6_route *b);
 extern void ospf6_route_zebra_copy_nexthops(struct ospf6_route *route,
-                                           ifindex_t *ifindices,
-                                           struct in6_addr **addr,
+                                           struct zapi_nexthop nexthops[],
                                            int entries);
 extern int ospf6_route_get_first_nh_index(struct ospf6_route *route);
 
index 387690bc8ad84fd2fb1c9c1caf42d7ffad0ad9ac..dc5792aa1765ed55fcfeab1bbbe3b133d2a22cef 100644 (file)
@@ -308,19 +308,24 @@ DEFUN (no_router_ospf6,
 /* change Router_ID commands. */
 DEFUN (ospf6_router_id,
        ospf6_router_id_cmd,
-       "router-id A.B.C.D",
-       "Configure OSPF Router-ID\n"
+       "ospf6 router-id A.B.C.D",
+       OSPF6_STR
+       "Configure OSPF6 Router-ID\n"
        V4NOTATION_STR)
 {
        VTY_DECLVAR_CONTEXT(ospf6, o);
-       int idx_ipv4 = 1;
+       int idx = 0;
        int ret;
+       const char *router_id_str;
        u_int32_t router_id;
 
-       ret = inet_pton(AF_INET, argv[idx_ipv4]->arg, &router_id);
+       argv_find(argv, argc, "A.B.C.D", &idx);
+       router_id_str = argv[idx]->arg;
+
+       ret = inet_pton(AF_INET, router_id_str, &router_id);
        if (ret == 0) {
                vty_out(vty, "malformed OSPF Router-ID: %s\n",
-                       argv[idx_ipv4]->arg);
+                       router_id_str);
                return CMD_SUCCESS;
        }
 
@@ -331,6 +336,40 @@ DEFUN (ospf6_router_id,
        return CMD_SUCCESS;
 }
 
+DEFUN (no_ospf6_router_id,
+       no_ospf6_router_id_cmd,
+       "no ospf6 router-id [A.B.C.D]",
+       NO_STR
+       OSPF6_STR
+       "Configure OSPF6 Router-ID\n"
+       V4NOTATION_STR)
+{
+       VTY_DECLVAR_CONTEXT(ospf6, o);
+       o->router_id_static = 0;
+       o->router_id = 0;
+
+       return CMD_SUCCESS;
+}
+
+#if CONFDATE > 20180828
+CPP_NOTICE("ospf6: `router-id A.B.C.D` deprecated 2017/08/28")
+#endif
+ALIAS_HIDDEN(ospf6_router_id,
+            ospf6_router_id_hdn_cmd,
+            "router-id A.B.C.D",
+            "Configure OSPF6 Router-ID\n"
+            V4NOTATION_STR)
+
+#if CONFDATE > 20180828
+CPP_NOTICE("ospf6: `no router-id A.B.C.D` deprecated 2017/08/28")
+#endif
+ALIAS_HIDDEN(no_ospf6_router_id,
+            no_ospf6_router_id_hdn_cmd,
+            "no router-id [A.B.C.D]",
+            NO_STR
+            "Configure OSPF6 Router-ID\n"
+            V4NOTATION_STR)
+
 DEFUN (ospf6_log_adjacency_changes,
        ospf6_log_adjacency_changes_cmd,
        "log-adjacency-changes",
@@ -974,7 +1013,7 @@ static int config_write_ospf6(struct vty *vty)
                  sizeof(router_id));
        vty_out(vty, "router ospf6\n");
        if (ospf6->router_id_static != 0)
-               vty_out(vty, " router-id %s\n", router_id);
+               vty_out(vty, " ospf6 router-id %s\n", router_id);
 
        /* log-adjacency-changes flag print. */
        if (CHECK_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_CHANGES)) {
@@ -1032,6 +1071,9 @@ void ospf6_top_init(void)
 
        install_default(OSPF6_NODE);
        install_element(OSPF6_NODE, &ospf6_router_id_cmd);
+       install_element(OSPF6_NODE, &no_ospf6_router_id_cmd);
+       install_element(OSPF6_NODE, &ospf6_router_id_hdn_cmd);
+       install_element(OSPF6_NODE, &no_ospf6_router_id_hdn_cmd);
        install_element(OSPF6_NODE, &ospf6_log_adjacency_changes_cmd);
        install_element(OSPF6_NODE, &ospf6_log_adjacency_changes_detail_cmd);
        install_element(OSPF6_NODE, &no_ospf6_log_adjacency_changes_cmd);
index d33f41730e2130b9c1f0403f9f5e4b2c3476bde5..3443bc47b616acd3900294bbc4c3e1b4daeb71e7 100644 (file)
@@ -207,75 +207,30 @@ static int ospf6_zebra_if_address_update_delete(int command,
        return 0;
 }
 
-static int ospf6_zebra_read_ipv6(int command, struct zclient *zclient,
-                                zebra_size_t length, vrf_id_t vrf_id)
+static int ospf6_zebra_read_route(int command, struct zclient *zclient,
+                                 zebra_size_t length, vrf_id_t vrf_id)
 {
-       struct stream *s;
-       struct zapi_ipv6 api;
+       struct zapi_route api;
        unsigned long ifindex;
-       struct prefix p, src_p;
        struct in6_addr *nexthop;
 
        if (ospf6 == NULL)
                return 0;
 
-       s = zclient->ibuf;
-       ifindex = 0;
-       nexthop = NULL;
-       memset(&api, 0, sizeof(api));
-
-       /* Type, flags, message. */
-       api.type = stream_getc(s);
-       api.instance = stream_getw(s);
-       api.flags = stream_getl(s);
-       api.message = stream_getc(s);
-
-       /* IPv6 prefix. */
-       memset(&p, 0, sizeof(struct prefix));
-       p.family = AF_INET6;
-       p.prefixlen = MIN(IPV6_MAX_PREFIXLEN, stream_getc(s));
-       stream_get(&p.u.prefix6, s, PSIZE(p.prefixlen));
-
-       memset(&src_p, 0, sizeof(struct prefix));
-       src_p.family = AF_INET6;
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) {
-               src_p.prefixlen = stream_getc(s);
-               stream_get(&src_p.u.prefix6, s, PSIZE(src_p.prefixlen));
-       }
+       if (zapi_route_decode(zclient->ibuf, &api) < 0)
+               return -1;
 
-       if (src_p.prefixlen)
-               /* we completely ignore srcdest routes for now. */
+       /* we completely ignore srcdest routes for now. */
+       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
                return 0;
 
-       /* Nexthop, ifindex, distance, metric. */
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) {
-               api.nexthop_num = stream_getc(s);
-               nexthop = (struct in6_addr *)malloc(api.nexthop_num
-                                                   * sizeof(struct in6_addr));
-               stream_get(nexthop, s,
-                          api.nexthop_num * sizeof(struct in6_addr));
-       }
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) {
-               api.ifindex_num = stream_getc(s);
-               ifindex = stream_getl(s);
-       }
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE))
-               api.distance = stream_getc(s);
-       else
-               api.distance = 0;
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC))
-               api.metric = stream_getl(s);
-       else
-               api.metric = 0;
-
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG))
-               api.tag = stream_getl(s);
-       else
-               api.tag = 0;
+       ifindex = api.nexthops[0].ifindex;
+       nexthop = &api.nexthops[0].gate.ipv6;
 
        if (IS_OSPF6_DEBUG_ZEBRA(RECV)) {
                char prefixstr[PREFIX2STR_BUFFER], nexthopstr[128];
-               prefix2str((struct prefix *)&p, prefixstr, sizeof(prefixstr));
+               prefix2str((struct prefix *)&api.prefix, prefixstr,
+                          sizeof(prefixstr));
                if (nexthop)
                        inet_ntop(AF_INET6, nexthop, nexthopstr,
                                  sizeof(nexthopstr));
@@ -284,20 +239,17 @@ static int ospf6_zebra_read_ipv6(int command, struct zclient *zclient,
 
                zlog_debug(
                        "Zebra Receive route %s: %s %s nexthop %s ifindex %ld tag %" ROUTE_TAG_PRI,
-                       (command == ZEBRA_REDISTRIBUTE_IPV6_ADD ? "add"
-                                                               : "delete"),
+                       (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD ? "add"
+                                                                : "delete"),
                        zebra_route_string(api.type), prefixstr, nexthopstr,
                        ifindex, api.tag);
        }
 
-       if (command == ZEBRA_REDISTRIBUTE_IPV6_ADD)
-               ospf6_asbr_redistribute_add(api.type, ifindex, &p,
+       if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
+               ospf6_asbr_redistribute_add(api.type, ifindex, &api.prefix,
                                            api.nexthop_num, nexthop, api.tag);
        else
-               ospf6_asbr_redistribute_remove(api.type, ifindex, &p);
-
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP))
-               free(nexthop);
+               ospf6_asbr_redistribute_remove(api.type, ifindex, &api.prefix);
 
        return 0;
 }
@@ -317,7 +269,7 @@ DEFUN (show_zebra,
        }
 
        vty_out(vty, "Zebra Infomation\n");
-       vty_out(vty, "  enable: %d fail: %d\n", zclient->enable, zclient->fail);
+       vty_out(vty, "  fail: %d\n", zclient->fail);
        vty_out(vty, "  redistribute default: %d\n",
                vrf_bitmap_check(zclient->default_information, VRF_DEFAULT));
        vty_out(vty, "  redistribute:");
@@ -329,38 +281,15 @@ DEFUN (show_zebra,
        return CMD_SUCCESS;
 }
 
-/* Zebra configuration write function. */
-static int config_write_ospf6_zebra(struct vty *vty)
-{
-       if (!zclient->enable) {
-               vty_out(vty, "no router zebra\n");
-               vty_out(vty, "!\n");
-       } else if (!vrf_bitmap_check(
-                          zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6],
-                          VRF_DEFAULT)) {
-               vty_out(vty, "router zebra\n");
-               vty_out(vty, " no redistribute ospf6\n");
-               vty_out(vty, "!\n");
-       }
-       return 0;
-}
-
-/* Zebra node structure. */
-static struct cmd_node zebra_node = {
-       ZEBRA_NODE, "%s(config-zebra)# ",
-};
-
 #define ADD    0
 #define REM    1
 static void ospf6_zebra_route_update(int type, struct ospf6_route *request)
 {
-       struct zapi_ipv6 api;
+       struct zapi_route api;
        char buf[PREFIX2STR_BUFFER];
        int nhcount;
-       struct in6_addr **nexthops;
-       ifindex_t *ifindexes;
        int ret = 0;
-       struct prefix_ipv6 *dest;
+       struct prefix *dest;
 
        if (IS_OSPF6_DEBUG_ZEBRA(SEND)) {
                prefix2str(&request->prefix, buf, sizeof(buf));
@@ -408,36 +337,16 @@ static void ospf6_zebra_route_update(int type, struct ospf6_route *request)
                return;
        }
 
-       /* allocate memory for nexthop_list */
-       nexthops =
-               XCALLOC(MTYPE_OSPF6_OTHER, nhcount * sizeof(struct in6_addr *));
-       if (nexthops == NULL) {
-               zlog_warn("Can't send route to zebra: malloc failed");
-               return;
-       }
-
-       /* allocate memory for ifindex_list */
-       ifindexes = XCALLOC(MTYPE_OSPF6_OTHER, nhcount * sizeof(ifindex_t));
-       if (ifindexes == NULL) {
-               zlog_warn("Can't send route to zebra: malloc failed");
-               XFREE(MTYPE_OSPF6_OTHER, nexthops);
-               return;
-       }
-
-       ospf6_route_zebra_copy_nexthops(request, ifindexes, nexthops, nhcount);
+       dest = &request->prefix;
 
+       memset(&api, 0, sizeof(api));
        api.vrf_id = VRF_DEFAULT;
        api.type = ZEBRA_ROUTE_OSPF6;
-       api.instance = 0;
-       api.flags = 0;
-       api.message = 0;
        api.safi = SAFI_UNICAST;
+       api.prefix = *dest;
        SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
        api.nexthop_num = nhcount;
-       api.nexthop = nexthops;
-       SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX);
-       api.ifindex_num = nhcount;
-       api.ifindex = ifindexes;
+       ospf6_route_zebra_copy_nexthops(request, api.nexthops, nhcount);
        SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
        api.metric = (request->path.metric_type == 2 ? request->path.u.cost_e2
                                                     : request->path.cost);
@@ -446,193 +355,97 @@ static void ospf6_zebra_route_update(int type, struct ospf6_route *request)
                api.tag = request->path.tag;
        }
 
-       dest = (struct prefix_ipv6 *)&request->prefix;
-
        SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE);
-       api.distance = ospf6_distance_apply(dest, request);
+       api.distance =
+               ospf6_distance_apply((struct prefix_ipv6 *)dest, request);
 
        if (type == REM)
-               ret = zapi_ipv6_route(ZEBRA_IPV6_ROUTE_DELETE, zclient, dest,
-                                     NULL, &api);
+               ret = zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
        else
-               ret = zapi_ipv6_route(ZEBRA_IPV6_ROUTE_ADD, zclient, dest, NULL,
-                                     &api);
+               ret = zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api);
 
        if (ret < 0)
-               zlog_err("zapi_ipv6_route() %s failed: %s",
+               zlog_err("zclient_route_send() %s failed: %s",
                         (type == REM ? "delete" : "add"),
                         safe_strerror(errno));
 
-       XFREE(MTYPE_OSPF6_OTHER, nexthops);
-       XFREE(MTYPE_OSPF6_OTHER, ifindexes);
-
        return;
 }
 
 void ospf6_zebra_route_update_add(struct ospf6_route *request)
 {
-       if (!vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6],
-                             VRF_DEFAULT)) {
-               ospf6->route_table->hook_add = NULL;
-               ospf6->route_table->hook_remove = NULL;
-               return;
-       }
        ospf6_zebra_route_update(ADD, request);
 }
 
 void ospf6_zebra_route_update_remove(struct ospf6_route *request)
 {
-       if (!vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6],
-                             VRF_DEFAULT)) {
-               ospf6->route_table->hook_add = NULL;
-               ospf6->route_table->hook_remove = NULL;
-               return;
-       }
        ospf6_zebra_route_update(REM, request);
 }
 
 void ospf6_zebra_add_discard(struct ospf6_route *request)
 {
-       struct zapi_ipv6 api;
-       char buf[INET6_ADDRSTRLEN];
-       struct prefix_ipv6 *dest;
-
-       if (vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6],
-                            VRF_DEFAULT)) {
-               if (!CHECK_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) {
-                       api.vrf_id = VRF_DEFAULT;
-                       api.type = ZEBRA_ROUTE_OSPF6;
-                       api.flags = ZEBRA_FLAG_BLACKHOLE;
-                       api.instance = 0;
-                       api.message = 0;
-                       api.safi = SAFI_UNICAST;
-                       SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
-                       api.nexthop_num = 0;
-                       api.ifindex_num = 0;
-
-                       dest = (struct prefix_ipv6 *)&request->prefix;
-
-                       zapi_ipv6_route(ZEBRA_IPV6_ROUTE_ADD, zclient, dest,
-                                       NULL, &api);
-
-                       if (IS_OSPF6_DEBUG_ZEBRA(SEND))
-                               zlog_debug("Zebra: Route add discard %s/%d",
-                                          inet_ntop(AF_INET6, &dest->prefix,
-                                                    buf, INET6_ADDRSTRLEN),
-                                          dest->prefixlen);
-                       SET_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED);
-               } else {
-                       dest = (struct prefix_ipv6 *)&request->prefix;
-
-                       if (IS_OSPF6_DEBUG_ZEBRA(SEND))
-                               zlog_debug(
-                                       "Zebra: Blackhole route present already %s/%d",
-                                       inet_ntop(AF_INET6, &dest->prefix, buf,
-                                                 INET6_ADDRSTRLEN),
-                                       dest->prefixlen);
-               }
-       }
-}
-
-void ospf6_zebra_delete_discard(struct ospf6_route *request)
-{
-       struct zapi_ipv6 api;
+       struct zapi_route api;
        char buf[INET6_ADDRSTRLEN];
-       struct prefix_ipv6 *dest;
-
-       if (vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6],
-                            VRF_DEFAULT)) {
-               if (CHECK_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) {
-                       api.vrf_id = VRF_DEFAULT;
-                       api.type = ZEBRA_ROUTE_OSPF6;
-                       api.flags = ZEBRA_FLAG_BLACKHOLE;
-                       api.instance = 0;
-                       api.message = 0;
-                       api.safi = SAFI_UNICAST;
-                       SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
-                       api.nexthop_num = 0;
-                       api.ifindex_num = 0;
-
-                       dest = (struct prefix_ipv6 *)&request->prefix;
-
-                       zapi_ipv6_route(ZEBRA_IPV6_ROUTE_DELETE, zclient, dest,
-                                       NULL, &api);
-
-                       if (IS_OSPF6_DEBUG_ZEBRA(SEND))
-                               zlog_debug("Zebra: Route delete discard %s/%d",
-                                          inet_ntop(AF_INET6, &dest->prefix,
-                                                    buf, INET6_ADDRSTRLEN),
-                                          dest->prefixlen);
-                       UNSET_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED);
-               } else {
-                       dest = (struct prefix_ipv6 *)&request->prefix;
-                       if (IS_OSPF6_DEBUG_ZEBRA(SEND))
-                               zlog_debug(
-                                       "Zebra: Blackhole route already deleted %s/%d",
-                                       inet_ntop(AF_INET6, &dest->prefix, buf,
-                                                 INET6_ADDRSTRLEN),
-                                       dest->prefixlen);
-               }
-       }
-}
-
-DEFUN (redistribute_ospf6,
-       redistribute_ospf6_cmd,
-       "redistribute ospf6",
-       "Redistribute control\n"
-       "OSPF6 route\n")
-{
-       struct ospf6_route *route;
-
-       if (vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6],
-                            VRF_DEFAULT))
-               return CMD_SUCCESS;
-
-       vrf_bitmap_set(zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6],
-                      VRF_DEFAULT);
+       struct prefix *dest = &request->prefix;
 
-       if (ospf6 == NULL)
-               return CMD_SUCCESS;
+       if (!CHECK_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) {
+               memset(&api, 0, sizeof(api));
+               api.vrf_id = VRF_DEFAULT;
+               api.type = ZEBRA_ROUTE_OSPF6;
+               api.flags = ZEBRA_FLAG_BLACKHOLE;
+               api.safi = SAFI_UNICAST;
+               api.prefix = *dest;
 
-       /* send ospf6 route to zebra route table */
-       for (route = ospf6_route_head(ospf6->route_table); route;
-            route = ospf6_route_next(route))
-               ospf6_zebra_route_update_add(route);
+               zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api);
 
-       ospf6->route_table->hook_add = ospf6_zebra_route_update_add;
-       ospf6->route_table->hook_remove = ospf6_zebra_route_update_remove;
+               if (IS_OSPF6_DEBUG_ZEBRA(SEND))
+                       zlog_debug("Zebra: Route add discard %s/%d",
+                                  inet_ntop(AF_INET6, &dest->u.prefix6, buf,
+                                            INET6_ADDRSTRLEN),
+                                  dest->prefixlen);
 
-       return CMD_SUCCESS;
+               SET_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED);
+       } else {
+               if (IS_OSPF6_DEBUG_ZEBRA(SEND))
+                       zlog_debug(
+                               "Zebra: Blackhole route present already %s/%d",
+                               inet_ntop(AF_INET6, &dest->u.prefix6, buf,
+                                         INET6_ADDRSTRLEN),
+                               dest->prefixlen);
+       }
 }
 
-DEFUN (no_redistribute_ospf6,
-       no_redistribute_ospf6_cmd,
-       "no redistribute ospf6",
-       NO_STR
-       "Redistribute control\n"
-       "OSPF6 route\n")
+void ospf6_zebra_delete_discard(struct ospf6_route *request)
 {
-       struct ospf6_route *route;
+       struct zapi_route api;
+       char buf[INET6_ADDRSTRLEN];
+       struct prefix *dest = &request->prefix;
 
-       if (!vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6],
-                             VRF_DEFAULT))
-               return CMD_SUCCESS;
+       if (CHECK_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) {
+               memset(&api, 0, sizeof(api));
+               api.vrf_id = VRF_DEFAULT;
+               api.type = ZEBRA_ROUTE_OSPF6;
+               api.flags = ZEBRA_FLAG_BLACKHOLE;
+               api.safi = SAFI_UNICAST;
+               api.prefix = *dest;
 
-       vrf_bitmap_unset(zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6],
-                        VRF_DEFAULT);
+               zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
 
-       if (ospf6 == NULL)
-               return CMD_SUCCESS;
-
-       ospf6->route_table->hook_add = NULL;
-       ospf6->route_table->hook_remove = NULL;
-
-       /* withdraw ospf6 route from zebra route table */
-       for (route = ospf6_route_head(ospf6->route_table); route;
-            route = ospf6_route_next(route))
-               ospf6_zebra_route_update_remove(route);
+               if (IS_OSPF6_DEBUG_ZEBRA(SEND))
+                       zlog_debug("Zebra: Route delete discard %s/%d",
+                                  inet_ntop(AF_INET6, &dest->u.prefix6, buf,
+                                            INET6_ADDRSTRLEN),
+                                  dest->prefixlen);
 
-       return CMD_SUCCESS;
+               UNSET_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED);
+       } else {
+               if (IS_OSPF6_DEBUG_ZEBRA(SEND))
+                       zlog_debug(
+                               "Zebra: Blackhole route already deleted %s/%d",
+                               inet_ntop(AF_INET6, &dest->u.prefix6, buf,
+                                         INET6_ADDRSTRLEN),
+                               dest->prefixlen);
+       }
 }
 
 static struct ospf6_distance *ospf6_distance_new(void)
@@ -785,24 +598,11 @@ void ospf6_zebra_init(struct thread_master *master)
        zclient->interface_address_add = ospf6_zebra_if_address_update_add;
        zclient->interface_address_delete =
                ospf6_zebra_if_address_update_delete;
-       zclient->redistribute_route_ipv4_add = NULL;
-       zclient->redistribute_route_ipv4_del = NULL;
-       zclient->redistribute_route_ipv6_add = ospf6_zebra_read_ipv6;
-       zclient->redistribute_route_ipv6_del = ospf6_zebra_read_ipv6;
-
-       /* redistribute connected route by default */
-       /* ospf6_zebra_redistribute (ZEBRA_ROUTE_CONNECT); */
-
-       /* Install zebra node. */
-       install_node(&zebra_node, config_write_ospf6_zebra);
+       zclient->redistribute_route_add = ospf6_zebra_read_route;
+       zclient->redistribute_route_del = ospf6_zebra_read_route;
 
        /* Install command element for zebra node. */
        install_element(VIEW_NODE, &show_ospf6_zebra_cmd);
-       install_default(ZEBRA_NODE);
-       install_element(ZEBRA_NODE, &redistribute_ospf6_cmd);
-       install_element(ZEBRA_NODE, &no_redistribute_ospf6_cmd);
-
-       return;
 }
 
 /* Debug */
index 6b47fca578d0cd8e4e691615bbd4155863c27063..84a56fb505a46891e099c09a048ac104a0893423 100644 (file)
@@ -24,6 +24,7 @@
 #include "linklist.h"
 #include "vty.h"
 #include "command.h"
+#include "plist.h"
 
 #include "ospf6_proto.h"
 #include "ospf6_network.h"
@@ -44,8 +45,6 @@
 #include "ospf6d.h"
 #include "ospf6_bfd.h"
 
-char ospf6_daemon_version[] = OSPF6_DAEMON_VERSION;
-
 struct route_node *route_prev(struct route_node *node)
 {
        struct route_node *end;
@@ -70,21 +69,6 @@ struct route_node *route_prev(struct route_node *node)
        return prev;
 }
 
-
-/* show database functions */
-DEFUN (show_version_ospf6,
-       show_version_ospf6_cmd,
-       "show version ospf6",
-       SHOW_STR
-       "Display version\n"
-       "Display ospf6d version\n"
-      )
-{
-       vty_out(vty, "Zebra OSPF6d Version: %s\n", ospf6_daemon_version);
-
-       return CMD_SUCCESS;
-}
-
 static struct cmd_node debug_node = {
        DEBUG_NODE, "", 1 /* VTYSH */
 };
@@ -102,10 +86,24 @@ static int config_write_ospf6_debug(struct vty *vty)
        config_write_ospf6_debug_asbr(vty);
        config_write_ospf6_debug_abr(vty);
        config_write_ospf6_debug_flood(vty);
-       vty_out(vty, "!\n");
+
        return 0;
 }
 
+DEFUN_NOSH (show_debugging_ospf6,
+           show_debugging_ospf6_cmd,
+           "show debugging [ospf6]",
+           SHOW_STR
+           DEBUG_STR
+           OSPF6_STR)
+{
+       vty_out(vty, "OSPF6 debugging status:");
+
+       config_write_ospf6_debug(vty);
+
+       return CMD_SUCCESS;
+}
+
 #define AREA_LSDB_TITLE_FORMAT                                                 \
        "\n        Area Scoped Link State Database (Area %s)\n\n"
 #define IF_LSDB_TITLE_FORMAT                                                   \
@@ -1142,6 +1140,20 @@ DEFUN (show_ipv6_ospf6_linkstate_detail,
        return CMD_SUCCESS;
 }
 
+static void ospf6_plist_add(struct prefix_list *plist)
+{
+       if (prefix_list_afi(plist) != AFI_IP6)
+               return;
+       ospf6_area_plist_update(plist, 1);
+}
+
+static void ospf6_plist_del(struct prefix_list *plist)
+{
+       if (prefix_list_afi(plist) != AFI_IP6)
+               return;
+       ospf6_area_plist_update(plist, 0);
+}
+
 /* Install ospf related commands. */
 void ospf6_init(void)
 {
@@ -1157,6 +1169,9 @@ void ospf6_init(void)
        ospf6_asbr_init();
        ospf6_abr_init();
 
+       prefix_list_add_hook(ospf6_plist_add);
+       prefix_list_delete_hook(ospf6_plist_del);
+
        ospf6_bfd_init();
        install_node(&debug_node, config_write_ospf6_debug);
 
@@ -1174,7 +1189,7 @@ void ospf6_init(void)
 
        install_element_ospf6_clear_interface();
 
-       install_element(VIEW_NODE, &show_version_ospf6_cmd);
+       install_element(VIEW_NODE, &show_debugging_ospf6_cmd);
 
        install_element(VIEW_NODE, &show_ipv6_ospf6_border_routers_cmd);
 
index 1515c3ad0c9a814a8c0e3536e0cf97de4185b274..77a40eac63f60a441cee57d604a7b909dd77ea8e 100644 (file)
@@ -21,8 +21,6 @@
 #ifndef OSPF6D_H
 #define OSPF6D_H
 
-#define OSPF6_DAEMON_VERSION    "0.9.7r"
-
 #include "libospf.h"
 #include "thread.h"
 
index d3d1ffed5ec3f19b631d4ef0a03a2330e305b49e..619bd4e5f529d9b7546a49b09a1072103a0d5dea 100644 (file)
@@ -1597,12 +1597,12 @@ static int show_debugging_ospf_common(struct vty *vty, struct ospf *ospf)
        return CMD_SUCCESS;
 }
 
-DEFUN (show_debugging_ospf,
-       show_debugging_ospf_cmd,
-       "show debugging ospf",
-       SHOW_STR
-       DEBUG_STR
-       OSPF_STR)
+DEFUN_NOSH (show_debugging_ospf,
+           show_debugging_ospf_cmd,
+           "show debugging [ospf]",
+           SHOW_STR
+           DEBUG_STR
+           OSPF_STR)
 {
        struct ospf *ospf;
 
@@ -1612,13 +1612,13 @@ DEFUN (show_debugging_ospf,
        return show_debugging_ospf_common(vty, ospf);
 }
 
-DEFUN (show_debugging_ospf_instance,
-       show_debugging_ospf_instance_cmd,
-       "show debugging ospf (1-65535)",
-       SHOW_STR
-       DEBUG_STR
-       OSPF_STR
-       "Instance ID\n")
+DEFUN_NOSH (show_debugging_ospf_instance,
+           show_debugging_ospf_instance_cmd,
+           "show debugging ospf (1-65535)",
+           SHOW_STR
+           DEBUG_STR
+           OSPF_STR
+           "Instance ID\n")
 {
        int idx_number = 3;
        struct ospf *ospf;
index 4ea8ec26f2acf892d923a212e60f361484b6007a..54639afd6c852cf4cf2bb52f8ddc6f14eec7d3d0 100644 (file)
@@ -1163,6 +1163,6 @@ void ospf_if_init()
 {
        /* Initialize Zebra interface data structure. */
        om->iflist = vrf_iflist(VRF_DEFAULT);
-       if_add_hook(IF_NEW_HOOK, ospf_if_new_hook);
-       if_add_hook(IF_DELETE_HOOK, ospf_if_delete_hook);
+       hook_register_prio(if_add, 0, ospf_if_new_hook);
+       hook_register_prio(if_del, 0, ospf_if_delete_hook);
 }
index ac2406ec2d363f5733d495e2b73359606ac6f10c..36f9a6757a1d4bb34bca4ff3deb5685157a87e9a 100644 (file)
@@ -3938,7 +3938,7 @@ void ospf_ls_upd_send(struct ospf_neighbor *nbr, struct list *update, int flag)
                if (flag == OSPF_SEND_PACKET_INDIRECT)
                        zlog_warn(
                                "* LS-Update is directly sent on NBMA network.");
-               if (IPV4_ADDR_SAME(&oi->address->u.prefix4, &p.prefix.s_addr))
+               if (IPV4_ADDR_SAME(&oi->address->u.prefix4, &p.prefix))
                        zlog_warn("* LS-Update is sent to myself.");
        }
 
index d9354e0cb13160853feae7666616630de5d60b55..c52790a8394132486bd8f919b50773983ce262b9 100644 (file)
@@ -1897,7 +1897,8 @@ DEFUN (no_ospf_area_filter_list,
 
 DEFUN (ospf_area_authentication_message_digest,
        ospf_area_authentication_message_digest_cmd,
-       "area <A.B.C.D|(0-4294967295)> authentication message-digest",
+       "[no] area <A.B.C.D|(0-4294967295)> authentication message-digest",
+       NO_STR
        "OSPF area parameters\n"
        "OSPF area ID in IP address format\n"
        "OSPF area ID as a decimal value\n"
@@ -1914,7 +1915,7 @@ DEFUN (ospf_area_authentication_message_digest,
 
        area = ospf_area_get(ospf, area_id);
        ospf_area_display_format_set(ospf, area, format);
-       area->auth_type = OSPF_AUTH_CRYPTOGRAPHIC;
+       area->auth_type = strmatch(argv[0]->text, "no") ? OSPF_AUTH_NULL : OSPF_AUTH_CRYPTOGRAPHIC;
 
        return CMD_SUCCESS;
 }
@@ -2267,7 +2268,9 @@ DEFUN (no_ospf_timers_lsa_min_arrival,
        return CMD_SUCCESS;
 }
 
-/* Deprecated: 08/07/2017 */
+#if CONFDATE > 20180708
+CPP_NOTICE("ospf: `timers lsa arrival (0-1000)` deprecated 2017/07/08")
+#endif
 ALIAS_HIDDEN (ospf_timers_lsa_min_arrival,
               ospf_timers_lsa_arrival_cmd,
               "timers lsa arrival (0-1000)",
@@ -2276,7 +2279,9 @@ ALIAS_HIDDEN (ospf_timers_lsa_min_arrival,
               "ospf minimum arrival interval delay\n"
               "delay (msec) between accepted lsas\n");
 
-/* Deprecated: 08/07/2017 */
+#if CONFDATE > 20180708
+CPP_NOTICE("ospf: `no timers lsa arrival (0-1000)` deprecated 2017/07/08")
+#endif
 ALIAS_HIDDEN (no_ospf_timers_lsa_min_arrival,
               no_ospf_timers_lsa_arrival_cmd,
               "no timers lsa arrival (0-1000)",
@@ -4032,12 +4037,13 @@ DEFUN (show_ip_ospf_neighbor_int,
        JSON_STR)
 {
        struct ospf *ospf;
+       int idx_ifname = 4;
        u_char uj = use_json(argc, argv);
 
        if ((ospf = ospf_lookup()) == NULL || !ospf->oi_running)
                return CMD_SUCCESS;
 
-       return show_ip_ospf_neighbor_int_common(vty, ospf, 0, argv, uj);
+       return show_ip_ospf_neighbor_int_common(vty, ospf, idx_ifname, argv, uj);
 }
 
 DEFUN (show_ip_ospf_instance_neighbor_int,
@@ -4052,6 +4058,7 @@ DEFUN (show_ip_ospf_instance_neighbor_int,
        JSON_STR)
 {
        int idx_number = 3;
+       int idx_ifname = 5;
        struct ospf *ospf;
        u_short instance = 0;
        u_char uj = use_json(argc, argv);
@@ -4064,7 +4071,7 @@ DEFUN (show_ip_ospf_instance_neighbor_int,
        if (!ospf->oi_running)
                return CMD_SUCCESS;
 
-       return show_ip_ospf_neighbor_int_common(vty, ospf, 1, argv, uj);
+       return show_ip_ospf_neighbor_int_common(vty, ospf, idx_ifname, argv, uj);
 }
 
 static void show_ip_ospf_nbr_nbma_detail_sub(struct vty *vty,
@@ -4422,12 +4429,13 @@ DEFUN (show_ip_ospf_neighbor_id,
        JSON_STR)
 {
        struct ospf *ospf;
+       int idx_router_id = 4;
        u_char uj = use_json(argc, argv);
 
        if ((ospf = ospf_lookup()) == NULL || !ospf->oi_running)
                return CMD_SUCCESS;
 
-       return show_ip_ospf_neighbor_id_common(vty, ospf, 0, argv, uj);
+       return show_ip_ospf_neighbor_id_common(vty, ospf, idx_router_id, argv, uj);
 }
 
 DEFUN (show_ip_ospf_instance_neighbor_id,
@@ -4442,6 +4450,7 @@ DEFUN (show_ip_ospf_instance_neighbor_id,
        JSON_STR)
 {
        int idx_number = 3;
+       int idx_router_id = 5;
        struct ospf *ospf;
        u_short instance = 0;
        u_char uj = use_json(argc, argv);
@@ -4454,7 +4463,7 @@ DEFUN (show_ip_ospf_instance_neighbor_id,
        if (!ospf->oi_running)
                return CMD_SUCCESS;
 
-       return show_ip_ospf_neighbor_id_common(vty, ospf, 1, argv, uj);
+       return show_ip_ospf_neighbor_id_common(vty, ospf, idx_router_id, argv, uj);
 }
 
 static int show_ip_ospf_neighbor_detail_common(struct vty *vty,
@@ -4725,12 +4734,13 @@ DEFUN (show_ip_ospf_neighbor_int_detail,
        JSON_STR)
 {
        struct ospf *ospf;
+       int idx_ifname = 4;
        u_char uj = use_json(argc, argv);
 
        if ((ospf = ospf_lookup()) == NULL || !ospf->oi_running)
                return CMD_SUCCESS;
 
-       return show_ip_ospf_neighbor_int_detail_common(vty, ospf, 0, argv, uj);
+       return show_ip_ospf_neighbor_int_detail_common(vty, ospf, idx_ifname, argv, uj);
 }
 
 DEFUN (show_ip_ospf_instance_neighbor_int_detail,
@@ -4746,6 +4756,7 @@ DEFUN (show_ip_ospf_instance_neighbor_int_detail,
        JSON_STR)
 {
        int idx_number = 3;
+       int idx_ifname = 5;
        struct ospf *ospf;
        u_short instance = 0;
        u_char uj = use_json(argc, argv);
@@ -4758,7 +4769,7 @@ DEFUN (show_ip_ospf_instance_neighbor_int_detail,
        if (!ospf->oi_running)
                return CMD_SUCCESS;
 
-       return show_ip_ospf_neighbor_int_detail_common(vty, ospf, 1, argv, uj);
+       return show_ip_ospf_neighbor_int_detail_common(vty, ospf, idx_ifname, argv, uj);
 }
 
 /* Show functions */
@@ -6881,10 +6892,12 @@ DEFUN (no_ip_ospf_transmit_delay,
 
 DEFUN_HIDDEN (no_ospf_transmit_delay,
               no_ospf_transmit_delay_cmd,
-              "no ospf transmit-delay",
+              "no ospf transmit-delay [(1-65535) [A.B.C.D]]",
               NO_STR
               "OSPF interface commands\n"
-              "Link state transmit delay\n")
+              "Link state transmit delay\n"
+              "Seconds\n"
+              "Address of interface")
 {
        return no_ip_ospf_transmit_delay(self, vty, argc, argv);
 }
index d615afc0727a7b8f498f2c099b0f97fbac9ff0e5..dcb392f1add5129ba9411e7fa64ae6448117ab75 100644 (file)
@@ -333,272 +333,144 @@ static int ospf_interface_link_params(int command, struct zclient *zclient,
 
 void ospf_zebra_add(struct prefix_ipv4 *p, struct ospf_route * or)
 {
-       u_char message;
+       struct zapi_route api;
+       struct zapi_nexthop *api_nh;
        u_char distance;
-       u_int32_t flags;
-       int psize;
-       struct stream *s;
        struct ospf_path *path;
        struct listnode *node;
        struct ospf *ospf = ospf_lookup();
+       int count = 0;
+
+       memset(&api, 0, sizeof(api));
+       api.vrf_id = VRF_DEFAULT;
+       api.type = ZEBRA_ROUTE_OSPF;
+       api.instance = ospf->instance;
+       api.safi = SAFI_UNICAST;
+
+       memcpy(&api.prefix, p, sizeof(*p));
+       SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
+       api.nexthop_num = or->paths->count;
+
+       /* Metric value. */
+       SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
+       if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL)
+               api.metric = or->cost + or->u.ext.type2_cost;
+       else if (or->path_type == OSPF_PATH_TYPE2_EXTERNAL)
+               api.metric = or->u.ext.type2_cost;
+       else
+               api.metric = or->cost;
+
+       /* Check if path type is ASE */
+       if (((or->path_type == OSPF_PATH_TYPE1_EXTERNAL)
+            || (or->path_type == OSPF_PATH_TYPE2_EXTERNAL))
+           && (or->u.ext.tag > 0) && (or->u.ext.tag <= ROUTE_TAG_MAX)) {
+               SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
+               api.tag = or->u.ext.tag;
+       }
 
-       if ((ospf->instance
-            && redist_check_instance(
-                       &zclient->mi_redist[AFI_IP][ZEBRA_ROUTE_OSPF],
-                       ospf->instance))
-           || vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_OSPF],
-                               VRF_DEFAULT)) {
-               message = 0;
-               flags = 0;
-
-               /* OSPF pass nexthop and metric */
-               SET_FLAG(message, ZAPI_MESSAGE_NEXTHOP);
-               SET_FLAG(message, ZAPI_MESSAGE_METRIC);
-
-               /* Distance value. */
-               distance = ospf_distance_apply(p, or);
-               if (distance)
-                       SET_FLAG(message, ZAPI_MESSAGE_DISTANCE);
-
-               /* Check if path type is ASE */
-               if (((or->path_type == OSPF_PATH_TYPE1_EXTERNAL)
-                    || (or->path_type == OSPF_PATH_TYPE2_EXTERNAL))
-                   && (or->u.ext.tag > 0) && (or->u.ext.tag <= ROUTE_TAG_MAX))
-                       SET_FLAG(message, ZAPI_MESSAGE_TAG);
-
-               /* Make packet. */
-               s = zclient->obuf;
-               stream_reset(s);
-
-               /* Put command, type, flags, message. */
-               zclient_create_header(s, ZEBRA_IPV4_ROUTE_ADD, VRF_DEFAULT);
-               stream_putc(s, ZEBRA_ROUTE_OSPF);
-               stream_putw(s, ospf->instance);
-               stream_putl(s, flags);
-               stream_putc(s, message);
-               stream_putw(s, SAFI_UNICAST);
-
-               /* Put prefix information. */
-               psize = PSIZE(p->prefixlen);
-               stream_putc(s, p->prefixlen);
-               stream_write(s, (u_char *)&p->prefix, psize);
-
-               /* Nexthop count. */
-               stream_putc(s, or->paths->count);
-
-               /* Nexthop, ifindex, distance and metric information. */
-               for (ALL_LIST_ELEMENTS_RO(or->paths, node, path)) {
+       /* Distance value. */
+       distance = ospf_distance_apply(p, or);
+       if (distance) {
+               SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE);
+               api.distance = distance;
+       }
+
+       /* Nexthop, ifindex, distance and metric information. */
+       for (ALL_LIST_ELEMENTS_RO(or->paths, node, path)) {
+               api_nh = &api.nexthops[count];
 #ifdef HAVE_NETLINK
-                       if (path->unnumbered
-                           || (path->nexthop.s_addr != INADDR_ANY
-                               && path->ifindex != 0)) {
-                               stream_putc(s, NEXTHOP_TYPE_IPV4_IFINDEX);
-                               stream_put_in_addr(s, &path->nexthop);
-                               stream_putl(s, path->ifindex);
-                       } else if (path->nexthop.s_addr != INADDR_ANY) {
-                               stream_putc(s, NEXTHOP_TYPE_IPV4);
-                               stream_put_in_addr(s, &path->nexthop);
-                       } else {
-                               stream_putc(s, NEXTHOP_TYPE_IFINDEX);
-                               if (path->ifindex)
-                                       stream_putl(s, path->ifindex);
-                               else
-                                       stream_putl(s, 0);
-                       }
+               if (path->unnumbered || (path->nexthop.s_addr != INADDR_ANY
+                                        && path->ifindex != 0)) {
 #else  /* HAVE_NETLINK */
-                       if (path->nexthop.s_addr != INADDR_ANY
-                           && path->ifindex != 0) {
-                               stream_putc(s, NEXTHOP_TYPE_IPV4_IFINDEX);
-                               stream_put_in_addr(s, &path->nexthop);
-                               stream_putl(s, path->ifindex);
-                       } else if (path->nexthop.s_addr != INADDR_ANY) {
-                               stream_putc(s, NEXTHOP_TYPE_IPV4);
-                               stream_put_in_addr(s, &path->nexthop);
-                       } else {
-                               stream_putc(s, NEXTHOP_TYPE_IFINDEX);
-                               if (path->ifindex)
-                                       stream_putl(s, path->ifindex);
-                               else
-                                       stream_putl(s, 0);
-                       }
+               if (path->nexthop.s_addr != INADDR_ANY && path->ifindex != 0) {
 #endif /* HAVE_NETLINK */
-
-                       if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) {
-                               char buf[2][INET_ADDRSTRLEN];
-                               zlog_debug(
-                                       "Zebra: Route add %s/%d nexthop %s, ifindex=%d",
-                                       inet_ntop(AF_INET, &p->prefix, buf[0],
-                                                 sizeof(buf[0])),
-                                       p->prefixlen,
-                                       inet_ntop(AF_INET, &path->nexthop,
-                                                 buf[1], sizeof(buf[1])),
-                                       path->ifindex);
-                       }
+                       api_nh->gate.ipv4 = path->nexthop;
+                       api_nh->ifindex = path->ifindex;
+                       api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX;
+               } else if (path->nexthop.s_addr != INADDR_ANY) {
+                       api_nh->gate.ipv4 = path->nexthop;
+                       api_nh->type = NEXTHOP_TYPE_IPV4;
+               } else {
+                       api_nh->ifindex = path->ifindex;
+                       api_nh->type = NEXTHOP_TYPE_IFINDEX;
                }
+               count++;
 
-               if (CHECK_FLAG(message, ZAPI_MESSAGE_DISTANCE))
-                       stream_putc(s, distance);
-               if (CHECK_FLAG(message, ZAPI_MESSAGE_METRIC)) {
-                       if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL)
-                               stream_putl(s, or->cost + or->u.ext.type2_cost);
-                       else if (or->path_type == OSPF_PATH_TYPE2_EXTERNAL)
-                               stream_putl(s, or->u.ext.type2_cost);
-                       else
-                               stream_putl(s, or->cost);
+               if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) {
+                       char buf[2][INET_ADDRSTRLEN];
+                       zlog_debug(
+                               "Zebra: Route add %s/%d nexthop %s, ifindex=%d",
+                               inet_ntop(AF_INET, &p->prefix, buf[0],
+                                         sizeof(buf[0])),
+                               p->prefixlen, inet_ntop(AF_INET, &path->nexthop,
+                                                       buf[1], sizeof(buf[1])),
+                               path->ifindex);
                }
-
-               if (CHECK_FLAG(message, ZAPI_MESSAGE_TAG))
-                       stream_putl(s, or->u.ext.tag);
-
-               stream_putw_at(s, 0, stream_get_endp(s));
-
-               zclient_send_message(zclient);
        }
+
+       zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api);
 }
 
 void ospf_zebra_delete(struct prefix_ipv4 *p, struct ospf_route * or)
 {
-       u_char message;
-       u_char distance;
-       u_int32_t flags;
-       int psize;
-       struct stream *s;
-       struct ospf_path *path;
-       struct listnode *node;
+       struct zapi_route api;
        struct ospf *ospf = ospf_lookup();
 
-       if ((ospf->instance
-            && redist_check_instance(
-                       &zclient->mi_redist[AFI_IP][ZEBRA_ROUTE_OSPF],
-                       ospf->instance))
-           || vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_OSPF],
-                               VRF_DEFAULT)) {
-               message = 0;
-               flags = 0;
-               /* Distance value. */
-               distance = ospf_distance_apply(p, or);
-               /* Make packet. */
-               s = zclient->obuf;
-               stream_reset(s);
-
-               /* Put command, type, flags, message. */
-               zclient_create_header(s, ZEBRA_IPV4_ROUTE_DELETE, VRF_DEFAULT);
-               stream_putc(s, ZEBRA_ROUTE_OSPF);
-               stream_putw(s, ospf->instance);
-               stream_putl(s, flags);
-               stream_putc(s, message);
-               stream_putw(s, SAFI_UNICAST);
-
-               /* Put prefix information. */
-               psize = PSIZE(p->prefixlen);
-               stream_putc(s, p->prefixlen);
-               stream_write(s, (u_char *)&p->prefix, psize);
-
-               /* Nexthop count. */
-               stream_putc(s, or->paths->count);
-
-               /* Nexthop, ifindex, distance and metric information. */
-               for (ALL_LIST_ELEMENTS_RO(or->paths, node, path)) {
-                       if (path->nexthop.s_addr != INADDR_ANY
-                           && path->ifindex != 0) {
-                               stream_putc(s, NEXTHOP_TYPE_IPV4_IFINDEX);
-                               stream_put_in_addr(s, &path->nexthop);
-                               stream_putl(s, path->ifindex);
-                       } else if (path->nexthop.s_addr != INADDR_ANY) {
-                               stream_putc(s, NEXTHOP_TYPE_IPV4);
-                               stream_put_in_addr(s, &path->nexthop);
-                       } else {
-                               stream_putc(s, NEXTHOP_TYPE_IFINDEX);
-                               stream_putl(s, path->ifindex);
-                       }
-
-                       if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) {
-                               char buf[2][INET_ADDRSTRLEN];
-                               zlog_debug(
-                                       "Zebra: Route delete %s/%d nexthop %s",
-                                       inet_ntop(AF_INET, &p->prefix, buf[0],
-                                                 sizeof(buf[0])),
-                                       p->prefixlen,
-                                       inet_ntop(AF_INET, &path->nexthop,
-                                                 buf[1], sizeof(buf[1])));
-                       }
-               }
-
-               if (CHECK_FLAG(message, ZAPI_MESSAGE_DISTANCE))
-                       stream_putc(s, distance);
-               if (CHECK_FLAG(message, ZAPI_MESSAGE_METRIC)) {
-                       if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL)
-                               stream_putl(s, or->cost + or->u.ext.type2_cost);
-                       else if (or->path_type == OSPF_PATH_TYPE2_EXTERNAL)
-                               stream_putl(s, or->u.ext.type2_cost);
-                       else
-                               stream_putl(s, or->cost);
-               }
-
-               stream_putw_at(s, 0, stream_get_endp(s));
-
-               zclient_send_message(zclient);
+       memset(&api, 0, sizeof(api));
+       api.vrf_id = VRF_DEFAULT;
+       api.type = ZEBRA_ROUTE_OSPF;
+       api.instance = ospf->instance;
+       api.safi = SAFI_UNICAST;
+       memcpy(&api.prefix, p, sizeof(*p));
+
+       if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) {
+               char buf[INET_ADDRSTRLEN];
+               zlog_debug("Zebra: Route delete %s/%d",
+                          inet_ntop(AF_INET, &p->prefix, buf, sizeof(buf[0])),
+                          p->prefixlen);
        }
+
+       zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
 }
 
 void ospf_zebra_add_discard(struct prefix_ipv4 *p)
 {
-       struct zapi_ipv4 api;
+       struct zapi_route api;
        struct ospf *ospf = ospf_lookup();
 
-       if ((ospf->instance
-            && redist_check_instance(
-                       &zclient->mi_redist[AFI_IP][ZEBRA_ROUTE_OSPF],
-                       ospf->instance))
-           || vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_OSPF],
-                               VRF_DEFAULT)) {
-               api.vrf_id = VRF_DEFAULT;
-               api.type = ZEBRA_ROUTE_OSPF;
-               api.instance = ospf->instance;
-               api.flags = ZEBRA_FLAG_BLACKHOLE;
-               api.message = 0;
-               api.safi = SAFI_UNICAST;
-               SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
-               api.nexthop_num = 0;
-               api.ifindex_num = 0;
-               api.tag = 0;
-
-               zapi_ipv4_route(ZEBRA_IPV4_ROUTE_ADD, zclient, p, &api);
+       memset(&api, 0, sizeof(api));
+       api.vrf_id = VRF_DEFAULT;
+       api.type = ZEBRA_ROUTE_OSPF;
+       api.instance = ospf->instance;
+       api.flags = ZEBRA_FLAG_BLACKHOLE;
+       api.safi = SAFI_UNICAST;
+       memcpy(&api.prefix, p, sizeof(*p));
 
-               if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE))
-                       zlog_debug("Zebra: Route add discard %s/%d",
-                                  inet_ntoa(p->prefix), p->prefixlen);
-       }
+       zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api);
+
+       if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE))
+               zlog_debug("Zebra: Route add discard %s/%d",
+                          inet_ntoa(p->prefix), p->prefixlen);
 }
 
 void ospf_zebra_delete_discard(struct prefix_ipv4 *p)
 {
-       struct zapi_ipv4 api;
+       struct zapi_route api;
        struct ospf *ospf = ospf_lookup();
 
-       if ((ospf->instance
-            && redist_check_instance(
-                       &zclient->mi_redist[AFI_IP][ZEBRA_ROUTE_OSPF],
-                       ospf->instance))
-           || vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_OSPF],
-                               VRF_DEFAULT)) {
-               api.vrf_id = VRF_DEFAULT;
-               api.type = ZEBRA_ROUTE_OSPF;
-               api.instance = ospf->instance;
-               api.flags = ZEBRA_FLAG_BLACKHOLE;
-               api.message = 0;
-               api.safi = SAFI_UNICAST;
-               SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
-               api.nexthop_num = 0;
-               api.ifindex_num = 0;
-               api.tag = 0;
-
-               zapi_ipv4_route(ZEBRA_IPV4_ROUTE_DELETE, zclient, p, &api);
+       memset(&api, 0, sizeof(api));
+       api.vrf_id = VRF_DEFAULT;
+       api.type = ZEBRA_ROUTE_OSPF;
+       api.instance = ospf->instance;
+       api.flags = ZEBRA_FLAG_BLACKHOLE;
+       api.safi = SAFI_UNICAST;
+       memcpy(&api.prefix, p, sizeof(*p));
 
-               if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE))
-                       zlog_debug("Zebra: Route delete discard %s/%d",
-                                  inet_ntoa(p->prefix), p->prefixlen);
-       }
+       zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
+
+       if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE))
+               zlog_debug("Zebra: Route delete discard %s/%d",
+                          inet_ntoa(p->prefix), p->prefixlen);
 }
 
 struct ospf_external *ospf_external_lookup(u_char type, u_short instance)
@@ -1001,61 +873,32 @@ void ospf_routemap_unset(struct ospf_redist *red)
 }
 
 /* Zebra route add and delete treatment. */
-static int ospf_zebra_read_ipv4(int command, struct zclient *zclient,
-                               zebra_size_t length, vrf_id_t vrf_id)
+static int ospf_zebra_read_route(int command, struct zclient *zclient,
+                                zebra_size_t length, vrf_id_t vrf_id)
 {
-       struct stream *s;
-       struct zapi_ipv4 api;
+       struct zapi_route api;
+       struct prefix_ipv4 p;
        unsigned long ifindex;
        struct in_addr nexthop;
-       struct prefix_ipv4 p;
        struct external_info *ei;
        struct ospf *ospf;
        int i;
 
-       s = zclient->ibuf;
-       ifindex = 0;
-       nexthop.s_addr = 0;
+       ospf = ospf_lookup();
+       if (ospf == NULL)
+               return 0;
 
-       /* Type, flags, message. */
-       api.type = stream_getc(s);
-       api.instance = stream_getw(s);
-       api.flags = stream_getl(s);
-       api.message = stream_getc(s);
+       if (zapi_route_decode(zclient->ibuf, &api) < 0)
+               return -1;
 
-       /* IPv4 prefix. */
-       memset(&p, 0, sizeof(struct prefix_ipv4));
-       p.family = AF_INET;
-       p.prefixlen = MIN(IPV4_MAX_PREFIXLEN, stream_getc(s));
-       stream_get(&p.prefix, s, PSIZE(p.prefixlen));
+       ifindex = api.nexthops[0].ifindex;
+       nexthop = api.nexthops[0].gate.ipv4;
 
+       memcpy(&p, &api.prefix, sizeof(p));
        if (IPV4_NET127(ntohl(p.prefix.s_addr)))
                return 0;
 
-       /* Nexthop, ifindex, distance, metric. */
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) {
-               api.nexthop_num = stream_getc(s);
-               nexthop.s_addr = stream_get_ipv4(s);
-       }
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) {
-               api.ifindex_num = stream_getc(s);
-               /* XXX assert(api.ifindex_num == 1); */
-               ifindex = stream_getl(s);
-       }
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE))
-               api.distance = stream_getc(s);
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC))
-               api.metric = stream_getl(s);
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG))
-               api.tag = stream_getl(s);
-       else
-               api.tag = 0;
-
-       ospf = ospf_lookup();
-       if (ospf == NULL)
-               return 0;
-
-       if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD) {
+       if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD) {
                /* XXX|HACK|TODO|FIXME:
                 * Maybe we should ignore reject/blackhole routes? Testing shows
                 * that
@@ -1070,7 +913,7 @@ static int ospf_zebra_read_ipv4(int command, struct zclient *zclient,
                 * return 0;
                 */
 
-               /* Protocol tag overwrites all other tag value send by zebra */
+               /* Protocol tag overwrites all other tag value sent by zebra */
                if (ospf->dtag[api.type] > 0)
                        api.tag = ospf->dtag[api.type];
 
@@ -1112,7 +955,7 @@ static int ospf_zebra_read_ipv4(int command, struct zclient *zclient,
                                                            zebra,
                                                            ZEBRA_REDISTRIBUTE))
                                                        zlog_debug(
-                                                               "ospf_zebra_read_ipv4() : %s refreshing LSA",
+                                                               "ospf_zebra_read_route() : %s refreshing LSA",
                                                                inet_ntoa(
                                                                        p.prefix));
                                                ospf_external_lsa_refresh(
@@ -1122,7 +965,7 @@ static int ospf_zebra_read_ipv4(int command, struct zclient *zclient,
                                }
                        }
                }
-       } else /* if (command == ZEBRA_REDISTRIBUTE_IPV4_DEL) */
+       } else /* if (command == ZEBRA_REDISTRIBUTE_ROUTE_DEL) */
        {
                ospf_external_info_delete(api.type, api.instance, p);
                if (is_prefix_default(&p))
@@ -1538,8 +1381,8 @@ void ospf_zebra_init(struct thread_master *master, u_short instance)
        zclient->interface_address_delete = ospf_interface_address_delete;
        zclient->interface_link_params = ospf_interface_link_params;
 
-       zclient->redistribute_route_ipv4_add = ospf_zebra_read_ipv4;
-       zclient->redistribute_route_ipv4_del = ospf_zebra_read_ipv4;
+       zclient->redistribute_route_add = ospf_zebra_read_route;
+       zclient->redistribute_route_del = ospf_zebra_read_route;
 
        access_list_add_hook(ospf_filter_update);
        access_list_delete_hook(ospf_filter_update);
index db24aef423648c769fb5b47279c97b26b6c14861..ae509f4a9bbbcdaa00c8aeefd425bf92e6a3754a 100644 (file)
@@ -1666,7 +1666,7 @@ static void pim_show_join_helper(struct vty *vty,
                                               json_row);
        } else {
                vty_out(vty,
-                       "%-9s %-15s %-15s %-15s %-6s %8s %-6s %5s\n",
+                       "%-9s %-15s %-15s %-15s %-10s %8s %-6s %5s\n",
                        ch->interface->name, inet_ntoa(ifaddr),
                        ch_src_str, ch_grp_str,
                        pim_ifchannel_ifjoin_name(ch->ifjoin_state,
@@ -1690,7 +1690,7 @@ static void pim_show_join(struct pim_instance *pim, struct vty *vty, u_char uj)
                json = json_object_new_object();
        else
                vty_out(vty,
-                       "Interface Address         Source          Group           State  Uptime   Expire Prune\n");
+                       "Interface Address         Source          Group           State      Uptime   Expire Prune\n");
 
        for (ALL_LIST_ELEMENTS_RO(vrf_iflist(pim->vrf_id), if_node, ifp)) {
                pim_ifp = ifp->info;
@@ -5066,7 +5066,7 @@ static int pim_rp_cmd_worker(struct pim_instance *pim, struct vty *vty,
 
        if (result == PIM_RP_NO_PATH) {
                vty_out(vty, "%% No Path to RP address specified: %s\n", rp);
-               return CMD_WARNING_CONFIG_FAILED;
+               return CMD_WARNING;
        }
 
        if (result == PIM_GROUP_OVERLAP) {
@@ -7254,14 +7254,17 @@ DEFUN (no_debug_msdp_packets,
 ALIAS(no_debug_msdp_packets, undebug_msdp_packets_cmd, "undebug msdp packets",
       UNDEBUG_STR DEBUG_MSDP_STR DEBUG_MSDP_PACKETS_STR)
 
-DEFUN (show_debugging_pim,
-       show_debugging_pim_cmd,
-       "show debugging pim",
-       SHOW_STR
-       DEBUG_STR
-       PIM_STR)
+DEFUN_NOSH (show_debugging_pim,
+           show_debugging_pim_cmd,
+           "show debugging [pim]",
+           SHOW_STR
+           DEBUG_STR
+           PIM_STR)
 {
+       vty_out(vty, "PIM debugging status\n");
+
        pim_debug_config_write(vty);
+
        return CMD_SUCCESS;
 }
 
index 39f5f2cc4bfd2e83c3887c5801d0b72b8ff6fbe4..b5d6f049485bfc8b10df3fb2d1aa0b592c8432d3 100644 (file)
@@ -42,6 +42,7 @@
 #include "pim_oil.h"
 #include "pim_upstream.h"
 #include "pim_ssm.h"
+#include "pim_rp.h"
 
 RB_GENERATE(pim_ifchannel_rb, pim_ifchannel,
            pim_ifp_rb, pim_ifchannel_compare);
@@ -348,7 +349,7 @@ const char *pim_ifchannel_ifjoin_name(enum pim_ifjoin_state ifjoin_state,
        switch (ifjoin_state) {
        case PIM_IFJOIN_NOINFO:
                if (PIM_IF_FLAG_TEST_S_G_RPT(flags))
-                       return "SGRpt";
+                       return "SGRpt(NI)";
                else
                        return "NOINFO";
                break;
@@ -356,16 +357,28 @@ const char *pim_ifchannel_ifjoin_name(enum pim_ifjoin_state ifjoin_state,
                return "JOIN";
                break;
        case PIM_IFJOIN_PRUNE:
-               return "PRUNE";
+               if (PIM_IF_FLAG_TEST_S_G_RPT(flags))
+                       return "SGRpt(P)";
+               else
+                       return "PRUNE";
                break;
        case PIM_IFJOIN_PRUNE_PENDING:
-               return "PRUNEP";
+               if (PIM_IF_FLAG_TEST_S_G_RPT(flags))
+                       return "SGRpt(PP)";
+               else
+                       return "PRUNEP";
                break;
        case PIM_IFJOIN_PRUNE_TMP:
-               return "PRUNET";
+               if (PIM_IF_FLAG_TEST_S_G_RPT(flags))
+                       return "SGRpt(P')";
+               else
+                       return "PRUNET";
                break;
        case PIM_IFJOIN_PRUNE_PENDING_TMP:
-               return "PRUNEPT";
+               if (PIM_IF_FLAG_TEST_S_G_RPT(flags))
+                       return "SGRpt(PP')";
+               else
+                       return "PRUNEPT";
                break;
        }
 
@@ -628,33 +641,34 @@ static int on_ifjoin_prune_pending_timer(struct thread *t)
        ch = THREAD_ARG(t);
 
        if (ch->ifjoin_state == PIM_IFJOIN_PRUNE_PENDING) {
-               /* Send PruneEcho(S,G) ? */
                ifp = ch->interface;
                pim_ifp = ifp->info;
-               send_prune_echo = (listcount(pim_ifp->pim_neighbor_list) > 1);
-
-               if (send_prune_echo) {
-                       struct pim_rpf rpf;
+               if (!PIM_IF_FLAG_TEST_S_G_RPT(ch->flags)) {
+                       /* Send PruneEcho(S,G) ? */
+                       send_prune_echo =
+                               (listcount(pim_ifp->pim_neighbor_list) > 1);
+
+                       if (send_prune_echo) {
+                               struct pim_rpf rpf;
+
+                               rpf.source_nexthop.interface = ifp;
+                               rpf.rpf_addr.u.prefix4 =
+                                       pim_ifp->primary_address;
+                               pim_jp_agg_single_upstream_send(&rpf,
+                                                               ch->upstream,
+                                                               0);
+                       }
 
-                       rpf.source_nexthop.interface = ifp;
-                       rpf.rpf_addr.u.prefix4 = pim_ifp->primary_address;
-                       pim_jp_agg_single_upstream_send(&rpf, ch->upstream, 0);
-               }
-               /* If SGRpt flag is set on ifchannel, Trigger SGRpt
-                  message on RP path upon prune timer expiry.
-               */
-               if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags)) {
+                       ifjoin_to_noinfo(ch, true);
+               } else {
+                       /* If SGRpt flag is set on ifchannel, Trigger SGRpt
+                        *  message on RP path upon prune timer expiry.
+                        */
+                       ch->ifjoin_state = PIM_IFJOIN_PRUNE;
                        if (ch->upstream)
                                pim_upstream_update_join_desired(pim_ifp->pim,
                                                                 ch->upstream);
-                       /*
-                         ch->ifjoin_state transition to NOINFO state
-                         ch_del is set to 0 for not deleteing from here.
-                         Holdtime expiry (ch_del set to 1) delete the entry.
-                       */
-                       ifjoin_to_noinfo(ch, false);
-               } else
-                       ifjoin_to_noinfo(ch, true);
+               }
                /* from here ch may have been deleted */
        } else {
                zlog_warn(
@@ -1104,7 +1118,6 @@ void pim_ifchannel_local_membership_del(struct interface *ifp,
        orig = ch = pim_ifchannel_find(ifp, sg);
        if (!ch)
                return;
-
        ifmembership_set(ch, PIM_IFMEMBERSHIP_NOINFO);
 
        if (sg->src.s_addr == INADDR_ANY) {
@@ -1311,11 +1324,12 @@ void pim_ifchannel_scan_forward_start(struct interface *new_ifp)
  * we get End of Message
  */
 void pim_ifchannel_set_star_g_join_state(struct pim_ifchannel *ch, int eom,
-                                        uint8_t source_flags, uint8_t join,
-                                        uint8_t starg_alone)
+                                        uint8_t join)
 {
        struct pim_ifchannel *child;
        struct listnode *ch_node;
+       struct pim_instance *pim =
+               ((struct pim_interface *)ch->interface->info)->pim;
 
        if (PIM_DEBUG_PIM_TRACE)
                zlog_debug(
@@ -1326,33 +1340,6 @@ void pim_ifchannel_set_star_g_join_state(struct pim_ifchannel *ch, int eom,
                return;
 
        for (ALL_LIST_ELEMENTS_RO(ch->sources, ch_node, child)) {
-               /* Only *,G Join received and no (SG-RPT) prune.
-                  eom = 1, only (W,G) join_alone is true, WC and RPT are set.
-                  Scan all S,G associated to G and if any SG-RPT
-                  remove the SG-RPT flag.
-               */
-               if (eom && starg_alone && (source_flags & PIM_RPT_BIT_MASK)
-                   && (source_flags & PIM_WILDCARD_BIT_MASK)) {
-                       if (PIM_IF_FLAG_TEST_S_G_RPT(child->flags)) {
-                               struct pim_upstream *up = child->upstream;
-
-                               PIM_IF_FLAG_UNSET_S_G_RPT(child->flags);
-                               if (up) {
-                                       if (PIM_DEBUG_TRACE)
-                                               zlog_debug(
-                                                       "%s: SGRpt flag is cleared, add inherit oif to up %s",
-                                                       __PRETTY_FUNCTION__,
-                                                       up->sg_str);
-                                       pim_channel_add_oif(
-                                               up->channel_oil, ch->interface,
-                                               PIM_OIF_FLAG_PROTO_STAR);
-                                       pim_ifchannel_ifjoin_switch(
-                                               __PRETTY_FUNCTION__, child,
-                                               PIM_IFJOIN_JOIN);
-                               }
-                       }
-               }
-
                if (!PIM_IF_FLAG_TEST_S_G_RPT(child->flags))
                        continue;
 
@@ -1371,8 +1358,30 @@ void pim_ifchannel_set_star_g_join_state(struct pim_ifchannel *ch, int eom,
                        break;
                case PIM_IFJOIN_PRUNE_TMP:
                case PIM_IFJOIN_PRUNE_PENDING_TMP:
-                       if (eom)
+                       if (eom) {
+                               struct pim_upstream *parent =
+                                       child->upstream->parent;
+
+                               PIM_IF_FLAG_UNSET_S_G_RPT(child->flags);
                                child->ifjoin_state = PIM_IFJOIN_NOINFO;
+
+                               if (I_am_RP(pim, child->sg.grp)) {
+                                       pim_channel_add_oif(
+                                               child->upstream->channel_oil,
+                                               ch->interface,
+                                               PIM_OIF_FLAG_PROTO_STAR);
+                                       pim_upstream_switch(
+                                               pim, child->upstream,
+                                               PIM_UPSTREAM_JOINED);
+                                       pim_jp_agg_single_upstream_send(
+                                               &child->upstream->rpf,
+                                               child->upstream, true);
+                               }
+                               if (parent)
+                                       pim_jp_agg_single_upstream_send(
+                                               &parent->rpf,
+                                               parent, true);
+                       }
                        break;
                }
        }
index cef431c30d0f35af712b968a83998b26d853bd2f..0b1a8ea0e872f37b7bcfd564fc9f1bab3335d19c 100644 (file)
@@ -151,8 +151,7 @@ void pim_ifchannel_update_assert_tracking_desired(struct pim_ifchannel *ch);
 
 void pim_ifchannel_scan_forward_start(struct interface *new_ifp);
 void pim_ifchannel_set_star_g_join_state(struct pim_ifchannel *ch, int eom,
-                                        uint8_t source_flags, uint8_t join,
-                                        uint8_t starg_alone);
+                                        uint8_t join);
 
 int pim_ifchannel_compare(const struct pim_ifchannel *ch1,
                          const struct pim_ifchannel *ch2);
index c60e5a65aaee8826eaf084a18e492539b6c16bf8..4f5e534010481500018d4f3bace81dca3a448580 100644 (file)
@@ -231,7 +231,6 @@ int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh,
                uint16_t msg_num_pruned_sources;
                int source;
                struct pim_ifchannel *starg_ch = NULL, *sg_ch = NULL;
-               uint8_t starg_alone = 0;
 
                memset(&sg, 0, sizeof(struct prefix_sg));
                addr_offset = pim_parse_addr_group(&sg, buf, pastend - buf);
@@ -289,12 +288,10 @@ int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh,
                                  msg_source_flags);
 
                        if (sg.src.s_addr == INADDR_ANY) {
-                               starg_alone = 1;
                                starg_ch = pim_ifchannel_find(ifp, &sg);
                                if (starg_ch)
                                        pim_ifchannel_set_star_g_join_state(
-                                               starg_ch, 0, msg_source_flags,
-                                               1, starg_alone);
+                                               starg_ch, 0, 1);
                        }
                }
 
@@ -307,7 +304,6 @@ int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh,
                        }
 
                        buf += addr_offset;
-                       starg_alone = 0;
                        recv_prune(ifp, neigh, msg_holdtime,
                                   msg_upstream_addr.u.prefix4, &sg,
                                   msg_source_flags);
@@ -340,8 +336,7 @@ int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh,
                        }
                }
                if (starg_ch)
-                       pim_ifchannel_set_star_g_join_state(
-                               starg_ch, 1, msg_source_flags, 0, starg_alone);
+                       pim_ifchannel_set_star_g_join_state(starg_ch, 1, 0);
                starg_ch = NULL;
        } /* scan groups */
 
@@ -419,7 +414,7 @@ int pim_joinprune_send(struct pim_rpf *rpf, struct list *groups)
        struct pim_jp_agg_group *group;
        struct pim_interface *pim_ifp = NULL;
        struct pim_jp_groups *grp = NULL;
-       struct pim_jp *msg;
+       struct pim_jp *msg = NULL;
        struct listnode *node, *nnode;
        uint8_t pim_msg[10000];
        uint8_t *curr_ptr = pim_msg;
index 751611479ec770cf4d43e63dc38fb57b85ba2956..96b9568c61cd426c8eaa51a9c595b0eff7c3d480 100644 (file)
@@ -698,6 +698,8 @@ static struct pim_upstream *pim_upstream_new(struct pim_instance *pim,
                if (up->sources)
                        list_delete(up->sources);
 
+               list_delete(up->ifchannels);
+
                hash_release(pim->upstream_hash, up);
                XFREE(MTYPE_PIM_UPSTREAM, up);
                return NULL;
@@ -1622,8 +1624,9 @@ static void pim_upstream_sg_running(void *arg)
        // No packet can have arrived here if this is the case
        if (!up->channel_oil->installed) {
                if (PIM_DEBUG_TRACE)
-                       zlog_debug("%s: %s is not installed in mroute",
-                                  __PRETTY_FUNCTION__, up->sg_str);
+                       zlog_debug("%s: %s[%s] is not installed in mroute",
+                                  __PRETTY_FUNCTION__,
+                                  up->sg_str, pim->vrf->name);
                return;
        }
 
index 8e3c7595b792adcfaed1f207696709f7d33a5764..6a69986323c3844c4169783926f571e24c15f78e 100644 (file)
@@ -36,12 +36,14 @@ class RenderHandler(object):
 
     deref = ''
     drop_str = False
+    canfail = True
 
 class StringHandler(RenderHandler):
     argtype = 'const char *'
     decl = Template('const char *$varname = NULL;')
     code = Template('$varname = argv[_i]->arg;')
     drop_str = True
+    canfail = False
 
 class LongHandler(RenderHandler):
     argtype = 'long'
@@ -130,6 +132,10 @@ handlers = {
 }
 
 # core template invoked for each occurence of DEFPY.
+#
+# the "#if $..." bits are there to keep this template unified into one
+# common form, without requiring a more advanced template engine (e.g.
+# jinja2)
 templ = Template('''/* $fnname => "$cmddef" */
 DEFUN_CMD_FUNC_DECL($fnname)
 #define funcdecl_$fnname static int ${fnname}_magic(\\
@@ -140,20 +146,31 @@ DEFUN_CMD_FUNC_DECL($fnname)
 funcdecl_$fnname;
 DEFUN_CMD_FUNC_TEXT($fnname)
 {
+#if $nonempty /* anything to parse? */
        int _i;
+#if $canfail /* anything that can fail? */
        unsigned _fail = 0, _failcnt = 0;
+#endif
 $argdecls
        for (_i = 0; _i < argc; _i++) {
                if (!argv[_i]->varname)
                        continue;
-               _fail = 0;$argblocks
+#if $canfail /* anything that can fail? */
+               _fail = 0;
+#endif
+$argblocks
+#if $canfail /* anything that can fail? */
                if (_fail)
                        vty_out (vty, "%% invalid input for %s: %s\\n",
                                   argv[_i]->varname, argv[_i]->arg);
                _failcnt += _fail;
+#endif
        }
+#if $canfail /* anything that can fail? */
        if (_failcnt)
                return CMD_WARNING;
+#endif
+#endif
        return ${fnname}_magic(self, vty, argc, argv$arglist);
 }
 
@@ -196,6 +213,7 @@ def process_file(fn, ofd, dumpfd, all_defun):
             arglist = []
             argblocks = []
             doc = []
+            canfail = 0
 
             def do_add(handler, varname, attr = ''):
                 argdefs.append(',\\\n\t%s %s%s' % (handler.argtype, varname, attr))
@@ -213,6 +231,8 @@ def process_file(fn, ofd, dumpfd, all_defun):
                 if handler is None: continue
                 do_add(handler, varname)
                 code = handler.code.substitute({'varname': varname}).replace('\n', '\n\t\t\t')
+                if handler.canfail:
+                    canfail = 1
                 strblock = ''
                 if not handler.drop_str:
                     do_add(StringHandler(None), '%s_str' % (varname), ' __attribute__ ((unused))')
@@ -229,6 +249,8 @@ def process_file(fn, ofd, dumpfd, all_defun):
             params['argdecls'] = ''.join(argdecls)
             params['arglist'] = ''.join(arglist)
             params['argblocks'] = ''.join(argblocks)
+            params['canfail'] = canfail
+            params['nonempty'] = len(argblocks)
             ofd.write(templ.substitute(params))
 
 if __name__ == '__main__':
@@ -257,4 +279,4 @@ if __name__ == '__main__':
     process_file(args.cfile, ofd, dumpfd, args.all_defun)
 
     if args.o is not None:
-        clippy.wrdiff(args.o, ofd)
+        clippy.wrdiff(args.o, ofd, [args.cfile, os.path.realpath(__file__)])
index 82aa9495d44476f7935c64114fd8e065414f7ddb..41aeae6b4d8da09b58051ba4e0b8018954af5886 100644 (file)
@@ -16,6 +16,7 @@
 # with this program; see the file COPYING; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 
+import os, stat
 import _clippy
 from _clippy import parse, Graph, GraphNode
 
@@ -47,7 +48,7 @@ def dump(graph):
     for i, depth in graph_iterate(graph):
         print('\t%s%s %r' % ('  ' * (depth * 2), i.type, i.text))
 
-def wrdiff(filename, buf):
+def wrdiff(filename, buf, reffiles = []):
     '''write buffer to file if contents changed'''
 
     expl = ''
@@ -57,8 +58,16 @@ def wrdiff(filename, buf):
     try:    old = open(filename, 'r').read()
     except: pass
     if old == buf:
+        for reffile in reffiles:
+            # ensure output timestamp is newer than inputs, for make
+            reftime = os.stat(reffile)[stat.ST_MTIME]
+            outtime = os.stat(filename)[stat.ST_MTIME]
+            if outtime <= reftime:
+                os.utime(filename, (reftime + 1, reftime + 1))
         # sys.stderr.write('%s unchanged, not written\n' % (filename))
         return
-    with open('.new.' + filename, 'w') as out:
+
+    newname = '%s.new-%d' % (filename, os.getpid())
+    with open(newname, 'w') as out:
         out.write(buf)
-    os.rename('.new.' + filename, filename)
+    os.rename(newname, filename)
index 12cdcf04fe699df78a59df5df05baabeebe9d529..cc0632b56252035f42cfab193f0ba3e88e506ad2 100644 (file)
@@ -13,7 +13,6 @@
 %{!?with_pam:           %global  with_pam           0 }
 %{!?with_ospfclient:    %global  with_ospfclient    1 }
 %{!?with_ospfapi:       %global  with_ospfapi       1 }
-%{!?with_irdp:          %global  with_irdp          1 }
 %{!?with_rtadv:         %global  with_rtadv         1 }
 %{!?with_ldpd:          %global  with_ldpd          1 }
 %{!?with_nhrpd:         %global  with_nhrpd         1 }
@@ -221,6 +220,7 @@ developing OSPF-API and frr applications.
     --libexecdir=%{_libexecdir} \
     --localstatedir=%{_localstatedir} \
     --disable-werror \
+    --enable-irdp \
 %if !%{with_shared}
     --disable-shared \
 %endif
@@ -238,11 +238,6 @@ developing OSPF-API and frr applications.
 %else
     --enable-ospfapi=no \
 %endif
-%if %{with_irdp}
-    --enable-irdp=yes \
-%else
-    --enable-irdp=no \
-%endif
 %if %{with_rtadv}
     --enable-rtadv=yes \
 %else
@@ -325,6 +320,9 @@ rm -rf %{buildroot}/usr/share/info/dir
 # Remove debian init script if it was installed
 rm -f %{buildroot}%{_sbindir}/frr
 
+# kill bogus libtool files for modules
+rm -f %{buildroot}%{_libdir}/frr/modules/*.la
+
 # install /etc sources
 %if "%{initsystem}" == "systemd"
 mkdir -p %{buildroot}%{_unitdir}
@@ -554,6 +552,7 @@ rm -rf %{buildroot}
 %{_libdir}/lib*.so.0
 %attr(755,root,root) %{_libdir}/lib*.so.0.*
 %endif
+%attr(755,root,root) %{_libdir}/frr/modules/zebra_irdp.so
 %{_bindir}/*
 %config(noreplace) /etc/frr/[!v]*.conf*
 %config(noreplace) %attr(750,%frr_user,%frr_user) /etc/frr/daemons
index 492d036991b9ece51d21a6cda35b7d34b9e0d39f..56ba8e7f3e75426845dfa94d802730d24dee2996 100644 (file)
@@ -27,12 +27,12 @@ unsigned long rip_debug_event = 0;
 unsigned long rip_debug_packet = 0;
 unsigned long rip_debug_zebra = 0;
 
-DEFUN (show_debugging_rip,
-       show_debugging_rip_cmd,
-       "show debugging rip",
-       SHOW_STR
-       DEBUG_STR
-       RIP_STR)
+DEFUN_NOSH (show_debugging_rip,
+           show_debugging_rip_cmd,
+           "show debugging [rip]",
+           SHOW_STR
+           DEBUG_STR
+           RIP_STR)
 {
        vty_out(vty, "RIP debugging status:\n");
 
index a1704711230dc01b31b5b7ed1e9fa7f7cece36a7..00b6d1cadd2aaafc3ed15d9e7b523fc2583eaf3c 100644 (file)
@@ -1877,8 +1877,8 @@ static int rip_interface_delete_hook(struct interface *ifp)
 void rip_if_init(void)
 {
        /* Default initial size of interface vector. */
-       if_add_hook(IF_NEW_HOOK, rip_interface_new_hook);
-       if_add_hook(IF_DELETE_HOOK, rip_interface_delete_hook);
+       hook_register_prio(if_add, 0, rip_interface_new_hook);
+       hook_register_prio(if_del, 0, rip_interface_delete_hook);
 
        /* RIP network init. */
        rip_enable_interface = vector_init(1);
index 961a846db23f82d38db79872357694aabfc9a6e1..2140e8b1101df96748c04e6e44604cda0c3269e5 100644 (file)
@@ -39,155 +39,107 @@ struct zclient *zclient = NULL;
 /* Send ECMP routes to zebra. */
 static void rip_zebra_ipv4_send(struct route_node *rp, u_char cmd)
 {
-       static struct in_addr **nexthops = NULL;
-       static unsigned int nexthops_len = 0;
-
        struct list *list = (struct list *)rp->info;
-       struct zapi_ipv4 api;
+       struct zapi_route api;
+       struct zapi_nexthop *api_nh;
        struct listnode *listnode = NULL;
        struct rip_info *rinfo = NULL;
        int count = 0;
 
-       if (vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_RIP],
-                            VRF_DEFAULT)) {
-               api.vrf_id = VRF_DEFAULT;
-               api.type = ZEBRA_ROUTE_RIP;
-               api.instance = 0;
-               api.flags = 0;
-               api.message = 0;
-               api.safi = SAFI_UNICAST;
-
-               if (nexthops_len < listcount(list)) {
-                       nexthops_len = listcount(list);
-                       nexthops = XREALLOC(MTYPE_TMP, nexthops,
-                                           nexthops_len
-                                                   * sizeof(struct in_addr *));
-               }
-
-               SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
-               for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) {
-                       nexthops[count++] = &rinfo->nexthop;
-                       if (cmd == ZEBRA_IPV4_ROUTE_ADD)
-                               SET_FLAG(rinfo->flags, RIP_RTF_FIB);
-                       else
-                               UNSET_FLAG(rinfo->flags, RIP_RTF_FIB);
-               }
-
-               api.nexthop = nexthops;
-               api.nexthop_num = count;
-               api.ifindex_num = 0;
+       memset(&api, 0, sizeof(api));
+       api.vrf_id = VRF_DEFAULT;
+       api.type = ZEBRA_ROUTE_RIP;
+       api.safi = SAFI_UNICAST;
+
+       SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
+       for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) {
+               api_nh = &api.nexthops[count];
+               api_nh->gate.ipv4 = rinfo->nexthop;
+               api_nh->type = NEXTHOP_TYPE_IPV4;
+               if (cmd == ZEBRA_ROUTE_ADD)
+                       SET_FLAG(rinfo->flags, RIP_RTF_FIB);
+               else
+                       UNSET_FLAG(rinfo->flags, RIP_RTF_FIB);
+               count++;
+       }
 
-               rinfo = listgetdata(listhead(list));
+       api.prefix = rp->p;
+       api.nexthop_num = count;
 
-               SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
-               api.metric = rinfo->metric;
+       rinfo = listgetdata(listhead(list));
 
-               if (rinfo->distance
-                   && rinfo->distance != ZEBRA_RIP_DISTANCE_DEFAULT) {
-                       SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE);
-                       api.distance = rinfo->distance;
-               }
+       SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
+       api.metric = rinfo->metric;
 
-               if (rinfo->tag) {
-                       SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
-                       api.tag = rinfo->tag;
-               }
+       if (rinfo->distance && rinfo->distance != ZEBRA_RIP_DISTANCE_DEFAULT) {
+               SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE);
+               api.distance = rinfo->distance;
+       }
 
-               zapi_ipv4_route(cmd, zclient, (struct prefix_ipv4 *)&rp->p,
-                               &api);
-
-               if (IS_RIP_DEBUG_ZEBRA) {
-                       if (rip->ecmp)
-                               zlog_debug("%s: %s/%d nexthops %d",
-                                          (cmd == ZEBRA_IPV4_ROUTE_ADD)
-                                                  ? "Install into zebra"
-                                                  : "Delete from zebra",
-                                          inet_ntoa(rp->p.u.prefix4),
-                                          rp->p.prefixlen, count);
-                       else
-                               zlog_debug("%s: %s/%d",
-                                          (cmd == ZEBRA_IPV4_ROUTE_ADD)
-                                                  ? "Install into zebra"
-                                                  : "Delete from zebra",
-                                          inet_ntoa(rp->p.u.prefix4),
-                                          rp->p.prefixlen);
-               }
+       if (rinfo->tag) {
+               SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
+               api.tag = rinfo->tag;
+       }
 
-               rip_global_route_changes++;
+       zclient_route_send(cmd, zclient, &api);
+
+       if (IS_RIP_DEBUG_ZEBRA) {
+               if (rip->ecmp)
+                       zlog_debug("%s: %s/%d nexthops %d",
+                                  (cmd == ZEBRA_ROUTE_ADD)
+                                          ? "Install into zebra"
+                                          : "Delete from zebra",
+                                  inet_ntoa(rp->p.u.prefix4), rp->p.prefixlen,
+                                  count);
+               else
+                       zlog_debug("%s: %s/%d",
+                                  (cmd == ZEBRA_ROUTE_ADD)
+                                          ? "Install into zebra"
+                                          : "Delete from zebra",
+                                  inet_ntoa(rp->p.u.prefix4), rp->p.prefixlen);
        }
+
+       rip_global_route_changes++;
 }
 
 /* Add/update ECMP routes to zebra. */
 void rip_zebra_ipv4_add(struct route_node *rp)
 {
-       rip_zebra_ipv4_send(rp, ZEBRA_IPV4_ROUTE_ADD);
+       rip_zebra_ipv4_send(rp, ZEBRA_ROUTE_ADD);
 }
 
 /* Delete ECMP routes from zebra. */
 void rip_zebra_ipv4_delete(struct route_node *rp)
 {
-       rip_zebra_ipv4_send(rp, ZEBRA_IPV4_ROUTE_DELETE);
+       rip_zebra_ipv4_send(rp, ZEBRA_ROUTE_DELETE);
 }
 
 /* Zebra route add and delete treatment. */
-static int rip_zebra_read_ipv4(int command, struct zclient *zclient,
-                              zebra_size_t length, vrf_id_t vrf_id)
+static int rip_zebra_read_route(int command, struct zclient *zclient,
+                               zebra_size_t length, vrf_id_t vrf_id)
 {
-       struct stream *s;
-       struct zapi_ipv4 api;
-       unsigned long ifindex;
+       struct zapi_route api;
        struct in_addr nexthop;
-       struct prefix_ipv4 p;
+       unsigned long ifindex;
 
        if (!rip)
                return 0;
 
-       s = zclient->ibuf;
-       ifindex = 0;
-       nexthop.s_addr = 0;
-
-       /* Type, flags, message. */
-       api.type = stream_getc(s);
-       api.instance = stream_getw(s);
-       api.flags = stream_getl(s);
-       api.message = stream_getc(s);
-
-       /* IPv4 prefix. */
-       memset(&p, 0, sizeof(struct prefix_ipv4));
-       p.family = AF_INET;
-       p.prefixlen = MIN(IPV4_MAX_PREFIXLEN, stream_getc(s));
-       stream_get(&p.prefix, s, PSIZE(p.prefixlen));
-
-       /* Nexthop, ifindex, distance, metric. */
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) {
-               api.nexthop_num = stream_getc(s);
-               nexthop.s_addr = stream_get_ipv4(s);
-       }
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) {
-               api.ifindex_num = stream_getc(s);
-               ifindex = stream_getl(s);
-       }
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE))
-               api.distance = stream_getc(s);
-       else
-               api.distance = 255;
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC))
-               api.metric = stream_getl(s);
-       else
-               api.metric = 0;
-
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG))
-               api.tag = stream_getl(s);
-       else
-               api.tag = 0;
+       if (zapi_route_decode(zclient->ibuf, &api) < 0)
+               return -1;
+
+       nexthop = api.nexthops[0].gate.ipv4;
+       ifindex = api.nexthops[0].ifindex;
 
        /* Then fetch IPv4 prefixes. */
-       if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD)
-               rip_redistribute_add(api.type, RIP_ROUTE_REDISTRIBUTE, &p,
-                                    ifindex, &nexthop, api.metric,
-                                    api.distance, api.tag);
-       else if (command == ZEBRA_REDISTRIBUTE_IPV4_DEL)
-               rip_redistribute_delete(api.type, RIP_ROUTE_REDISTRIBUTE, &p,
+       if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
+               rip_redistribute_add(api.type, RIP_ROUTE_REDISTRIBUTE,
+                                    (struct prefix_ipv4 *)&api.prefix, ifindex,
+                                    &nexthop, api.metric, api.distance,
+                                    api.tag);
+       else if (command == ZEBRA_REDISTRIBUTE_ROUTE_DEL)
+               rip_redistribute_delete(api.type, RIP_ROUTE_REDISTRIBUTE,
+                                       (struct prefix_ipv4 *)&api.prefix,
                                        ifindex);
 
        return 0;
@@ -298,27 +250,6 @@ void rip_redistribute_clean(void)
        }
 }
 
-DEFUN (rip_redistribute_rip,
-       rip_redistribute_rip_cmd,
-       "redistribute rip",
-       "Redistribute information from another routing protocol\n"
-       "Routing Information Protocol (RIP)\n")
-{
-       vrf_bitmap_set(zclient->redist[AFI_IP][ZEBRA_ROUTE_RIP], VRF_DEFAULT);
-       return CMD_SUCCESS;
-}
-
-DEFUN (no_rip_redistribute_rip,
-       no_rip_redistribute_rip_cmd,
-       "no redistribute rip",
-       NO_STR
-       "Redistribute information from another routing protocol\n"
-       "Routing Information Protocol (RIP)\n")
-{
-       vrf_bitmap_unset(zclient->redist[AFI_IP][ZEBRA_ROUTE_RIP], VRF_DEFAULT);
-       return CMD_SUCCESS;
-}
-
 DEFUN (rip_redistribute_type,
        rip_redistribute_type_cmd,
        "redistribute " FRR_REDIST_STR_RIPD,
@@ -604,66 +535,46 @@ DEFUN (no_rip_default_information_originate,
        return CMD_SUCCESS;
 }
 
-/* RIP configuration write function. */
-static int config_write_zebra(struct vty *vty)
-{
-       if (!zclient->enable) {
-               vty_out(vty, "no router zebra\n");
-               return 1;
-       } else if (!vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_RIP],
-                                    VRF_DEFAULT)) {
-               vty_out(vty, "router zebra\n");
-               vty_out(vty, " no redistribute rip\n");
-               return 1;
-       }
-       return 0;
-}
-
 int config_write_rip_redistribute(struct vty *vty, int config_mode)
 {
        int i;
 
-       for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
-               if (i != zclient->redist_default
-                   && vrf_bitmap_check(zclient->redist[AFI_IP][i],
-                                       VRF_DEFAULT)) {
-                       if (config_mode) {
-                               if (rip->route_map[i].metric_config) {
-                                       if (rip->route_map[i].name)
-                                               vty_out(vty,
-                                                       " redistribute %s metric %d route-map %s\n",
-                                                       zebra_route_string(i),
-                                                       rip->route_map[i]
-                                                               .metric,
-                                                       rip->route_map[i].name);
-                                       else
-                                               vty_out(vty,
-                                                       " redistribute %s metric %d\n",
-                                                       zebra_route_string(i),
-                                                       rip->route_map[i]
-                                                               .metric);
-                               } else {
-                                       if (rip->route_map[i].name)
-                                               vty_out(vty,
-                                                       " redistribute %s route-map %s\n",
-                                                       zebra_route_string(i),
-                                                       rip->route_map[i].name);
-                                       else
-                                               vty_out(vty,
-                                                       " redistribute %s\n",
-                                                       zebra_route_string(i));
-                               }
-                       } else
-                               vty_out(vty, " %s", zebra_route_string(i));
+       for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
+               if (i == zclient->redist_default
+                   || !vrf_bitmap_check(zclient->redist[AFI_IP][i],
+                                        VRF_DEFAULT))
+                       continue;
+
+               if (!config_mode) {
+                       vty_out(vty, " %s", zebra_route_string(i));
+                       continue;
+               }
+
+               if (rip->route_map[i].metric_config) {
+                       if (rip->route_map[i].name)
+                               vty_out(vty,
+                                       " redistribute %s metric %d route-map %s\n",
+                                       zebra_route_string(i),
+                                       rip->route_map[i].metric,
+                                       rip->route_map[i].name);
+                       else
+                               vty_out(vty, " redistribute %s metric %d\n",
+                                       zebra_route_string(i),
+                                       rip->route_map[i].metric);
+               } else {
+                       if (rip->route_map[i].name)
+                               vty_out(vty, " redistribute %s route-map %s\n",
+                                       zebra_route_string(i),
+                                       rip->route_map[i].name);
+                       else
+                               vty_out(vty, " redistribute %s\n",
+                                       zebra_route_string(i));
                }
+       }
+
        return 0;
 }
 
-/* Zebra node structure. */
-static struct cmd_node zebra_node = {
-       ZEBRA_NODE, "%s(config-router)# ",
-};
-
 static void rip_zebra_connected(struct zclient *zclient)
 {
        zclient_send_reg_requests(zclient, VRF_DEFAULT);
@@ -681,16 +592,8 @@ void rip_zclient_init(struct thread_master *master)
        zclient->interface_address_delete = rip_interface_address_delete;
        zclient->interface_up = rip_interface_up;
        zclient->interface_down = rip_interface_down;
-       zclient->redistribute_route_ipv4_add = rip_zebra_read_ipv4;
-       zclient->redistribute_route_ipv4_del = rip_zebra_read_ipv4;
-
-       /* Install zebra node. */
-       install_node(&zebra_node, config_write_zebra);
-
-       /* Install command elements to zebra node. */
-       install_default(ZEBRA_NODE);
-       install_element(ZEBRA_NODE, &rip_redistribute_rip_cmd);
-       install_element(ZEBRA_NODE, &no_rip_redistribute_rip_cmd);
+       zclient->redistribute_route_add = rip_zebra_read_route;
+       zclient->redistribute_route_del = rip_zebra_read_route;
 
        /* Install command elements to rip node. */
        install_element(RIP_NODE, &rip_redistribute_type_cmd);
index d56161d39e19aff0f88f3ecef78280f9637ee7a0..9ebc302b1b32e9be2d72edda4ca0923828535c3e 100644 (file)
@@ -28,12 +28,12 @@ unsigned long ripng_debug_event = 0;
 unsigned long ripng_debug_packet = 0;
 unsigned long ripng_debug_zebra = 0;
 
-DEFUN (show_debugging_ripng,
-       show_debugging_ripng_cmd,
-       "show debugging ripng",
-       SHOW_STR
-       DEBUG_STR
-       "RIPng configuration\n")
+DEFUN_NOSH (show_debugging_ripng,
+           show_debugging_ripng_cmd,
+           "show debugging [ripng]",
+           SHOW_STR
+           DEBUG_STR
+           "RIPng configuration\n")
 {
        vty_out(vty, "RIPng debugging status:\n");
 
index c762d8ace729cadee9c7eb2c3105101352bea045..02fab6825483b48a77449e905063ec0e7c9ee78a 100644 (file)
@@ -1121,8 +1121,8 @@ static struct cmd_node interface_node = {
 void ripng_if_init()
 {
        /* Interface initialize. */
-       if_add_hook(IF_NEW_HOOK, ripng_if_new_hook);
-       if_add_hook(IF_DELETE_HOOK, ripng_if_delete_hook);
+       hook_register_prio(if_add, 0, ripng_if_new_hook);
+       hook_register_prio(if_del, 0, ripng_if_delete_hook);
 
        /* RIPng enable network init. */
        ripng_enable_network = route_table_init();
index 386bee43b8cb6caf6b6acb7f27ad7b22690729bb..283d8691a3db243ffc4596a4c243b545d03df8c6 100644 (file)
@@ -39,162 +39,101 @@ struct zclient *zclient = NULL;
 /* Send ECMP routes to zebra. */
 static void ripng_zebra_ipv6_send(struct route_node *rp, u_char cmd)
 {
-       static struct in6_addr **nexthops = NULL;
-       static ifindex_t *ifindexes = NULL;
-       static unsigned int nexthops_len = 0;
-
        struct list *list = (struct list *)rp->info;
-       struct zapi_ipv6 api;
+       struct zapi_route api;
+       struct zapi_nexthop *api_nh;
        struct listnode *listnode = NULL;
        struct ripng_info *rinfo = NULL;
        int count = 0;
 
-       if (vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_RIPNG],
-                            VRF_DEFAULT)) {
-               api.vrf_id = VRF_DEFAULT;
-               api.type = ZEBRA_ROUTE_RIPNG;
-               api.instance = 0;
-               api.flags = 0;
-               api.message = 0;
-               api.safi = SAFI_UNICAST;
-
-               if (nexthops_len < listcount(list)) {
-                       nexthops_len = listcount(list);
-                       nexthops = XREALLOC(
-                               MTYPE_TMP, nexthops,
-                               nexthops_len * sizeof(struct in6_addr *));
-                       ifindexes =
-                               XREALLOC(MTYPE_TMP, ifindexes,
-                                        nexthops_len * sizeof(unsigned int));
-               }
-
-               SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
-               SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX);
-               for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) {
-                       nexthops[count] = &rinfo->nexthop;
-                       ifindexes[count] = rinfo->ifindex;
-                       count++;
-                       if (cmd == ZEBRA_IPV6_ROUTE_ADD)
-                               SET_FLAG(rinfo->flags, RIPNG_RTF_FIB);
-                       else
-                               UNSET_FLAG(rinfo->flags, RIPNG_RTF_FIB);
-               }
+       memset(&api, 0, sizeof(api));
+       api.vrf_id = VRF_DEFAULT;
+       api.type = ZEBRA_ROUTE_RIPNG;
+       api.safi = SAFI_UNICAST;
+       api.prefix = rp->p;
+
+       SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
+       for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) {
+               api_nh = &api.nexthops[count];
+               api_nh->gate.ipv6 = rinfo->nexthop;
+               api_nh->ifindex = rinfo->ifindex;
+               api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
+               count++;
+               if (cmd == ZEBRA_ROUTE_ADD)
+                       SET_FLAG(rinfo->flags, RIPNG_RTF_FIB);
+               else
+                       UNSET_FLAG(rinfo->flags, RIPNG_RTF_FIB);
+       }
 
-               api.nexthop = nexthops;
-               api.nexthop_num = count;
-               api.ifindex = ifindexes;
-               api.ifindex_num = count;
+       api.nexthop_num = count;
 
-               rinfo = listgetdata(listhead(list));
+       rinfo = listgetdata(listhead(list));
 
-               SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
-               api.metric = rinfo->metric;
+       SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
+       api.metric = rinfo->metric;
 
-               if (rinfo->tag) {
-                       SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
-                       api.tag = rinfo->tag;
-               }
+       if (rinfo->tag) {
+               SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
+               api.tag = rinfo->tag;
+       }
 
-               zapi_ipv6_route(cmd, zclient, (struct prefix_ipv6 *)&rp->p,
-                               NULL, &api);
-
-               if (IS_RIPNG_DEBUG_ZEBRA) {
-                       if (ripng->ecmp)
-                               zlog_debug("%s: %s/%d nexthops %d",
-                                          (cmd == ZEBRA_IPV6_ROUTE_ADD)
-                                                  ? "Install into zebra"
-                                                  : "Delete from zebra",
-                                          inet6_ntoa(rp->p.u.prefix6),
-                                          rp->p.prefixlen, count);
-                       else
-                               zlog_debug("%s: %s/%d",
-                                          (cmd == ZEBRA_IPV6_ROUTE_ADD)
-                                                  ? "Install into zebra"
-                                                  : "Delete from zebra",
-                                          inet6_ntoa(rp->p.u.prefix6),
-                                          rp->p.prefixlen);
-               }
+       zclient_route_send(cmd, zclient, &api);
+
+       if (IS_RIPNG_DEBUG_ZEBRA) {
+               if (ripng->ecmp)
+                       zlog_debug("%s: %s/%d nexthops %d",
+                                  (cmd == ZEBRA_ROUTE_ADD)
+                                          ? "Install into zebra"
+                                          : "Delete from zebra",
+                                  inet6_ntoa(rp->p.u.prefix6), rp->p.prefixlen,
+                                  count);
+               else
+                       zlog_debug(
+                               "%s: %s/%d",
+                               (cmd == ZEBRA_ROUTE_ADD) ? "Install into zebra"
+                                                        : "Delete from zebra",
+                               inet6_ntoa(rp->p.u.prefix6), rp->p.prefixlen);
        }
 }
 
 /* Add/update ECMP routes to zebra. */
 void ripng_zebra_ipv6_add(struct route_node *rp)
 {
-       ripng_zebra_ipv6_send(rp, ZEBRA_IPV6_ROUTE_ADD);
+       ripng_zebra_ipv6_send(rp, ZEBRA_ROUTE_ADD);
 }
 
 /* Delete ECMP routes from zebra. */
 void ripng_zebra_ipv6_delete(struct route_node *rp)
 {
-       ripng_zebra_ipv6_send(rp, ZEBRA_IPV6_ROUTE_DELETE);
+       ripng_zebra_ipv6_send(rp, ZEBRA_ROUTE_DELETE);
 }
 
 /* Zebra route add and delete treatment. */
-static int ripng_zebra_read_ipv6(int command, struct zclient *zclient,
-                                zebra_size_t length, vrf_id_t vrf_id)
+static int ripng_zebra_read_route(int command, struct zclient *zclient,
+                                 zebra_size_t length, vrf_id_t vrf_id)
 {
-       struct stream *s;
-       struct zapi_ipv6 api;
-       unsigned long ifindex;
+       struct zapi_route api;
        struct in6_addr nexthop;
-       struct prefix_ipv6 p, src_p;
-
-       s = zclient->ibuf;
-       ifindex = 0;
-       memset(&nexthop, 0, sizeof(struct in6_addr));
-
-       /* Type, flags, message. */
-       api.type = stream_getc(s);
-       api.instance = stream_getw(s);
-       api.flags = stream_getl(s);
-       api.message = stream_getc(s);
-
-       /* IPv6 prefix. */
-       memset(&p, 0, sizeof(struct prefix_ipv6));
-       p.family = AF_INET6;
-       p.prefixlen = MIN(IPV6_MAX_PREFIXLEN, stream_getc(s));
-       stream_get(&p.prefix, s, PSIZE(p.prefixlen));
-
-       memset(&src_p, 0, sizeof(struct prefix_ipv6));
-       src_p.family = AF_INET6;
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) {
-               src_p.prefixlen = stream_getc(s);
-               stream_get(&src_p.prefix, s, PSIZE(src_p.prefixlen));
-       }
+       unsigned long ifindex;
 
-       if (src_p.prefixlen)
-               /* we completely ignore srcdest routes for now. */
-               return 0;
+       if (zapi_route_decode(zclient->ibuf, &api) < 0)
+               return -1;
 
-       /* Nexthop, ifindex, distance, metric. */
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) {
-               api.nexthop_num = stream_getc(s);
-               stream_get(&nexthop, s, 16);
-       }
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) {
-               api.ifindex_num = stream_getc(s);
-               ifindex = stream_getl(s);
-       }
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE))
-               api.distance = stream_getc(s);
-       else
-               api.distance = 0;
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC))
-               api.metric = stream_getl(s);
-       else
-               api.metric = 0;
+       /* we completely ignore srcdest routes for now. */
+       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
+               return 0;
 
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG))
-               api.tag = stream_getl(s);
-       else
-               api.tag = 0;
+       nexthop = api.nexthops[0].gate.ipv6;
+       ifindex = api.nexthops[0].ifindex;
 
-       if (command == ZEBRA_REDISTRIBUTE_IPV6_ADD)
-               ripng_redistribute_add(api.type, RIPNG_ROUTE_REDISTRIBUTE, &p,
+       if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
+               ripng_redistribute_add(api.type, RIPNG_ROUTE_REDISTRIBUTE,
+                                      (struct prefix_ipv6 *)&api.prefix,
                                       ifindex, &nexthop, api.tag);
        else
                ripng_redistribute_delete(api.type, RIPNG_ROUTE_REDISTRIBUTE,
-                                         &p, ifindex);
+                                         (struct prefix_ipv6 *)&api.prefix,
+                                         ifindex);
 
        return 0;
 }
@@ -294,29 +233,6 @@ void ripng_redistribute_clean()
        }
 }
 
-DEFUN (ripng_redistribute_ripng,
-       ripng_redistribute_ripng_cmd,
-       "redistribute ripng",
-       "Redistribute information from another routing protocol\n"
-       "RIPng route\n")
-{
-       vrf_bitmap_set(zclient->redist[AFI_IP6][ZEBRA_ROUTE_RIPNG],
-                      VRF_DEFAULT);
-       return CMD_SUCCESS;
-}
-
-DEFUN (no_ripng_redistribute_ripng,
-       no_ripng_redistribute_ripng_cmd,
-       "no redistribute ripng",
-       NO_STR
-       "Redistribute information from another routing protocol\n"
-       "RIPng route\n")
-{
-       vrf_bitmap_unset(zclient->redist[AFI_IP6][ZEBRA_ROUTE_RIPNG],
-                        VRF_DEFAULT);
-       return CMD_SUCCESS;
-}
-
 DEFUN (ripng_redistribute_type,
        ripng_redistribute_type_cmd,
        "redistribute " FRR_REDIST_STR_RIPNGD,
@@ -452,64 +368,40 @@ void ripng_redistribute_write(struct vty *vty, int config_mode)
 {
        int i;
 
-       for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
-               if (i != zclient->redist_default
-                   && vrf_bitmap_check(zclient->redist[AFI_IP6][i],
-                                       VRF_DEFAULT)) {
-                       if (config_mode) {
-                               if (ripng->route_map[i].metric_config) {
-                                       if (ripng->route_map[i].name)
-                                               vty_out(vty,
-                                                       " redistribute %s metric %d route-map %s\n",
-                                                       zebra_route_string(i),
-                                                       ripng->route_map[i]
-                                                               .metric,
-                                                       ripng->route_map[i]
-                                                               .name);
-                                       else
-                                               vty_out(vty,
-                                                       " redistribute %s metric %d\n",
-                                                       zebra_route_string(i),
-                                                       ripng->route_map[i]
-                                                               .metric);
-                               } else {
-                                       if (ripng->route_map[i].name)
-                                               vty_out(vty,
-                                                       " redistribute %s route-map %s\n",
-                                                       zebra_route_string(i),
-                                                       ripng->route_map[i]
-                                                               .name);
-                                       else
-                                               vty_out(vty,
-                                                       " redistribute %s\n",
-                                                       zebra_route_string(i));
-                               }
-                       } else
-                               vty_out(vty, "    %s", zebra_route_string(i));
+       for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
+               if (i == zclient->redist_default
+                   || !vrf_bitmap_check(zclient->redist[AFI_IP6][i],
+                                        VRF_DEFAULT))
+                       continue;
+
+               if (!config_mode) {
+                       vty_out(vty, "    %s", zebra_route_string(i));
+                       continue;
                }
-}
 
-/* RIPng configuration write function. */
-static int zebra_config_write(struct vty *vty)
-{
-       if (!zclient->enable) {
-               vty_out(vty, "no router zebra\n");
-               return 1;
-       } else if (!vrf_bitmap_check(
-                          zclient->redist[AFI_IP6][ZEBRA_ROUTE_RIPNG],
-                          VRF_DEFAULT)) {
-               vty_out(vty, "router zebra\n");
-               vty_out(vty, " no redistribute ripng\n");
-               return 1;
+               if (ripng->route_map[i].metric_config) {
+                       if (ripng->route_map[i].name)
+                               vty_out(vty,
+                                       " redistribute %s metric %d route-map %s\n",
+                                       zebra_route_string(i),
+                                       ripng->route_map[i].metric,
+                                       ripng->route_map[i].name);
+                       else
+                               vty_out(vty, " redistribute %s metric %d\n",
+                                       zebra_route_string(i),
+                                       ripng->route_map[i].metric);
+               } else {
+                       if (ripng->route_map[i].name)
+                               vty_out(vty, " redistribute %s route-map %s\n",
+                                       zebra_route_string(i),
+                                       ripng->route_map[i].name);
+                       else
+                               vty_out(vty, " redistribute %s\n",
+                                       zebra_route_string(i));
+               }
        }
-       return 0;
 }
 
-/* Zebra node structure. */
-static struct cmd_node zebra_node = {
-       ZEBRA_NODE, "%s(config-router)# ",
-};
-
 static void ripng_zebra_connected(struct zclient *zclient)
 {
        zclient_send_reg_requests(zclient, VRF_DEFAULT);
@@ -529,16 +421,8 @@ void zebra_init(struct thread_master *master)
        zclient->interface_delete = ripng_interface_delete;
        zclient->interface_address_add = ripng_interface_address_add;
        zclient->interface_address_delete = ripng_interface_address_delete;
-       zclient->redistribute_route_ipv6_add = ripng_zebra_read_ipv6;
-       zclient->redistribute_route_ipv6_del = ripng_zebra_read_ipv6;
-
-       /* Install zebra node. */
-       install_node(&zebra_node, zebra_config_write);
-
-       /* Install command element for zebra node. */
-       install_default(ZEBRA_NODE);
-       install_element(ZEBRA_NODE, &ripng_redistribute_ripng_cmd);
-       install_element(ZEBRA_NODE, &no_ripng_redistribute_ripng_cmd);
+       zclient->redistribute_route_add = ripng_zebra_read_route;
+       zclient->redistribute_route_del = ripng_zebra_read_route;
 
        /* Install command elements to ripng node */
        install_element(RIPNG_NODE, &ripng_redistribute_type_cmd);
index 604ffaa8b63f30ffdc54cb30e4b84176c7c1d515..41349cce24b7fd93d506b4b5ab2567cf99680b14 100644 (file)
@@ -45,4 +45,5 @@ __pycache__
 /lib/test_timer_correctness
 /lib/test_timer_performance
 /lib/test_ttable
+/lib/test_zmq
 /ospf6d/test_lsdb
index 59ea3c4c6998a0b0bcf2008dd124ee208ef45a18..8a8918dcb428304ee9197a8ed0f06a4b263f4026 100644 (file)
@@ -72,6 +72,12 @@ check_PROGRAMS = \
        $(TESTS_OSPF6D) \
        # end
 
+if ZEROMQ
+check_PROGRAMS += \
+       lib/test_zmq \
+       # end
+endif
+
 ../vtysh/vtysh_cmd.c:
        $(MAKE) -C ../vtysh vtysh_cmd.c
 
@@ -112,6 +118,8 @@ lib_test_timer_correctness_SOURCES = lib/test_timer_correctness.c \
 lib_test_timer_performance_SOURCES = lib/test_timer_performance.c \
                                      helpers/c/prng.c
 lib_test_ttable_SOURCES = lib/test_ttable.c
+lib_test_zmq_SOURCES = lib/test_zmq.c
+lib_test_zmq_CFLAGS = $(AM_CFLAGS) $(ZEROMQ_CFLAGS)
 lib_cli_test_cli_SOURCES = lib/cli/test_cli.c lib/cli/common_cli.c
 lib_cli_test_commands_SOURCES = lib/cli/test_commands_defun.c \
                                 lib/cli/test_commands.c \
@@ -147,6 +155,7 @@ lib_test_table_LDADD = $(ALL_TESTS_LDADD) -lm
 lib_test_timer_correctness_LDADD = $(ALL_TESTS_LDADD)
 lib_test_timer_performance_LDADD = $(ALL_TESTS_LDADD)
 lib_test_ttable_LDADD = $(ALL_TESTS_LDADD)
+lib_test_zmq_LDADD = ../lib/libfrrzmq.la $(ALL_TESTS_LDADD) $(ZEROMQ_LIBS)
 lib_cli_test_cli_LDADD = $(ALL_TESTS_LDADD)
 lib_cli_test_commands_LDADD = $(ALL_TESTS_LDADD)
 bgpd_test_aspath_LDADD = $(BGP_TEST_LDADD)
index 6727e663f544e466c6596d4fe02a7fd2e1f37aae..e61e9639ee94d2b7fb4029c0f1aa5bf0e0f5d731 100644 (file)
@@ -23,7 +23,7 @@ static bool atexit_registered;
 
 static void show_meminfo_at_exit(void)
 {
-       log_memstats_stderr("isis fuzztest");
+       log_memstats(stderr, "isis fuzztest");
 }
 
 static int comp_line(const void *p1, const void *p2)
index 77f1610fe23ba16b09ac362704b038482a087399..0fd2f80a39b5b12878588868a672e368270b0cb5 100644 (file)
@@ -53,7 +53,7 @@ static void vty_do_exit(int isexit)
        thread_master_free(master);
        closezlog();
 
-       log_memstats_stderr("testcli");
+       log_memstats(stderr, "testcli");
        if (!isexit)
                exit(0);
 }
index bda0bbac44ebdf0cdf1ea8c9cfc68988818b62bc..d55345186a2f18f1b5a7299a2c916d3096a004ae 100644 (file)
@@ -8,4 +8,4 @@ class TestCommands(frrtest.TestRefOut):
     @pytest.mark.skipif('QUAGGA_TEST_COMMANDS' not in os.environ,
                         reason='QUAGGA_TEST_COMMANDS not set')
     def test_refout(self):
-        return super(TestCommands, self).test_refout(self)
+        return super(TestCommands, self).test_refout()
diff --git a/tests/lib/test_zmq.c b/tests/lib/test_zmq.c
new file mode 100644 (file)
index 0000000..c270ec3
--- /dev/null
@@ -0,0 +1,212 @@
+/*
+ * ZeroMQ event test
+ * Copyright (C) 2017  David Lamparter, for NetDEF, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <zebra.h>
+#include "memory.h"
+#include "sigevent.h"
+#include "frr_zmq.h"
+
+DEFINE_MTYPE_STATIC(LIB, TESTBUF, "zmq test buffer")
+
+static struct thread_master *master;
+
+static void msg_buf_free(void *data, void *hint)
+{
+       XFREE(MTYPE_TESTBUF, data);
+}
+
+static void run_client(int syncfd)
+{
+       int i, j;
+       char buf[32];
+       char dummy;
+       void *zmqctx = NULL;
+       void *zmqsock;
+
+       read(syncfd, &dummy, 1);
+
+       zmqctx = zmq_ctx_new();
+       zmq_ctx_set(zmqctx, ZMQ_IPV6, 1);
+
+       zmqsock = zmq_socket(zmqctx, ZMQ_REQ);
+       if (zmq_connect(zmqsock, "tcp://127.0.0.1:17171")) {
+               perror("zmq_connect");
+               exit(1);
+       }
+
+       /* single-part */
+       for (i = 0; i < 8; i++) {
+               snprintf(buf, sizeof(buf), "msg #%d %c%c%c",
+                        i, 'a' + i, 'b' + i, 'c' + i);
+               printf("client send: %s\n", buf);
+               fflush(stdout);
+               zmq_send(zmqsock, buf, strlen(buf) + 1, 0);
+               zmq_recv(zmqsock, buf, sizeof(buf), 0);
+               printf("client recv: %s\n", buf);
+       }
+
+       /* multipart */
+       for (i = 2; i < 5; i++) {
+               int more;
+
+               printf("---\n");
+               for (j = 1; j <= i; j++) {
+                       zmq_msg_t part;
+                       char *dyn = XMALLOC(MTYPE_TESTBUF, 32);
+
+                       snprintf(dyn, 32, "part %d/%d", j, i);
+                       printf("client send: %s\n", dyn);
+                       fflush(stdout);
+
+                       zmq_msg_init_data(&part, dyn, strlen(dyn) + 1,
+                                         msg_buf_free, NULL);
+                       zmq_msg_send(&part, zmqsock, j < i ? ZMQ_SNDMORE : 0);
+               }
+
+               zmq_msg_t part;
+               do {
+                       char *data;
+
+                       zmq_msg_recv(&part, zmqsock, 0);
+                       data = zmq_msg_data(&part);
+                       more = zmq_msg_more(&part);
+                       printf("client recv (more: %d): %s\n", more, data);
+               } while (more);
+               zmq_msg_close(&part);
+       }
+       zmq_close(zmqsock);
+       zmq_ctx_term(zmqctx);
+}
+
+static struct frrzmq_cb *cb;
+
+static void serverpartfn(void *arg, void *zmqsock, zmq_msg_t *msg,
+                       unsigned partnum)
+{
+       int more = zmq_msg_more(msg);
+       char *in = zmq_msg_data(msg);
+       size_t i;
+       zmq_msg_t reply;
+       char *out;
+
+       printf("server recv part %u (more: %d): %s\n", partnum, more, in);
+       fflush(stdout);
+       /* REQ-REP doesn't allow sending a reply here */
+       if (more)
+               return;
+
+       out = XMALLOC(MTYPE_TESTBUF, strlen(in) + 1);
+       for (i = 0; i < strlen(in); i++)
+               out[i] = toupper(in[i]);
+       out[i] = '\0';
+       zmq_msg_init_data(&reply, out, strlen(out) + 1, msg_buf_free, NULL);
+       zmq_msg_send(&reply, zmqsock, ZMQ_SNDMORE);
+
+       out = XMALLOC(MTYPE_TESTBUF, 32);
+       snprintf(out, 32, "msg# was %u", partnum);
+       zmq_msg_init_data(&reply, out, strlen(out) + 1, msg_buf_free, NULL);
+       zmq_msg_send(&reply, zmqsock, 0);
+}
+
+static void serverfn(void *arg, void *zmqsock)
+{
+       static int num = 0;
+
+       char buf[32];
+       size_t i;
+       zmq_recv(zmqsock, buf, sizeof(buf), 0);
+
+       printf("server recv: %s\n", buf);
+       fflush(stdout);
+       for (i = 0; i < strlen(buf); i++)
+               buf[i] = toupper(buf[i]);
+       zmq_send(zmqsock, buf, strlen(buf) + 1, 0);
+
+       if (++num < 4)
+               return;
+
+       /* change to multipart callback */
+       frrzmq_thread_cancel(cb);
+
+       cb = frrzmq_thread_add_read_part(master, serverpartfn, NULL, zmqsock);
+}
+
+static void sigchld(void)
+{
+       printf("child exited.\n");
+       frrzmq_thread_cancel(cb);
+}
+
+static struct quagga_signal_t sigs[] = {
+       {
+               .signal = SIGCHLD,
+               .handler = sigchld,
+       },
+};
+
+static void run_server(int syncfd)
+{
+       void *zmqsock;
+       char dummy = 0;
+       struct thread t;
+
+       master = thread_master_create(NULL);
+       signal_init(master, array_size(sigs), sigs);
+       frrzmq_init();
+
+       zmqsock = zmq_socket(frrzmq_context, ZMQ_REP);
+       if (zmq_bind(zmqsock, "tcp://*:17171")) {
+               perror("zmq_bind");
+               exit(1);
+       }
+
+       cb = frrzmq_thread_add_read_msg(master, serverfn, NULL, zmqsock);
+
+       write(syncfd, &dummy, sizeof(dummy));
+       while (thread_fetch(master, &t))
+               thread_call(&t);
+
+       zmq_close(zmqsock);
+       frrzmq_finish();
+       thread_master_free(master);
+       log_memstats_stderr("test");
+}
+
+int main(void)
+{
+       int syncpipe[2];
+       pid_t child;
+
+       if (pipe(syncpipe)) {
+               perror("pipe");
+               exit(1);
+       }
+
+       child = fork();
+       if (child < 0) {
+               perror("fork");
+               exit(1);
+       } else if (child == 0) {
+               run_client(syncpipe[0]);
+               exit(0);
+       }
+
+       run_server(syncpipe[1]);
+       exit(0);
+}
diff --git a/tests/lib/test_zmq.py b/tests/lib/test_zmq.py
new file mode 100644 (file)
index 0000000..1f8ee54
--- /dev/null
@@ -0,0 +1,11 @@
+import frrtest
+import pytest
+import os
+
+class TestZMQ(frrtest.TestRefOut):
+    program = './test_zmq'
+
+    @pytest.mark.skipif('S["ZEROMQ_TRUE"]=""\n' not in open('../config.status').readlines(),
+                        reason='ZEROMQ not enabled')
+    def test_refout(self):
+        return super(TestZMQ, self).test_refout()
diff --git a/tests/lib/test_zmq.refout b/tests/lib/test_zmq.refout
new file mode 100644 (file)
index 0000000..61f45f0
--- /dev/null
@@ -0,0 +1,50 @@
+client send: msg #0 abc
+server recv: msg #0 abc
+client recv: MSG #0 ABC
+client send: msg #1 bcd
+server recv: msg #1 bcd
+client recv: MSG #1 BCD
+client send: msg #2 cde
+server recv: msg #2 cde
+client recv: MSG #2 CDE
+client send: msg #3 def
+server recv: msg #3 def
+client recv: MSG #3 DEF
+client send: msg #4 efg
+server recv part 0 (more: 0): msg #4 efg
+client recv: MSG #4 EFG
+client send: msg #5 fgh
+client recv: msg# was 0
+client send: msg #6 ghi
+server recv part 0 (more: 0): msg #6 ghi
+client recv: MSG #6 GHI
+client send: msg #7 hij
+client recv: msg# was 0
+---
+client send: part 1/2
+client send: part 2/2
+server recv part 0 (more: 1): part 1/2
+server recv part 1 (more: 0): part 2/2
+client recv (more: 1): PART 2/2
+client recv (more: 0): msg# was 1
+---
+client send: part 1/3
+client send: part 2/3
+client send: part 3/3
+server recv part 0 (more: 1): part 1/3
+server recv part 1 (more: 1): part 2/3
+server recv part 2 (more: 0): part 3/3
+client recv (more: 1): PART 3/3
+client recv (more: 0): msg# was 2
+---
+client send: part 1/4
+client send: part 2/4
+client send: part 3/4
+client send: part 4/4
+server recv part 0 (more: 1): part 1/4
+server recv part 1 (more: 1): part 2/4
+server recv part 2 (more: 1): part 3/4
+server recv part 3 (more: 0): part 4/4
+client recv (more: 1): PART 4/4
+client recv (more: 0): msg# was 3
+child exited.
index 0bea3ee81d089a5d8b28f8b2dd5eb94327a127c5..4eb4a5c28c7c05fde305f14dcf8e7e3a1d3694ac 100755 (executable)
--- a/tools/frr
+++ b/tools/frr
@@ -72,6 +72,11 @@ vtysh_b ()
 # returns:      0=ok, 1=error
 check_daemon()
 {
+        if [ $1 != "watchfrr" -a $1 != "vtysh_enable" ]; then
+          # check for daemon binary
+          if [ ! -x "$D_PATH/$1" ]; then return 1; fi
+        fi
+
         # If the integrated config file is used the others are not checked.
         if [ -r "$C_PATH/frr.conf" ]; then
           return 0
@@ -80,9 +85,6 @@ check_daemon()
         # vtysh_enable has no config file nor binary so skip check.
         # (Not sure why vtysh_enable is in this list but does not hurt)
         if [ $1 != "watchfrr" -a $1 != "vtysh_enable" ]; then
-          # check for daemon binary
-          if [ ! -x "$D_PATH/$1" ]; then return 1; fi
-
           # check for config file
           if [ -n "$2" ]; then
            if [ ! -r "$C_PATH/$1-$2.conf" ]; then
index 43496d4cbfebc64610d0beddb1c8b74dba370809..8556f0b46e4858273dae854945ea8c62982750a5 100755 (executable)
@@ -1162,19 +1162,11 @@ if __name__ == '__main__':
                         for line in lines_to_configure:
                             fh.write(line + '\n')
 
-                    output = subprocess.check_output(['/usr/bin/vtysh', '-f', filename])
-
-                    # exit non-zero if we see these errors
-                    for x in ('BGP instance name and AS number mismatch',
-                              'BGP instance is already running',
-                              '% not a local address'):
-                        for line in output.splitlines():
-                            if x in line:
-                                msg = "ERROR: %s" % x
-                                log.error(msg)
-                                print msg
-                                reload_ok = False
-
+                    try:
+                        subprocess.check_output(['/usr/bin/vtysh', '-f', filename])
+                    except subprocess.CalledProcessError as e:
+                        log.warning("frr-reload.py failed due to\n%s" % e.output)
+                        reload_ok = False
                     os.unlink(filename)
 
         # Make these changes persistent
index 9939a7fae9eda3c6d2f109c5aa98e67bc938cb1b..34d66735dfb62f81c47d46ee8873c452d5f64fca 100644 (file)
@@ -752,6 +752,7 @@ int vtysh_config_from_file(struct vty *vty, FILE *fp)
                                                        lineno, cmd_stat,
                                                        vtysh_client[i].name,
                                                        vty->buf);
+                                               retcode = cmd_stat;
                                                break;
                                        }
                                }
@@ -1914,6 +1915,28 @@ static int show_per_daemon(const char *line, const char *headline)
        return ret;
 }
 
+DEFUN (vtysh_show_debugging,
+       vtysh_show_debugging_cmd,
+       "show debugging",
+       SHOW_STR
+       DEBUG_STR)
+{
+       return show_per_daemon("do show debugging\n",
+                              "Debugging Information for %s:\n");
+}
+
+DEFUN (vtysh_show_debugging_hashtable,
+       vtysh_show_debugging_hashtable_cmd,
+       "show debugging hashtable [statistics]",
+       SHOW_STR
+       DEBUG_STR
+       "Statistics about hash tables\n"
+       "Statistics about hash tables\n")
+{
+       return show_per_daemon("do show debugging hashtable\n",
+                              "Hashtable statistics for %s:\n");
+}
+
 /* Memory */
 DEFUN (vtysh_show_memory,
        vtysh_show_memory_cmd,
@@ -1921,7 +1944,8 @@ DEFUN (vtysh_show_memory,
        SHOW_STR
        "Memory statistics\n")
 {
-       return show_per_daemon("show memory\n", "Memory statistics for %s:\n");
+       return show_per_daemon("show memory\n",
+                              "Memory statistics for %s:\n");
 }
 
 DEFUN (vtysh_show_modules,
@@ -1941,20 +1965,8 @@ DEFUN (vtysh_show_logging,
        SHOW_STR
        "Show current logging configuration\n")
 {
-       unsigned int i;
-       int ret = CMD_SUCCESS;
-       char line[] = "do show logging\n";
-
-       for (i = 0; i < array_size(vtysh_client); i++)
-               if (vtysh_client[i].fd >= 0) {
-                       fprintf(stdout, "Logging configuration for %s:\n",
-                               vtysh_client[i].name);
-                       ret = vtysh_client_execute(&vtysh_client[i], line,
-                                                  stdout);
-                       fprintf(stdout, "\n");
-               }
-
-       return ret;
+       return show_per_daemon("do show logging\n",
+                              "Logging configuration for %s:\n");
 }
 
 DEFUNSH(VTYSH_ALL, vtysh_log_stdout, vtysh_log_stdout_cmd, "log stdout",
@@ -3220,6 +3232,8 @@ void vtysh_init_vty(void)
        install_element(ENABLE_NODE, &vtysh_start_zsh_cmd);
 #endif
 
+       install_element(VIEW_NODE, &vtysh_show_debugging_cmd);
+       install_element(VIEW_NODE, &vtysh_show_debugging_hashtable_cmd);
        install_element(VIEW_NODE, &vtysh_show_memory_cmd);
        install_element(VIEW_NODE, &vtysh_show_modules_cmd);
 
index 1ce065fccf77221cadc07793afbfde32faeaa7b8..d7e79d6b2cc1660758a8d279d1c55f3f014d7b1c 100644 (file)
@@ -245,7 +245,10 @@ void vtysh_config_parse_line(void *arg, const char *line)
                                 == 0
                         || strncmp(line, "ip extcommunity-list",
                                    strlen("ip extcommunity-list"))
-                                   == 0)
+                                == 0
+                        || strncmp(line, "ip large-community-list",
+                                   strlen("ip large-community-list"))
+                                == 0)
                        config = config_get(COMMUNITY_LIST_NODE, line);
                else if (strncmp(line, "ip route", strlen("ip route")) == 0)
                        config = config_get(IP_NODE, line);
index 25f47bc51a8fa85e9068c0ce18a036f79699f496..afeba1c6dea19f090e136b0096e156a5123e07ee 100644 (file)
@@ -34,12 +34,12 @@ unsigned long zebra_debug_mpls;
 unsigned long zebra_debug_vxlan;
 unsigned long zebra_debug_pw;
 
-DEFUN (show_debugging_zebra,
-       show_debugging_zebra_cmd,
-       "show debugging zebra",
-       SHOW_STR
-       "Debugging information\n"
-       "Zebra configuration\n")
+DEFUN_NOSH (show_debugging_zebra,
+           show_debugging_zebra_cmd,
+           "show debugging [zebra]",
+           SHOW_STR
+           "Debugging information\n"
+           "Zebra configuration\n")
 {
        vty_out(vty, "Zebra debugging status:\n");
 
index 8456984330aab075e3b2a12c16cb30f1a64944bd..a03b7f9615e6444412422900c98a4ea5df265a99 100644 (file)
 
 #define ZEBRA_PTM_SUPPORT
 
-#if defined(HAVE_RTADV)
-/* Order is intentional.  Matches RFC4191.  This array is also used for
-   command matching, so only modify with care. */
-const char *rtadv_pref_strs[] = {"medium", "high", "INVALID", "low", 0};
-#endif /* HAVE_RTADV */
+DEFINE_HOOK(zebra_if_extra_info, (struct vty *vty, struct interface *ifp),
+                                (vty, ifp))
+DEFINE_HOOK(zebra_if_config_wr, (struct vty *vty, struct interface *ifp),
+                               (vty, ifp))
 
 static void if_down_del_nbr_connected(struct interface *ifp);
 
@@ -998,74 +997,6 @@ static void nbr_connected_dump_vty(struct vty *vty,
        vty_out(vty, "\n");
 }
 
-#if defined(HAVE_RTADV)
-/* Dump interface ND information to vty. */
-static void nd_dump_vty(struct vty *vty, struct interface *ifp)
-{
-       struct zebra_if *zif;
-       struct rtadvconf *rtadv;
-       int interval;
-
-       zif = (struct zebra_if *)ifp->info;
-       rtadv = &zif->rtadv;
-
-       if (rtadv->AdvSendAdvertisements) {
-               vty_out(vty,
-                       "  ND advertised reachable time is %d milliseconds\n",
-                       rtadv->AdvReachableTime);
-               vty_out(vty,
-                       "  ND advertised retransmit interval is %d milliseconds\n",
-                       rtadv->AdvRetransTimer);
-               vty_out(vty, "  ND router advertisements sent: %d rcvd: %d\n",
-                       zif->ra_sent, zif->ra_rcvd);
-               interval = rtadv->MaxRtrAdvInterval;
-               if (interval % 1000)
-                       vty_out(vty,
-                               "  ND router advertisements are sent every "
-                               "%d milliseconds\n",
-                               interval);
-               else
-                       vty_out(vty,
-                               "  ND router advertisements are sent every "
-                               "%d seconds\n",
-                               interval / 1000);
-               if (rtadv->AdvDefaultLifetime != -1)
-                       vty_out(vty,
-                               "  ND router advertisements live for %d seconds\n",
-                               rtadv->AdvDefaultLifetime);
-               else
-                       vty_out(vty,
-                               "  ND router advertisements lifetime tracks ra-interval\n");
-               vty_out(vty,
-                       "  ND router advertisement default router preference is "
-                       "%s\n",
-                       rtadv_pref_strs[rtadv->DefaultPreference]);
-               if (rtadv->AdvManagedFlag)
-                       vty_out(vty,
-                               "  Hosts use DHCP to obtain routable addresses.\n");
-               else
-                       vty_out(vty,
-                               "  Hosts use stateless autoconfig for addresses.\n");
-               if (rtadv->AdvHomeAgentFlag) {
-                       vty_out(vty,
-                               "  ND router advertisements with Home Agent flag bit set.\n");
-                       if (rtadv->HomeAgentLifetime != -1)
-                               vty_out(vty,
-                                       "  Home Agent lifetime is %u seconds\n",
-                                       rtadv->HomeAgentLifetime);
-                       else
-                               vty_out(vty,
-                                       "  Home Agent lifetime tracks ra-lifetime\n");
-                       vty_out(vty, "  Home Agent preference is %u\n",
-                               rtadv->HomeAgentPreference);
-               }
-               if (rtadv->AdvIntervalOption)
-                       vty_out(vty,
-                               "  ND router advertisements with Adv. Interval option.\n");
-       }
-}
-#endif /* HAVE_RTADV */
-
 static const char *zebra_ziftype_2str(zebra_iftype_t zif_type)
 {
        switch (zif_type) {
@@ -1279,12 +1210,8 @@ static void if_dump_vty(struct vty *vty, struct interface *ifp)
                                inet_ntoa(iflp->rmt_ip), iflp->rmt_as);
        }
 
-#ifdef RTADV
-       nd_dump_vty(vty, ifp);
-#endif /* RTADV */
-#if defined(HAVE_RTADV)
-       nd_dump_vty(vty, ifp);
-#endif /* HAVE_RTADV */
+       hook_call(zebra_if_extra_info, vty, ifp);
+
        if (listhead(ifp->nbr_connected))
                vty_out(vty, "  Neighbor address(s):\n");
        for (ALL_LIST_ELEMENTS_RO(ifp->nbr_connected, node, nbr_connected))
@@ -2913,13 +2840,7 @@ static int if_config_write(struct vty *vty)
                                                : "no ");
                }
 
-#if defined(HAVE_RTADV)
-               rtadv_config_write(vty, ifp);
-#endif /* HAVE_RTADV */
-
-#ifdef HAVE_IRDP
-               irdp_config_write(vty, ifp);
-#endif /* IRDP */
+               hook_call(zebra_if_config_wr, vty, ifp);
 
                link_params_config_write(vty, ifp);
 
@@ -2932,8 +2853,8 @@ static int if_config_write(struct vty *vty)
 void zebra_if_init(void)
 {
        /* Initialize interface and new hook. */
-       if_add_hook(IF_NEW_HOOK, if_zebra_new_hook);
-       if_add_hook(IF_DELETE_HOOK, if_zebra_delete_hook);
+       hook_register_prio(if_add, 0, if_zebra_new_hook);
+       hook_register_prio(if_del, 0, if_zebra_delete_hook);
 
        /* Install configuration write function. */
        install_node(&interface_node, if_config_write);
index 970c3c52927b78fe5d67883cb245ba679628273c..7b56dcd4a40c7263f1b1ba1052963153df1fc4d3 100644 (file)
 
 #include "redistribute.h"
 #include "vrf.h"
-
-#ifdef HAVE_IRDP
-#include "zebra/irdp.h"
-#endif
+#include "hook.h"
 
 #include "zebra/zebra_l2.h"
 
@@ -202,6 +199,8 @@ typedef enum {
        ZEBRA_IF_SLAVE_OTHER,  /* Something else - e.g., bond slave */
 } zebra_slave_iftype_t;
 
+struct irdp_interface;
+
 /* `zebra' daemon local interface structure. */
 struct zebra_if {
        /* Shutdown configuration. */
@@ -227,9 +226,7 @@ struct zebra_if {
        unsigned int ra_sent, ra_rcvd;
 #endif /* HAVE_RTADV */
 
-#ifdef HAVE_IRDP
-       struct irdp_interface irdp;
-#endif
+       struct irdp_interface *irdp;
 
 #ifdef HAVE_STRUCT_SOCKADDR_DL
        union {
@@ -273,6 +270,11 @@ struct zebra_if {
        struct interface *link;
 };
 
+DECLARE_HOOK(zebra_if_extra_info, (struct vty *vty, struct interface *ifp),
+                                 (vty, ifp))
+DECLARE_HOOK(zebra_if_config_wr, (struct vty *vty, struct interface *ifp),
+                                (vty, ifp))
+
 static inline void zebra_if_set_ziftype(struct interface *ifp,
                                        zebra_iftype_t zif_type,
                                        zebra_slave_iftype_t zif_slave_type)
index 01308b915b3f4a316e142a771d465fb42b3fd6c5..ea190b574df0896af22df60ae7f05f7b2e74fcfc 100644 (file)
@@ -138,10 +138,9 @@ struct Adv {
        int pref;
 };
 
-extern void irdp_init(void);
+extern void irdp_if_init(void);
 extern int irdp_sock_init(void);
-extern void irdp_finish(void);
-extern void irdp_config_write(struct vty *, struct interface *);
+extern int irdp_config_write(struct vty *, struct interface *);
 extern int irdp_send_thread(struct thread *t_advert);
 extern void irdp_advert_off(struct interface *ifp);
 extern void process_solicit(struct interface *ifp);
index 5682e12e6f51385e07095b67e35b16fed835b4ef..34c78e2a482002ea7182f2a1fb25c6c0ebf454e9 100644 (file)
@@ -35,8 +35,6 @@
 
 #include <zebra.h>
 
-#ifdef HAVE_IRDP
-
 #include "if.h"
 #include "vty.h"
 #include "sockunion.h"
 
 extern int irdp_sock;
 
+DEFINE_MTYPE_STATIC(ZEBRA, IRDP_IF, "IRDP interface data")
+
+static struct irdp_interface *irdp_if_get(struct interface *ifp)
+{
+       struct zebra_if *zi = ifp->info;
+       if (!zi->irdp)
+               zi->irdp = XCALLOC(MTYPE_IRDP_IF, sizeof(*zi->irdp));
+       return zi->irdp;
+}
+
+static int irdp_if_delete(struct interface *ifp)
+{
+       struct zebra_if *zi = ifp->info;
+       if (!zi)
+               return 0;
+       XFREE(MTYPE_IRDP_IF, zi->irdp);
+       return 0;
+}
+
 static const char *inet_2a(u_int32_t a, char *b)
 {
        sprintf(b, "%u.%u.%u.%u", (a)&0xFF, (a >> 8) & 0xFF, (a >> 16) & 0xFF,
@@ -117,10 +134,13 @@ static int if_group(struct interface *ifp, int sock, u_int32_t group,
 static int if_add_group(struct interface *ifp)
 {
        struct zebra_if *zi = ifp->info;
-       struct irdp_interface *irdp = &zi->irdp;
+       struct irdp_interface *irdp = zi->irdp;
        int ret;
        char b1[INET_ADDRSTRLEN];
 
+       if (!irdp)
+               return -1;
+
        ret = if_group(ifp, irdp_sock, INADDR_ALLRTRS_GROUP, IP_ADD_MEMBERSHIP);
        if (ret < 0) {
                return ret;
@@ -135,10 +155,13 @@ static int if_add_group(struct interface *ifp)
 static int if_drop_group(struct interface *ifp)
 {
        struct zebra_if *zi = ifp->info;
-       struct irdp_interface *irdp = &zi->irdp;
+       struct irdp_interface *irdp = zi->irdp;
        int ret;
        char b1[INET_ADDRSTRLEN];
 
+       if (!irdp)
+               return -1;
+
        ret = if_group(ifp, irdp_sock, INADDR_ALLRTRS_GROUP,
                       IP_DROP_MEMBERSHIP);
        if (ret < 0)
@@ -150,11 +173,8 @@ static int if_drop_group(struct interface *ifp)
        return 0;
 }
 
-static void if_set_defaults(struct interface *ifp)
+static void if_set_defaults(struct irdp_interface *irdp)
 {
-       struct zebra_if *zi = ifp->info;
-       struct irdp_interface *irdp = &zi->irdp;
-
        irdp->MaxAdvertInterval = IRDP_MAXADVERTINTERVAL;
        irdp->MinAdvertInterval = IRDP_MINADVERTINTERVAL;
        irdp->Preference = IRDP_PREFERENCE;
@@ -176,11 +196,13 @@ static void irdp_if_start(struct interface *ifp, int multicast,
                          int set_defaults)
 {
        struct zebra_if *zi = ifp->info;
-       struct irdp_interface *irdp = &zi->irdp;
+       struct irdp_interface *irdp = zi->irdp;
        struct listnode *node;
        struct connected *ifc;
        u_int32_t timer, seed;
 
+       assert(irdp);
+
        if (irdp->flags & IF_ACTIVE) {
                zlog_warn("IRDP: Interface is already active %s", ifp->name);
                return;
@@ -215,7 +237,7 @@ static void irdp_if_start(struct interface *ifp, int multicast,
        }
 
        if (set_defaults)
-               if_set_defaults(ifp);
+               if_set_defaults(irdp);
 
        irdp->irdp_sent = 0;
 
@@ -254,7 +276,7 @@ static void irdp_if_start(struct interface *ifp, int multicast,
 static void irdp_if_stop(struct interface *ifp)
 {
        struct zebra_if *zi = ifp->info;
-       struct irdp_interface *irdp = &zi->irdp;
+       struct irdp_interface *irdp = zi->irdp;
 
        if (irdp == NULL) {
                zlog_warn("Interface %s structure is NULL", ifp->name);
@@ -281,8 +303,10 @@ static void irdp_if_stop(struct interface *ifp)
 static void irdp_if_shutdown(struct interface *ifp)
 {
        struct zebra_if *zi = ifp->info;
-       struct irdp_interface *irdp = &zi->irdp;
+       struct irdp_interface *irdp = zi->irdp;
 
+       if (!irdp)
+               return;
        if (irdp->flags & IF_SHUTDOWN) {
                zlog_warn("IRDP: Interface is already shutdown %s", ifp->name);
                return;
@@ -300,8 +324,7 @@ static void irdp_if_shutdown(struct interface *ifp)
 
 static void irdp_if_no_shutdown(struct interface *ifp)
 {
-       struct zebra_if *zi = ifp->info;
-       struct irdp_interface *irdp = &zi->irdp;
+       struct irdp_interface *irdp = irdp_if_get(ifp);
 
        if (!(irdp->flags & IF_SHUTDOWN)) {
                zlog_warn("IRDP: Interface is not shutdown %s", ifp->name);
@@ -316,14 +339,17 @@ static void irdp_if_no_shutdown(struct interface *ifp)
 
 /* Write configuration to user */
 
-void irdp_config_write(struct vty *vty, struct interface *ifp)
+int irdp_config_write(struct vty *vty, struct interface *ifp)
 {
        struct zebra_if *zi = ifp->info;
-       struct irdp_interface *irdp = &zi->irdp;
+       struct irdp_interface *irdp = zi->irdp;
        struct Adv *adv;
        struct listnode *node;
        char b1[INET_ADDRSTRLEN];
 
+       if (!irdp)
+               return 0;
+
        if (irdp->flags & IF_ACTIVE || irdp->flags & IF_SHUTDOWN) {
 
                if (irdp->flags & IF_SHUTDOWN)
@@ -348,6 +374,7 @@ void irdp_config_write(struct vty *vty, struct interface *ifp)
                vty_out(vty, " ip irdp maxadvertinterval %ld\n",
                        irdp->MaxAdvertInterval);
        }
+       return 0;
 }
 
 
@@ -359,6 +386,7 @@ DEFUN (ip_irdp_multicast,
        "Use multicast mode\n")
 {
        VTY_DECLVAR_CONTEXT(interface, ifp);
+       irdp_if_get(ifp);
 
        irdp_if_start(ifp, TRUE, TRUE);
        return CMD_SUCCESS;
@@ -372,6 +400,7 @@ DEFUN (ip_irdp_broadcast,
        "Use broadcast mode\n")
 {
        VTY_DECLVAR_CONTEXT(interface, ifp);
+       irdp_if_get(ifp);
 
        irdp_if_start(ifp, FALSE, TRUE);
        return CMD_SUCCESS;
@@ -427,11 +456,7 @@ DEFUN (ip_irdp_holdtime,
 {
        int idx_number = 3;
        VTY_DECLVAR_CONTEXT(interface, ifp);
-       struct zebra_if *zi;
-       struct irdp_interface *irdp;
-
-       zi = ifp->info;
-       irdp = &zi->irdp;
+       struct irdp_interface *irdp = irdp_if_get(ifp);
 
        irdp->Lifetime = atoi(argv[idx_number]->arg);
        return CMD_SUCCESS;
@@ -447,11 +472,7 @@ DEFUN (ip_irdp_minadvertinterval,
 {
        int idx_number = 3;
        VTY_DECLVAR_CONTEXT(interface, ifp);
-       struct zebra_if *zi;
-       struct irdp_interface *irdp;
-
-       zi = ifp->info;
-       irdp = &zi->irdp;
+       struct irdp_interface *irdp = irdp_if_get(ifp);
 
        if ((unsigned)atoi(argv[idx_number]->arg) <= irdp->MaxAdvertInterval) {
                irdp->MinAdvertInterval = atoi(argv[idx_number]->arg);
@@ -474,11 +495,7 @@ DEFUN (ip_irdp_maxadvertinterval,
 {
        int idx_number = 3;
        VTY_DECLVAR_CONTEXT(interface, ifp);
-       struct zebra_if *zi;
-       struct irdp_interface *irdp;
-
-       zi = ifp->info;
-       irdp = &zi->irdp;
+       struct irdp_interface *irdp = irdp_if_get(ifp);
 
        if (irdp->MinAdvertInterval <= (unsigned)atoi(argv[idx_number]->arg)) {
                irdp->MaxAdvertInterval = atoi(argv[idx_number]->arg);
@@ -506,11 +523,7 @@ DEFUN (ip_irdp_preference,
 {
        int idx_number = 3;
        VTY_DECLVAR_CONTEXT(interface, ifp);
-       struct zebra_if *zi;
-       struct irdp_interface *irdp;
-
-       zi = ifp->info;
-       irdp = &zi->irdp;
+       struct irdp_interface *irdp = irdp_if_get(ifp);
 
        irdp->Preference = atoi(argv[idx_number]->arg);
        return CMD_SUCCESS;
@@ -529,17 +542,13 @@ DEFUN (ip_irdp_address_preference,
        int idx_ipv4 = 3;
        int idx_number = 5;
        VTY_DECLVAR_CONTEXT(interface, ifp);
+       struct irdp_interface *irdp = irdp_if_get(ifp);
        struct listnode *node;
        struct in_addr ip;
        int pref;
        int ret;
-       struct zebra_if *zi;
-       struct irdp_interface *irdp;
        struct Adv *adv;
 
-       zi = ifp->info;
-       irdp = &zi->irdp;
-
        ret = inet_aton(argv[idx_ipv4]->arg, &ip);
        if (!ret)
                return CMD_WARNING_CONFIG_FAILED;
@@ -571,16 +580,12 @@ DEFUN (no_ip_irdp_address_preference,
 {
        int idx_ipv4 = 4;
        VTY_DECLVAR_CONTEXT(interface, ifp);
+       struct irdp_interface *irdp = irdp_if_get(ifp);
        struct listnode *node, *nnode;
        struct in_addr ip;
        int ret;
-       struct zebra_if *zi;
-       struct irdp_interface *irdp;
        struct Adv *adv;
 
-       zi = ifp->info;
-       irdp = &zi->irdp;
-
        ret = inet_aton(argv[idx_ipv4]->arg, &ip);
        if (!ret)
                return CMD_WARNING_CONFIG_FAILED;
@@ -604,11 +609,7 @@ DEFUN (ip_irdp_debug_messages,
        "Enable debugging for IRDP messages\n")
 {
        VTY_DECLVAR_CONTEXT(interface, ifp);
-       struct zebra_if *zi;
-       struct irdp_interface *irdp;
-
-       zi = ifp->info;
-       irdp = &zi->irdp;
+       struct irdp_interface *irdp = irdp_if_get(ifp);
 
        irdp->flags |= IF_DEBUG_MESSAGES;
 
@@ -624,11 +625,7 @@ DEFUN (ip_irdp_debug_misc,
        "Enable debugging for miscellaneous IRDP events\n")
 {
        VTY_DECLVAR_CONTEXT(interface, ifp);
-       struct zebra_if *zi;
-       struct irdp_interface *irdp;
-
-       zi = ifp->info;
-       irdp = &zi->irdp;
+       struct irdp_interface *irdp = irdp_if_get(ifp);
 
        irdp->flags |= IF_DEBUG_MISC;
 
@@ -644,11 +641,7 @@ DEFUN (ip_irdp_debug_packet,
        "Enable debugging for IRDP packets\n")
 {
        VTY_DECLVAR_CONTEXT(interface, ifp);
-       struct zebra_if *zi;
-       struct irdp_interface *irdp;
-
-       zi = ifp->info;
-       irdp = &zi->irdp;
+       struct irdp_interface *irdp = irdp_if_get(ifp);
 
        irdp->flags |= IF_DEBUG_PACKET;
 
@@ -665,11 +658,7 @@ DEFUN (ip_irdp_debug_disable,
        "Disable debugging for all IRDP events\n")
 {
        VTY_DECLVAR_CONTEXT(interface, ifp);
-       struct zebra_if *zi;
-       struct irdp_interface *irdp;
-
-       zi = ifp->info;
-       irdp = &zi->irdp;
+       struct irdp_interface *irdp = irdp_if_get(ifp);
 
        irdp->flags &= ~IF_DEBUG_PACKET;
        irdp->flags &= ~IF_DEBUG_MESSAGES;
@@ -678,8 +667,11 @@ DEFUN (ip_irdp_debug_disable,
        return CMD_SUCCESS;
 }
 
-void irdp_init()
+void irdp_if_init()
 {
+       hook_register(zebra_if_config_wr, irdp_config_write);
+       hook_register(if_del, irdp_if_delete);
+
        install_element(INTERFACE_NODE, &ip_irdp_broadcast_cmd);
        install_element(INTERFACE_NODE, &ip_irdp_multicast_cmd);
        install_element(INTERFACE_NODE, &no_ip_irdp_cmd);
@@ -697,5 +689,3 @@ void irdp_init()
        install_element(INTERFACE_NODE, &ip_irdp_debug_packet_cmd);
        install_element(INTERFACE_NODE, &ip_irdp_debug_disable_cmd);
 }
-
-#endif /* HAVE_IRDP */
index 6220c9d81b1fda53083e053540568987058329f3..9dfa854725318a97a9849683d0ba798945cae6fd 100644 (file)
@@ -35,8 +35,6 @@
 
 #include <zebra.h>
 
-#ifdef HAVE_IRDP
-
 #include "if.h"
 #include "vty.h"
 #include "sockunion.h"
@@ -52,6 +50,8 @@
 #include "zclient.h"
 #include "thread.h"
 #include "privs.h"
+#include "libfrr.h"
+#include "version.h"
 #include "zebra/interface.h"
 #include "zebra/rtadv.h"
 #include "zebra/rib.h"
@@ -143,7 +143,7 @@ static int make_advertisement_packet(struct interface *ifp, struct prefix *p,
                                     struct stream *s)
 {
        struct zebra_if *zi = ifp->info;
-       struct irdp_interface *irdp = &zi->irdp;
+       struct irdp_interface *irdp = zi->irdp;
        int size;
        int pref;
        u_int16_t checksum;
@@ -175,11 +175,13 @@ static int make_advertisement_packet(struct interface *ifp, struct prefix *p,
 static void irdp_send(struct interface *ifp, struct prefix *p, struct stream *s)
 {
        struct zebra_if *zi = ifp->info;
-       struct irdp_interface *irdp = &zi->irdp;
+       struct irdp_interface *irdp = zi->irdp;
        char buf[PREFIX_STRLEN];
        u_int32_t dst;
        u_int32_t ttl = 1;
 
+       if (!irdp)
+               return;
        if (!(ifp->flags & IFF_UP))
                return;
 
@@ -211,11 +213,14 @@ int irdp_send_thread(struct thread *t_advert)
        u_int32_t timer, tmp;
        struct interface *ifp = THREAD_ARG(t_advert);
        struct zebra_if *zi = ifp->info;
-       struct irdp_interface *irdp = &zi->irdp;
+       struct irdp_interface *irdp = zi->irdp;
        struct prefix *p;
        struct listnode *node, *nnode;
        struct connected *ifc;
 
+       if (!irdp)
+               return 0;
+
        irdp->flags &= ~IF_SOLICIT;
 
        if (ifp->connected)
@@ -250,12 +255,15 @@ int irdp_send_thread(struct thread *t_advert)
 void irdp_advert_off(struct interface *ifp)
 {
        struct zebra_if *zi = ifp->info;
-       struct irdp_interface *irdp = &zi->irdp;
+       struct irdp_interface *irdp = zi->irdp;
        struct listnode *node, *nnode;
        int i;
        struct connected *ifc;
        struct prefix *p;
 
+       if (!irdp)
+               return;
+
        if (irdp->t_advertise)
                thread_cancel(irdp->t_advertise);
        irdp->t_advertise = NULL;
@@ -279,9 +287,12 @@ void irdp_advert_off(struct interface *ifp)
 void process_solicit(struct interface *ifp)
 {
        struct zebra_if *zi = ifp->info;
-       struct irdp_interface *irdp = &zi->irdp;
+       struct irdp_interface *irdp = zi->irdp;
        u_int32_t timer;
 
+       if (!irdp)
+               return;
+
        /* When SOLICIT is active we reject further incoming solicits
           this keeps down the answering rate so we don't have think
           about DoS attacks here. */
@@ -301,7 +312,7 @@ void process_solicit(struct interface *ifp)
                         &irdp->t_advertise);
 }
 
-void irdp_finish()
+static int irdp_finish(void)
 {
        struct vrf *vrf;
        struct listnode *node, *nnode;
@@ -317,7 +328,7 @@ void irdp_finish()
 
                if (!zi)
                        continue;
-               irdp = &zi->irdp;
+               irdp = zi->irdp;
                if (!irdp)
                        continue;
 
@@ -326,6 +337,26 @@ void irdp_finish()
                        irdp_advert_off(ifp);
                }
        }
+       return 0;
+}
+
+static int irdp_init(struct thread_master *master)
+{
+       irdp_if_init();
+
+       hook_register(frr_early_fini, irdp_finish);
+       return 0;
+}
+
+static int irdp_module_init(void)
+{
+       hook_register(frr_late_init, irdp_init);
+       return 0;
 }
 
-#endif /* HAVE_IRDP */
+FRR_MODULE_SETUP(
+       .name = "zebra_irdp",
+       .version = FRR_VERSION,
+       .description = "zebra IRDP module",
+       .init = irdp_module_init,
+)
index 3bd093d97bfb9ea85d11e2f00efcc034ffa4efbe..08322455368fde4b1e3104bceb48a898b5a88f97 100644 (file)
@@ -36,8 +36,6 @@
 #include <zebra.h>
 
 
-#ifdef HAVE_IRDP
-
 #include "if.h"
 #include "vty.h"
 #include "sockunion.h"
@@ -84,7 +82,7 @@ static void parse_irdp_packet(char *p, int len, struct interface *ifp)
        if (!zi)
                return;
 
-       irdp = &zi->irdp;
+       irdp = zi->irdp;
        if (!irdp)
                return;
 
@@ -240,7 +238,7 @@ int irdp_read_raw(struct thread *r)
        if (!zi)
                return ret;
 
-       irdp = &zi->irdp;
+       irdp = zi->irdp;
        if (!irdp)
                return ret;
 
@@ -353,6 +351,3 @@ void send_packet(struct interface *ifp, struct stream *s, u_int32_t dst,
        }
        /*   printf("TX on %s idx %d\n", ifp->name, ifp->ifindex); */
 }
-
-
-#endif /* HAVE_IRDP */
index 84d01bca6f045f28e4f452f5d5c333a197b7cd68..e2a1deb9ac691e11d16fe08446250e2f0c6a1166 100644 (file)
@@ -88,13 +88,10 @@ extern struct zebra_privs_t zserv_privs;
 #if !defined(ROUNDUP)
 
 /*
- * It's a bug for a platform not to define rounding/alignment for
- * sockaddrs on the routing socket.  This warning really is
- * intentional, to provoke filing bug reports with operating systems
- * that don't define RT_ROUNDUP or equivalent.
+ * If you're porting to a platform that changed RT_ROUNDUP but doesn't
+ * have it in its headers, this will break rather obviously and you'll
+ * have to fix it here.
  */
-#warning                                                                       \
-       "net/route.h does not define RT_ROUNDUP; making unwarranted assumptions!"
 
 /* OS X (Xcode as of 2014-12) is known not to define RT_ROUNDUP */
 #ifdef __APPLE__
index 538c2f0663129ed7db8e1e5463bfeeceb5d578a4..bc7276817d560e5c08020979345e310553cece97 100644 (file)
@@ -125,9 +125,7 @@ static void sigint(void)
 
        zlog_notice("Terminating on signal");
 
-#ifdef HAVE_IRDP
-       irdp_finish();
-#endif
+       frr_early_fini();
 
        zebra_ptm_finish();
        list_delete_all_node(zebrad.client_list);
@@ -147,17 +145,14 @@ static void sigint(void)
        access_list_reset();
        prefix_list_reset();
        route_map_finish();
-       cmd_terminate();
-       vty_terminate();
-       zprivs_terminate(&zserv_privs);
+
        list_delete(zebrad.client_list);
        work_queue_free(zebrad.ribq);
        if (zebrad.lsp_process_q)
                work_queue_free(zebrad.lsp_process_q);
        meta_queue_free(zebrad.mq);
-       thread_master_free(zebrad.master);
-       closezlog();
 
+       frr_fini();
        exit(0);
 }
 
@@ -297,9 +292,6 @@ int main(int argc, char **argv)
 #if defined(HAVE_RTADV)
        rtadv_cmd_init();
 #endif
-#ifdef HAVE_IRDP
-       irdp_init();
-#endif
 /* PTM socket */
 #ifdef ZEBRA_PTM_SUPPORT
        zebra_ptm_init();
index ed27dc3e8344c11bfaa74419b28f5f93df3bdf8e..9b21eb4d8c1a9c0b81daa353240c6a589a474c39 100644 (file)
@@ -95,8 +95,8 @@ static void zebra_redistribute_default(struct zserv *client, vrf_id_t vrf_id)
                RNODE_FOREACH_RE(rn, newre)
                if (CHECK_FLAG(newre->flags, ZEBRA_FLAG_SELECTED)
                    && newre->distance != DISTANCE_INFINITY)
-                       zsend_redistribute_route(1, client, &rn->p, NULL,
-                                                newre);
+                       zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_ADD,
+                                                client, &rn->p, NULL, newre);
 
                route_unlock_node(rn);
        }
@@ -114,7 +114,7 @@ static void zebra_redistribute(struct zserv *client, int type, u_short instance,
        if (!table)
                return;
 
-       for (rn = route_top(table); rn; rn = route_next(rn))
+       for (rn = route_top(table); rn; rn = srcdest_route_next(rn))
                RNODE_FOREACH_RE(rn, newre)
                {
                        struct prefix *dst_p, *src_p;
@@ -141,8 +141,8 @@ static void zebra_redistribute(struct zserv *client, int type, u_short instance,
                        if (!zebra_check_addr(dst_p))
                                continue;
 
-                       zsend_redistribute_route(1, client, dst_p, src_p,
-                                                newre);
+                       zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_ADD,
+                                                client, dst_p, src_p, newre);
                }
 }
 
@@ -191,7 +191,8 @@ void redistribute_update(struct prefix *p, struct prefix *src_p,
                        send_redistribute = 1;
 
                if (send_redistribute) {
-                       zsend_redistribute_route(1, client, p, src_p, re);
+                       zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_ADD,
+                                                client, p, src_p, re);
                } else if (prev_re
                           && ((re->instance
                                && redist_check_instance(
@@ -201,7 +202,8 @@ void redistribute_update(struct prefix *p, struct prefix *src_p,
                               || vrf_bitmap_check(
                                          client->redist[afi][prev_re->type],
                                          re->vrf_id))) {
-                       zsend_redistribute_route(0, client, p, src_p, prev_re);
+                       zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_DEL,
+                                                client, p, src_p, prev_re);
                }
        }
 }
@@ -242,7 +244,8 @@ void redistribute_delete(struct prefix *p, struct prefix *src_p,
                                   re->instance))
                    || vrf_bitmap_check(client->redist[afi][re->type],
                                        re->vrf_id)) {
-                       zsend_redistribute_route(0, client, p, src_p, re);
+                       zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_DEL,
+                                                client, p, src_p, re);
                }
        }
 }
index 4e4d726b4618042ad7878bc0f073a7d40582bc39..32ae41b917cd77496efd9a4e7cc63561bba311b5 100644 (file)
@@ -71,6 +71,27 @@ static int sin_masklen(struct in_addr mask)
 }
 #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
 
+#ifdef __OpenBSD__
+static int kernel_rtm_add_labels(struct nexthop_label *nh_label,
+                                struct sockaddr_mpls *smpls)
+{
+       if (nh_label->num_labels > 1) {
+               zlog_warn(
+                       "%s: can't push %u labels at "
+                       "once (maximum is 1)",
+                       __func__, nh_label->num_labels);
+               return -1;
+       }
+
+       memset(smpls, 0, sizeof(*smpls));
+       smpls->smpls_len = sizeof(*smpls);
+       smpls->smpls_family = AF_MPLS;
+       smpls->smpls_label = htonl(nh_label->label[0] << MPLS_LABEL_OFFSET);
+
+       return 0;
+}
+#endif
+
 /* Interface between zebra message and rtm message. */
 static int kernel_rtm_ipv4(int cmd, struct prefix *p, struct route_entry *re)
 
@@ -150,15 +171,11 @@ static int kernel_rtm_ipv4(int cmd, struct prefix *p, struct route_entry *re)
                        }
 
 #ifdef __OpenBSD__
-                       if (nexthop->nh_label) {
-                               memset(&smpls, 0, sizeof(smpls));
-                               smpls.smpls_len = sizeof(smpls);
-                               smpls.smpls_family = AF_MPLS;
-                               smpls.smpls_label =
-                                       htonl(nexthop->nh_label->label[0]
-                                             << MPLS_LABEL_OFFSET);
-                               smplsp = (union sockunion *)&smpls;
-                       }
+                       if (nexthop->nh_label
+                           && !kernel_rtm_add_labels(nexthop->nh_label,
+                                                     &smpls))
+                               continue;
+                       smplsp = (union sockunion *)&smpls;
 #endif
 
                        error = rtm_write(
@@ -266,6 +283,10 @@ static int kernel_rtm_ipv6(int cmd, struct prefix *p, struct route_entry *re)
 {
        struct sockaddr_in6 *mask;
        struct sockaddr_in6 sin_dest, sin_mask, sin_gate;
+#ifdef __OpenBSD__
+       struct sockaddr_mpls smpls;
+#endif
+       union sockunion *smplsp = NULL;
        struct nexthop *nexthop;
        int nexthop_num = 0;
        ifindex_t ifindex = 0;
@@ -338,10 +359,17 @@ static int kernel_rtm_ipv6(int cmd, struct prefix *p, struct route_entry *re)
                        mask = &sin_mask;
                }
 
+#ifdef __OpenBSD__
+               if (nexthop->nh_label
+                   && !kernel_rtm_add_labels(nexthop->nh_label, &smpls))
+                       continue;
+               smplsp = (union sockunion *)&smpls;
+#endif
+
                error = rtm_write(cmd, (union sockunion *)&sin_dest,
                                  (union sockunion *)mask,
                                  gate ? (union sockunion *)&sin_gate : NULL,
-                                 NULL, ifindex, re->flags, re->metric);
+                                 smplsp, ifindex, re->flags, re->metric);
 
 #if 0
       if (error)
index b8cf2d490afbe2a269c1e9969fb629c765a5bfe8..2182d6618ce4a33fa4a24c0b19a387424119cd1d 100644 (file)
@@ -62,6 +62,10 @@ extern struct zebra_privs_t zserv_privs;
 #define ALLNODE   "ff02::1"
 #define ALLROUTER "ff02::2"
 
+/* Order is intentional.  Matches RFC4191.  This array is also used for
+   command matching, so only modify with care. */
+const char *rtadv_pref_strs[] = {"medium", "high", "INVALID", "low", 0};
+
 enum rtadv_event {
        RTADV_START,
        RTADV_STOP,
@@ -1456,9 +1460,76 @@ DEFUN (no_ipv6_nd_mtu,
        return CMD_SUCCESS;
 }
 
+/* Dump interface ND information to vty. */
+static int nd_dump_vty(struct vty *vty, struct interface *ifp)
+{
+       struct zebra_if *zif;
+       struct rtadvconf *rtadv;
+       int interval;
+
+       zif = (struct zebra_if *)ifp->info;
+       rtadv = &zif->rtadv;
+
+       if (rtadv->AdvSendAdvertisements) {
+               vty_out(vty,
+                       "  ND advertised reachable time is %d milliseconds\n",
+                       rtadv->AdvReachableTime);
+               vty_out(vty,
+                       "  ND advertised retransmit interval is %d milliseconds\n",
+                       rtadv->AdvRetransTimer);
+               vty_out(vty, "  ND router advertisements sent: %d rcvd: %d\n",
+                       zif->ra_sent, zif->ra_rcvd);
+               interval = rtadv->MaxRtrAdvInterval;
+               if (interval % 1000)
+                       vty_out(vty,
+                               "  ND router advertisements are sent every "
+                               "%d milliseconds\n",
+                               interval);
+               else
+                       vty_out(vty,
+                               "  ND router advertisements are sent every "
+                               "%d seconds\n",
+                               interval / 1000);
+               if (rtadv->AdvDefaultLifetime != -1)
+                       vty_out(vty,
+                               "  ND router advertisements live for %d seconds\n",
+                               rtadv->AdvDefaultLifetime);
+               else
+                       vty_out(vty,
+                               "  ND router advertisements lifetime tracks ra-interval\n");
+               vty_out(vty,
+                       "  ND router advertisement default router preference is "
+                       "%s\n",
+                       rtadv_pref_strs[rtadv->DefaultPreference]);
+               if (rtadv->AdvManagedFlag)
+                       vty_out(vty,
+                               "  Hosts use DHCP to obtain routable addresses.\n");
+               else
+                       vty_out(vty,
+                               "  Hosts use stateless autoconfig for addresses.\n");
+               if (rtadv->AdvHomeAgentFlag) {
+                       vty_out(vty,
+                               "  ND router advertisements with Home Agent flag bit set.\n");
+                       if (rtadv->HomeAgentLifetime != -1)
+                               vty_out(vty,
+                                       "  Home Agent lifetime is %u seconds\n",
+                                       rtadv->HomeAgentLifetime);
+                       else
+                               vty_out(vty,
+                                       "  Home Agent lifetime tracks ra-lifetime\n");
+                       vty_out(vty, "  Home Agent preference is %u\n",
+                               rtadv->HomeAgentPreference);
+               }
+               if (rtadv->AdvIntervalOption)
+                       vty_out(vty,
+                               "  ND router advertisements with Adv. Interval option.\n");
+       }
+       return 0;
+}
+
 
 /* Write configuration about router advertisement. */
-void rtadv_config_write(struct vty *vty, struct interface *ifp)
+static int rtadv_config_write(struct vty *vty, struct interface *ifp)
 {
        struct zebra_if *zif;
        struct listnode *node;
@@ -1539,6 +1610,7 @@ void rtadv_config_write(struct vty *vty, struct interface *ifp)
                        vty_out(vty, " router-address");
                vty_out(vty, "\n");
        }
+       return 0;
 }
 
 
@@ -1600,6 +1672,9 @@ void rtadv_terminate(struct zebra_ns *zns)
 
 void rtadv_cmd_init(void)
 {
+       hook_register(zebra_if_extra_info, nd_dump_vty);
+       hook_register(zebra_if_config_wr, rtadv_config_write);
+
        install_element(INTERFACE_NODE, &ipv6_nd_suppress_ra_cmd);
        install_element(INTERFACE_NODE, &no_ipv6_nd_suppress_ra_cmd);
        install_element(INTERFACE_NODE, &ipv6_nd_ra_interval_cmd);
index 029c97cddc50687dbeba2d5850bc736ee3d9ef60..dcaeb3ed28bf1e359add90fc355f670f10ec645a 100644 (file)
@@ -55,8 +55,6 @@ struct rtadv_prefix {
 #endif
 };
 
-extern void rtadv_config_write(struct vty *, struct interface *);
-
 /* RFC4584 Extension to Sockets API for Mobile IPv6 */
 
 #ifndef ND_OPT_ADV_INTERVAL
index 0391cab9fde750aed0eee3ce03bfc87f0bb94b1b..347482362341bfc4c58ba32549e6f19ae976668d 100644 (file)
@@ -6,6 +6,9 @@ if ZEBRA
 sbin_PROGRAMS += zebra/zebra
 dist_examples_DATA += zebra/zebra.conf.sample
 
+if IRDP
+module_LTLIBRARIES += zebra/zebra_irdp.la
+endif
 if SNMP
 module_LTLIBRARIES += zebra/zebra_snmp.la
 endif
@@ -30,9 +33,6 @@ zebra_zebra_SOURCES = \
        zebra/ipforward_proc.c \
        zebra/ipforward_solaris.c \
        zebra/ipforward_sysctl.c \
-       zebra/irdp_interface.c \
-       zebra/irdp_main.c \
-       zebra/irdp_packet.c \
        zebra/kernel_netlink.c \
        zebra/kernel_socket.c \
        zebra/label_manager.c \
@@ -106,6 +106,13 @@ noinst_HEADERS += \
        zebra/zserv.h \
        # end
 
+zebra_zebra_irdp_la_SOURCES = \
+       zebra/irdp_interface.c \
+       zebra/irdp_main.c \
+       zebra/irdp_packet.c \
+       # end
+zebra_zebra_irdp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
+
 zebra_zebra_snmp_la_SOURCES = zebra/zebra_snmp.c
 zebra_zebra_snmp_la_CFLAGS = $(WERROR) $(SNMP_CFLAGS)
 zebra_zebra_snmp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
index b88bce9e82fca25d71756ffc57a881656df68f38..8c0700ac8b13a5152406b6a7c5a02409994991e6 100644 (file)
@@ -1589,8 +1589,10 @@ static int fpm_remote_srv_write(struct vty *vty)
 
        in.s_addr = zfpm_g->fpm_server;
 
-       if (zfpm_g->fpm_server != FPM_DEFAULT_IP
-           || zfpm_g->fpm_port != FPM_DEFAULT_PORT)
+       if ((zfpm_g->fpm_server != FPM_DEFAULT_IP
+               && zfpm_g->fpm_server != INADDR_ANY)
+           || (zfpm_g->fpm_port != FPM_DEFAULT_PORT
+               && zfpm_g->fpm_port != 0))
                vty_out(vty, "fpm connection ip %s port %d\n", inet_ntoa(in),
                        zfpm_g->fpm_port);
 
index 47cf7a3cbfc056ddda0276125f18b136c4dec7c2..cee3a03858b1d6e8f34c7e73f9a05866f558308e 100644 (file)
@@ -1671,27 +1671,20 @@ int mpls_str2label(const char *label_str, u_int8_t *num_labels,
 char *mpls_label2str(u_int8_t num_labels, mpls_label_t *labels, char *buf,
                     int len, int pretty)
 {
-       char *buf_ptr = buf;
-       buf[0] = '\0';
-
-       if (pretty) {
-               if (num_labels == 1) {
-                       label2str(labels[0], buf, len);
-               } else if (num_labels == 2) {
-                       label2str(labels[0], buf, len);
-                       buf_ptr += strlen(buf);
+       char label_buf[BUFSIZ];
+       int i;
 
-                       snprintf(buf_ptr, len, "/");
-                       buf_ptr++;
-
-                       label2str(labels[1], buf_ptr, len);
-               }
-       } else {
-               if (num_labels == 1)
-                       snprintf(buf, len, "%u", labels[0]);
-               else if (num_labels == 2)
-                       snprintf(buf, len, "%u/%u", labels[0], labels[1]);
+       buf[0] = '\0';
+       for (i = 0; i < num_labels; i++) {
+               if (i != 0)
+                       strlcat(buf, "/", len);
+               if (pretty)
+                       label2str(labels[i], label_buf, sizeof(label_buf));
+               else
+                       snprintf(label_buf, sizeof(label_buf), "%u", labels[i]);
+               strlcat(buf, label_buf, len);
        }
+
        return buf;
 }
 
index c8dab39210ea97cc918a26720d7182f3c3170f6d..c8df8670f4a5d7f5231196124696afa3ce8c3426 100644 (file)
@@ -37,8 +37,6 @@
 
 /* Definitions and macros. */
 
-#define MPLS_MAX_LABELS 2  /* Maximum # labels that can be pushed. */
-
 #define NHLFE_FAMILY(nhlfe)                                                    \
        (((nhlfe)->nexthop->type == NEXTHOP_TYPE_IPV6                          \
          || (nhlfe)->nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)              \
index 119cd5b700c2aa62bebc1675cc81fa6eeda1c0ae..33f0d49d4d5babd9a299f318675295b7158a1e8d 100644 (file)
@@ -256,6 +256,15 @@ static int kernel_lsp_cmd(int action, zebra_lsp_t *lsp)
                    || (action == RTM_DELETE
                        && (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED)
                            && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)))) {
+                       if (nhlfe->nexthop->nh_label->num_labels > 1) {
+                               zlog_warn(
+                                       "%s: can't push %u labels at once "
+                                       "(maximum is 1)",
+                                       __func__,
+                                       nhlfe->nexthop->nh_label->num_labels);
+                               continue;
+                       }
+
                        nexthop_num++;
 
                        switch (NHLFE_FAMILY(nhlfe)) {
index 4f1d8b0915c2d9e14eae021d02c3d2c30120d4fe..0b6263fac5241b2ce4b82f3d16fd493f060568d2 100644 (file)
@@ -434,8 +434,9 @@ DEFUN (pseudowire_control_word,
 
 DEFUN (show_pseudowires,
        show_pseudowires_cmd,
-       "show pseudowires",
+       "show mpls pseudowires",
        SHOW_STR
+       MPLS_STR
        "Pseudowires")
 {
        struct zebra_vrf *zvrf;
index ed5355426524bdb528654c5bca083d8f061f5137..dc61ea5e40c14a3211c89af7b8ba7393071af4e0 100644 (file)
@@ -1820,7 +1820,7 @@ void rib_queue_add(struct route_node *rn)
         * holder, if necessary, then push the work into it in any case.
         * This semantics was introduced after 0.99.9 release.
         */
-       if (!zebrad.ribq->items->count)
+       if (work_queue_empty(zebrad.ribq))
                work_queue_add(zebrad.ribq, zebrad.mq);
 
        rib_meta_queue_add(zebrad.mq, rn);
@@ -2352,7 +2352,7 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
                                break;
                        }
                        for (ALL_NEXTHOPS(re->nexthop, nexthop))
-                               if (IPV4_ADDR_SAME(&nexthop->gate.ipv4, gate)
+                               if (IPV4_ADDR_SAME(&nexthop->gate.ipv4, &gate->ipv4)
                                    || IPV6_ADDR_SAME(&nexthop->gate.ipv6,
                                                      gate)) {
                                        same = re;
index dba228ea350df68c7d0ba04840a54dc8d95305c9..6815916faf8d08b91e232f6b0d80be2b30e8d51f 100644 (file)
@@ -398,7 +398,7 @@ int static_add_route(afi_t afi, safi_t safi, u_char type, struct prefix *p,
        for (si = rn->info; si; si = si->next) {
                if (type == si->type
                    && (!gate || ((afi == AFI_IP
-                                  && IPV4_ADDR_SAME(gate, &si->addr.ipv4))
+                                  && IPV4_ADDR_SAME(&gate->ipv4, &si->addr.ipv4))
                                  || (afi == AFI_IP6
                                      && IPV6_ADDR_SAME(gate, &si->addr.ipv6))))
                    && (!strcmp (ifname ? ifname : "", si->ifname))) {
@@ -515,7 +515,7 @@ int static_delete_route(afi_t afi, safi_t safi, u_char type, struct prefix *p,
        for (si = rn->info; si; si = si->next)
                if (type == si->type
                    && (!gate || ((afi == AFI_IP
-                                  && IPV4_ADDR_SAME(gate, &si->addr.ipv4))
+                                  && IPV4_ADDR_SAME(&gate->ipv4, &si->addr.ipv4))
                                  || (afi == AFI_IP6
                                      && IPV6_ADDR_SAME(gate, &si->addr.ipv6))))
                    && (!strcmp(ifname ? ifname : "", si->ifname))
index 6ab47094a1498d545c2a7a3319d881a9ae043a68..ff9f0f59e7da5d55ab90584a6a73f34ae77d607b 100644 (file)
 #ifndef __ZEBRA_STATIC_H__
 #define __ZEBRA_STATIC_H__
 
+#include "zebra/zebra_mpls.h"
+
 /* Static route label information */
 struct static_nh_label {
        u_int8_t num_labels;
        u_int8_t reserved[3];
-       mpls_label_t label[2];
+       mpls_label_t label[MPLS_MAX_LABELS];
 };
 
 typedef enum {
index f01f037ed5f3dc0b8676742958ae5f8ecb2de831..9f887e840189428045cfb4d16fd7cd34a3556571 100644 (file)
@@ -1705,16 +1705,14 @@ static int static_config(struct vty *vty, afi_t afi, safi_t safi,
                                                inet_ntop(AF_INET,
                                                          &si->addr.ipv4, buf,
                                                          sizeof buf),
-                                               ifindex2ifname(si->ifindex,
-                                                              si->vrf_id));
+                                               si->ifname);
                                        break;
                                case STATIC_IPV6_GATEWAY_IFNAME:
                                        vty_out(vty, " %s %s",
                                                inet_ntop(AF_INET6,
                                                          &si->addr.ipv6, buf,
                                                          sizeof buf),
-                                               ifindex2ifname(si->ifindex,
-                                                              si->vrf_id));
+                                               si->ifname);
                                        break;
                                }
 
index cd893b567077ab49af580a1227ce69d48da23c2b..0e0cc78bbe3be3267f979a2288b1ff71acef1f33 100644 (file)
@@ -592,193 +592,76 @@ int zsend_interface_update(int cmd, struct zserv *client, struct interface *ifp)
        return zebra_server_send_message(client);
 }
 
-/*
- * This is the new function to announce and withdraw redistributed routes, used
- * by Zebra. This is the old zsend_route_multipath() function. That function
- * was duplicating code to send a lot of information that was essentially thrown
- * away or ignored by the receiver. This is the leaner function that is not a
- * duplicate of the zapi_ipv4_route_add/del.
- *
- * The primary difference is that this function merely sends a single NH instead
- * of
- * all the nexthops.
- */
-int zsend_redistribute_route(int add, struct zserv *client, struct prefix *p,
+int zsend_redistribute_route(int cmd, struct zserv *client, struct prefix *p,
                             struct prefix *src_p, struct route_entry *re)
 {
-       afi_t afi;
-       int cmd;
-       int psize;
-       struct stream *s;
+       struct zapi_route api;
+       struct zapi_nexthop *api_nh;
        struct nexthop *nexthop;
-       unsigned long nhnummark = 0, messmark = 0;
-       int nhnum = 0;
-       u_char zapi_flags = 0;
-       struct nexthop dummy_nh;
-
-       afi = family2afi(p->family);
-       if (add) {
-               switch (afi) {
-               case AFI_IP:
-                       cmd = ZEBRA_REDISTRIBUTE_IPV4_ADD;
-                       client->redist_v4_add_cnt++;
-                       break;
-               case AFI_IP6:
-                       cmd = ZEBRA_REDISTRIBUTE_IPV6_ADD;
-                       client->redist_v6_add_cnt++;
-                       break;
-               default:
-                       return -1;
-               }
-       } else {
-               switch (afi) {
-               case AFI_IP:
-                       cmd = ZEBRA_REDISTRIBUTE_IPV4_DEL;
-                       client->redist_v4_del_cnt++;
-                       break;
-               case AFI_IP6:
-                       cmd = ZEBRA_REDISTRIBUTE_IPV6_DEL;
-                       client->redist_v6_del_cnt++;
-                       break;
-               default:
-                       return -1;
-               }
-       }
-
-       s = client->obuf;
-       stream_reset(s);
-       memset(&dummy_nh, 0, sizeof(struct nexthop));
+       int count = 0;
 
-       zserv_create_header(s, cmd, re->vrf_id);
-
-       /* Put type and nexthop. */
-       stream_putc(s, re->type);
-       stream_putw(s, re->instance);
-       stream_putl(s, re->flags);
-
-       /* marker for message flags field */
-       messmark = stream_get_endp(s);
-       stream_putc(s, 0);
+       memset(&api, 0, sizeof(api));
+       api.vrf_id = VRF_DEFAULT;
+       api.type = re->type;
+       api.instance = re->instance;
+       api.flags = re->flags;
 
        /* Prefix. */
-       psize = PSIZE(p->prefixlen);
-       stream_putc(s, p->prefixlen);
-       stream_write(s, (u_char *)&p->u.prefix, psize);
-
+       api.prefix = *p;
        if (src_p) {
-               SET_FLAG(zapi_flags, ZAPI_MESSAGE_SRCPFX);
-               psize = PSIZE(src_p->prefixlen);
-               stream_putc(s, src_p->prefixlen);
-               stream_write(s, (u_char *)&src_p->u.prefix, psize);
+               SET_FLAG(api.message, ZAPI_MESSAGE_SRCPFX);
+               memcpy(&api.src_prefix, src_p, sizeof(api.src_prefix));
        }
 
+       /* Nexthops. */
+       if (re->nexthop_active_num) {
+               SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
+               api.nexthop_num = re->nexthop_active_num;
+       }
        for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) {
-               /* We don't send any nexthops when there's a multipath */
-               if (re->nexthop_active_num > 1
-                   && client->proto != ZEBRA_ROUTE_LDP) {
-                       SET_FLAG(zapi_flags, ZAPI_MESSAGE_NEXTHOP);
-                       SET_FLAG(zapi_flags, ZAPI_MESSAGE_IFINDEX);
-
-                       stream_putc(s, 1);
-                       if (p->family == AF_INET) {
-                               stream_put_in_addr(s, &dummy_nh.gate.ipv4);
-                       } else if (p->family == AF_INET6) {
-                               stream_write(s, (u_char *)&dummy_nh.gate.ipv6,
-                                            16);
-                       } else {
-                               /* We don't handle anything else now, abort */
-                               zlog_err(
-                                       "%s: Unable to redistribute route of unknown family, %d\n",
-                                       __func__, p->family);
-                               return -1;
-                       }
-                       stream_putc(s, 1);
-                       stream_putl(s, 0); /* dummy ifindex */
-                       break;
-               }
-
-               if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) {
-                       SET_FLAG(zapi_flags, ZAPI_MESSAGE_NEXTHOP);
-                       SET_FLAG(zapi_flags, ZAPI_MESSAGE_IFINDEX);
-                       if (nhnummark == 0) {
-                               nhnummark = stream_get_endp(s);
-                               stream_putc(s, 1); /* placeholder */
-                       }
-                       nhnum++;
-
-                       switch (nexthop->type) {
-                       case NEXTHOP_TYPE_IPV4:
-                       case NEXTHOP_TYPE_IPV4_IFINDEX:
-                               stream_put_in_addr(s, &nexthop->gate.ipv4);
-                               break;
-                       case NEXTHOP_TYPE_IPV6:
-                       case NEXTHOP_TYPE_IPV6_IFINDEX:
-                               /* Only BGP supports IPv4 prefix with IPv6 NH,
-                                * so kill this */
-                               if (p->family == AF_INET)
-                                       stream_put_in_addr(s,
-                                                          &dummy_nh.gate.ipv4);
-                               else
-                                       stream_write(
-                                               s,
-                                               (u_char *)&nexthop->gate.ipv6,
-                                               16);
-                               break;
-                       default:
-                               if (cmd == ZEBRA_REDISTRIBUTE_IPV4_ADD
-                                   || cmd == ZEBRA_REDISTRIBUTE_IPV4_DEL) {
-                                       struct in_addr empty;
-                                       memset(&empty, 0,
-                                              sizeof(struct in_addr));
-                                       stream_write(s, (u_char *)&empty,
-                                                    IPV4_MAX_BYTELEN);
-                               } else {
-                                       struct in6_addr empty;
-                                       memset(&empty, 0,
-                                              sizeof(struct in6_addr));
-                                       stream_write(s, (u_char *)&empty,
-                                                    IPV6_MAX_BYTELEN);
-                               }
-                       }
-
-                       /* Interface index. */
-                       stream_putc(s, 1);
-                       stream_putl(s, nexthop->ifindex);
+               if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
+                       continue;
 
-                       /* ldpd needs all nexthops */
-                       if (client->proto != ZEBRA_ROUTE_LDP)
-                               break;
+               api_nh = &api.nexthops[count];
+               api_nh->type = nexthop->type;
+               switch (nexthop->type) {
+               case NEXTHOP_TYPE_BLACKHOLE:
+                       break;
+               case NEXTHOP_TYPE_IPV4:
+                       api_nh->gate.ipv4 = nexthop->gate.ipv4;
+                       break;
+               case NEXTHOP_TYPE_IPV4_IFINDEX:
+                       api_nh->gate.ipv4 = nexthop->gate.ipv4;
+                       api_nh->ifindex = nexthop->ifindex;
+                       break;
+               case NEXTHOP_TYPE_IFINDEX:
+                       api_nh->ifindex = nexthop->ifindex;
+                       break;
+               case NEXTHOP_TYPE_IPV6:
+                       api_nh->gate.ipv6 = nexthop->gate.ipv6;
+                       break;
+               case NEXTHOP_TYPE_IPV6_IFINDEX:
+                       api_nh->gate.ipv6 = nexthop->gate.ipv6;
+                       api_nh->ifindex = nexthop->ifindex;
                }
+               count++;
        }
 
-       /* Distance */
-       SET_FLAG(zapi_flags, ZAPI_MESSAGE_DISTANCE);
-       stream_putc(s, re->distance);
-
-       /* Metric */
-       SET_FLAG(zapi_flags, ZAPI_MESSAGE_METRIC);
-       stream_putl(s, re->metric);
-
-       /* Tag */
+       /* Attributes. */
+       SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE);
+       api.distance = re->distance;
+       SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
+       api.metric = re->metric;
        if (re->tag) {
-               SET_FLAG(zapi_flags, ZAPI_MESSAGE_TAG);
-               stream_putl(s, re->tag);
+               SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
+               api.tag = re->tag;
        }
+       SET_FLAG(api.message, ZAPI_MESSAGE_MTU);
+       api.mtu = re->mtu;
 
-       /* MTU */
-       SET_FLAG(zapi_flags, ZAPI_MESSAGE_MTU);
-       stream_putl(s, re->mtu);
-
-       /* write real message flags value */
-       stream_putc_at(s, messmark, zapi_flags);
-
-       /* Write next-hop number */
-       if (nhnummark)
-               stream_putc_at(s, nhnummark, nhnum);
-
-       /* Write packet size. */
-       stream_putw_at(s, 0, stream_get_endp(s));
-
+       /* Encode route and send. */
+       if (zapi_route_encode(cmd, client->obuf, &api) < 0)
+               return -1;
        return zebra_server_send_message(client);
 }
 
@@ -1157,6 +1040,145 @@ void zserv_nexthop_num_warn(const char *caller, const struct prefix *p,
        }
 }
 
+static int zread_route_add(struct zserv *client, u_short length,
+                          struct zebra_vrf *zvrf)
+{
+       struct stream *s;
+       struct zapi_route api;
+       struct zapi_nexthop *api_nh;
+       afi_t afi;
+       struct prefix_ipv6 *src_p = NULL;
+       struct route_entry *re;
+       struct nexthop *nexthop = NULL;
+       int i, ret;
+
+       s = client->ibuf;
+       if (zapi_route_decode(s, &api) < 0)
+               return -1;
+
+       /* Allocate new route. */
+       re = XCALLOC(MTYPE_RE, sizeof(struct route_entry));
+       re->type = api.type;
+       re->instance = api.instance;
+       re->flags = api.flags;
+       re->uptime = time(NULL);
+       re->vrf_id = zvrf_id(zvrf);
+       re->table = zvrf->table_id;
+
+       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) {
+               for (i = 0; i < api.nexthop_num; i++) {
+                       api_nh = &api.nexthops[i];
+
+                       switch (api_nh->type) {
+                       case NEXTHOP_TYPE_IFINDEX:
+                               route_entry_nexthop_ifindex_add(
+                                       re, api_nh->ifindex);
+                               break;
+                       case NEXTHOP_TYPE_IPV4:
+                               nexthop = route_entry_nexthop_ipv4_add(
+                                       re, &api_nh->gate.ipv4, NULL);
+                               break;
+                       case NEXTHOP_TYPE_IPV4_IFINDEX:
+                               nexthop = route_entry_nexthop_ipv4_ifindex_add(
+                                       re, &api_nh->gate.ipv4, NULL,
+                                       api_nh->ifindex);
+                               break;
+                       case NEXTHOP_TYPE_IPV6:
+                               nexthop = route_entry_nexthop_ipv6_add(
+                                       re, &api_nh->gate.ipv6);
+                               break;
+                       case NEXTHOP_TYPE_IPV6_IFINDEX:
+                               nexthop = route_entry_nexthop_ipv6_ifindex_add(
+                                       re, &api_nh->gate.ipv6,
+                                       api_nh->ifindex);
+                               break;
+                       case NEXTHOP_TYPE_BLACKHOLE:
+                               route_entry_nexthop_blackhole_add(re);
+                               break;
+                       }
+
+                       /* MPLS labels for BGP-LU or Segment Routing */
+                       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_LABEL)
+                           && api_nh->type != NEXTHOP_TYPE_IFINDEX
+                           && api_nh->type != NEXTHOP_TYPE_BLACKHOLE) {
+                               enum lsp_types_t label_type;
+
+                               label_type =
+                                       lsp_type_from_re_type(client->proto);
+                               nexthop_add_labels(nexthop, label_type,
+                                                  api_nh->label_num,
+                                                  &api_nh->labels[0]);
+                       }
+               }
+       }
+
+       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE))
+               re->distance = api.distance;
+       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC))
+               re->metric = api.metric;
+       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG))
+               re->tag = api.tag;
+       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_MTU))
+               re->mtu = api.mtu;
+
+       afi = family2afi(api.prefix.family);
+       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
+               src_p = &api.src_prefix;
+
+       ret = rib_add_multipath(afi, api.safi, &api.prefix, src_p, re);
+
+       /* Stats */
+       switch (api.prefix.family) {
+       case AF_INET:
+               if (ret > 0)
+                       client->v4_route_add_cnt++;
+               else if (ret < 0)
+                       client->v4_route_upd8_cnt++;
+               break;
+       case AF_INET6:
+               if (ret > 0)
+                       client->v6_route_add_cnt++;
+               else if (ret < 0)
+                       client->v6_route_upd8_cnt++;
+               break;
+       }
+
+       return 0;
+}
+
+static int zread_route_del(struct zserv *client, u_short length,
+                          struct zebra_vrf *zvrf)
+{
+       struct stream *s;
+       struct zapi_route api;
+       afi_t afi;
+       struct prefix_ipv6 *src_p = NULL;
+
+       s = client->ibuf;
+       if (zapi_route_decode(s, &api) < 0)
+               return -1;
+
+       afi = family2afi(api.prefix.family);
+       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
+               src_p = &api.src_prefix;
+
+       rib_delete(afi, api.safi, zvrf_id(zvrf), api.type, api.instance,
+                  api.flags, &api.prefix, src_p, NULL, 0, zvrf->table_id,
+                  api.metric);
+
+       /* Stats */
+       switch (api.prefix.family) {
+       case AF_INET:
+               client->v4_route_del_cnt++;
+               break;
+       case AF_INET6:
+               client->v6_route_del_cnt++;
+               break;
+       }
+
+       return 0;
+}
+
 /* This function support multiple nexthop. */
 /*
  * Parse the ZEBRA_IPV4_ROUTE_ADD sent from client. Update re and
@@ -1176,6 +1198,7 @@ static int zread_ipv4_add(struct zserv *client, u_short length,
        ifindex_t ifindex;
        safi_t safi;
        int ret;
+       enum lsp_types_t label_type = ZEBRA_LSP_NONE;
        mpls_label_t label;
        struct nexthop *nexthop;
 
@@ -1208,6 +1231,9 @@ static int zread_ipv4_add(struct zserv *client, u_short length,
                zserv_nexthop_num_warn(__func__, (const struct prefix *)&p,
                                       nexthop_num);
 
+               if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL))
+                       label_type = lsp_type_from_re_type(client->proto);
+
                for (i = 0; i < nexthop_num; i++) {
                        nexthop_type = stream_getc(s);
 
@@ -1224,9 +1250,8 @@ static int zread_ipv4_add(struct zserv *client, u_short length,
                                 * by label. */
                                if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL)) {
                                        label = (mpls_label_t)stream_getl(s);
-                                       nexthop_add_labels(
-                                               nexthop, nexthop->nh_label_type,
-                                               1, &label);
+                                       nexthop_add_labels(nexthop, label_type,
+                                                          1, &label);
                                }
                                break;
                        case NEXTHOP_TYPE_IPV4_IFINDEX:
@@ -1281,21 +1306,12 @@ static int zread_ipv4_add(struct zserv *client, u_short length,
 static int zread_ipv4_delete(struct zserv *client, u_short length,
                             struct zebra_vrf *zvrf)
 {
-       int i;
        struct stream *s;
        struct zapi_ipv4 api;
-       struct in_addr nexthop;
-       union g_addr *nexthop_p;
-       unsigned long ifindex;
        struct prefix p;
-       u_char nexthop_num;
-       u_char nexthop_type;
        u_int32_t table_id;
 
        s = client->ibuf;
-       ifindex = 0;
-       nexthop.s_addr = 0;
-       nexthop_p = NULL;
 
        /* Type, flags, message. */
        api.type = stream_getc(s);
@@ -1310,63 +1326,10 @@ static int zread_ipv4_delete(struct zserv *client, u_short length,
        p.prefixlen = stream_getc(s);
        stream_get(&p.u.prefix4, s, PSIZE(p.prefixlen));
 
-       /* Nexthop, ifindex, distance, metric. */
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) {
-               nexthop_num = stream_getc(s);
-
-               for (i = 0; i < nexthop_num; i++) {
-                       nexthop_type = stream_getc(s);
-
-                       switch (nexthop_type) {
-                       case NEXTHOP_TYPE_IFINDEX:
-                               ifindex = stream_getl(s);
-                               break;
-                       case NEXTHOP_TYPE_IPV4:
-                               nexthop.s_addr = stream_get_ipv4(s);
-                               /* For labeled-unicast, each nexthop is followed
-                                * by label, but
-                                * we don't care for delete.
-                                */
-                               if (CHECK_FLAG(api.message, ZAPI_MESSAGE_LABEL))
-                                       stream_forward_getp(s,
-                                                           sizeof(u_int32_t));
-                               nexthop_p = (union g_addr *)&nexthop;
-                               break;
-                       case NEXTHOP_TYPE_IPV4_IFINDEX:
-                               nexthop.s_addr = stream_get_ipv4(s);
-                               nexthop_p = (union g_addr *)&nexthop;
-                               ifindex = stream_getl(s);
-                               break;
-                       case NEXTHOP_TYPE_IPV6:
-                               stream_forward_getp(s, IPV6_MAX_BYTELEN);
-                               break;
-                       }
-               }
-       }
-
-       /* Distance. */
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE))
-               api.distance = stream_getc(s);
-       else
-               api.distance = 0;
-
-       /* Metric. */
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC))
-               api.metric = stream_getl(s);
-       else
-               api.metric = 0;
-
-       /* tag */
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG))
-               api.tag = stream_getl(s);
-       else
-               api.tag = 0;
-
        table_id = zvrf->table_id;
 
        rib_delete(AFI_IP, api.safi, zvrf_id(zvrf), api.type, api.instance,
-                  api.flags, &p, NULL, nexthop_p, ifindex, table_id,
-                  api.metric);
+                  api.flags, &p, NULL, NULL, 0, table_id, 0);
        client->v4_route_del_cnt++;
        return 0;
 }
@@ -1401,6 +1364,7 @@ static int zread_ipv4_route_ipv6_nexthop_add(struct zserv *client,
        static unsigned int ifindices[MULTIPATH_NUM];
        int ret;
        static mpls_label_t labels[MULTIPATH_NUM];
+       enum lsp_types_t label_type = ZEBRA_LSP_NONE;
        mpls_label_t label;
        struct nexthop *nexthop;
 
@@ -1441,6 +1405,10 @@ static int zread_ipv4_route_ipv6_nexthop_add(struct zserv *client,
                nexthop_num = stream_getc(s);
                zserv_nexthop_num_warn(__func__, (const struct prefix *)&p,
                                       nexthop_num);
+
+               if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL))
+                       label_type = lsp_type_from_re_type(client->proto);
+
                for (i = 0; i < nexthop_num; i++) {
                        nexthop_type = stream_getc(s);
 
@@ -1485,9 +1453,8 @@ static int zread_ipv4_route_ipv6_nexthop_add(struct zserv *client,
                                                re, &nexthops[i]);
 
                                if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL))
-                                       nexthop_add_labels(
-                                               nexthop, nexthop->nh_label_type,
-                                               1, &labels[i]);
+                                       nexthop_add_labels(nexthop, label_type,
+                                                          1, &labels[i]);
                        } else {
                                if ((i < if_count) && ifindices[i])
                                        route_entry_nexthop_ifindex_add(
@@ -1534,6 +1501,7 @@ static int zread_ipv6_add(struct zserv *client, u_short length,
        unsigned int i;
        struct stream *s;
        struct in6_addr nhop_addr;
+       ifindex_t ifindex;
        struct route_entry *re;
        u_char message;
        u_char nexthop_num;
@@ -1545,6 +1513,7 @@ static int zread_ipv6_add(struct zserv *client, u_short length,
        static unsigned int ifindices[MULTIPATH_NUM];
        int ret;
        static mpls_label_t labels[MULTIPATH_NUM];
+       enum lsp_types_t label_type = ZEBRA_LSP_NONE;
        mpls_label_t label;
        struct nexthop *nexthop;
 
@@ -1591,6 +1560,10 @@ static int zread_ipv6_add(struct zserv *client, u_short length,
                nexthop_num = stream_getc(s);
                zserv_nexthop_num_warn(__func__, (const struct prefix *)&p,
                                       nexthop_num);
+
+               if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL))
+                       label_type = lsp_type_from_re_type(client->proto);
+
                for (i = 0; i < nexthop_num; i++) {
                        nexthop_type = stream_getc(s);
 
@@ -1609,6 +1582,12 @@ static int zread_ipv6_add(struct zserv *client, u_short length,
                                        nexthops[nh_count++] = nhop_addr;
                                }
                                break;
+                       case NEXTHOP_TYPE_IPV6_IFINDEX:
+                               stream_get(&nhop_addr, s, 16);
+                               ifindex = stream_getl(s);
+                               route_entry_nexthop_ipv6_ifindex_add(
+                                       re, &nhop_addr, ifindex);
+                               break;
                        case NEXTHOP_TYPE_IFINDEX:
                                if (if_count < multipath_num) {
                                        ifindices[if_count++] = stream_getl(s);
@@ -1633,9 +1612,8 @@ static int zread_ipv6_add(struct zserv *client, u_short length,
                                        nexthop = route_entry_nexthop_ipv6_add(
                                                re, &nexthops[i]);
                                if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL))
-                                       nexthop_add_labels(
-                                               nexthop, nexthop->nh_label_type,
-                                               1, &labels[i]);
+                                       nexthop_add_labels(nexthop, label_type,
+                                                          1, &labels[i]);
                        } else {
                                if ((i < if_count) && ifindices[i])
                                        route_entry_nexthop_ifindex_add(
@@ -1681,18 +1659,12 @@ static int zread_ipv6_add(struct zserv *client, u_short length,
 static int zread_ipv6_delete(struct zserv *client, u_short length,
                             struct zebra_vrf *zvrf)
 {
-       int i;
        struct stream *s;
        struct zapi_ipv6 api;
-       struct in6_addr nexthop;
-       union g_addr *pnexthop = NULL;
-       unsigned long ifindex;
        struct prefix p;
        struct prefix_ipv6 src_p, *src_pp;
 
        s = client->ibuf;
-       ifindex = 0;
-       memset(&nexthop, 0, sizeof(struct in6_addr));
 
        /* Type, flags, message. */
        api.type = stream_getc(s);
@@ -1716,59 +1688,8 @@ static int zread_ipv6_delete(struct zserv *client, u_short length,
        } else
                src_pp = NULL;
 
-       /* Nexthop, ifindex, distance, metric. */
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) {
-               u_char nexthop_type;
-
-               api.nexthop_num = stream_getc(s);
-               for (i = 0; i < api.nexthop_num; i++) {
-                       nexthop_type = stream_getc(s);
-
-                       switch (nexthop_type) {
-                       case NEXTHOP_TYPE_IPV6:
-                               stream_get(&nexthop, s, 16);
-                               /* For labeled-unicast, each nexthop is followed
-                                * by label, but
-                                * we don't care for delete.
-                                */
-                               if (CHECK_FLAG(api.message, ZAPI_MESSAGE_LABEL))
-                                       stream_forward_getp(s,
-                                                           sizeof(u_int32_t));
-                               pnexthop = (union g_addr *)&nexthop;
-                               break;
-                       case NEXTHOP_TYPE_IFINDEX:
-                               ifindex = stream_getl(s);
-                               break;
-                       }
-               }
-       }
-
-       /* Distance. */
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE))
-               api.distance = stream_getc(s);
-       else
-               api.distance = 0;
-
-       /* Metric. */
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC))
-               api.metric = stream_getl(s);
-       else
-               api.metric = 0;
-
-       /* tag */
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG))
-               api.tag = stream_getl(s);
-       else
-               api.tag = 0;
-
-       if (IN6_IS_ADDR_UNSPECIFIED(&nexthop))
-               rib_delete(AFI_IP6, api.safi, zvrf_id(zvrf), api.type,
-                          api.instance, api.flags, &p, src_pp, NULL, ifindex,
-                          client->rtm_table, api.metric);
-       else
-               rib_delete(AFI_IP6, api.safi, zvrf_id(zvrf), api.type,
-                          api.instance, api.flags, &p, src_pp, pnexthop,
-                          ifindex, client->rtm_table, api.metric);
+       rib_delete(AFI_IP6, api.safi, zvrf_id(zvrf), api.type, api.instance,
+                  api.flags, &p, src_pp, NULL, 0, client->rtm_table, 0);
 
        client->v6_route_del_cnt++;
        return 0;
@@ -2435,6 +2356,12 @@ static int zebra_client_read(struct thread *thread)
        case ZEBRA_INTERFACE_DELETE:
                zread_interface_delete(client, length, zvrf);
                break;
+       case ZEBRA_ROUTE_ADD:
+               zread_route_add(client, length, zvrf);
+               break;
+       case ZEBRA_ROUTE_DELETE:
+               zread_route_del(client, length, zvrf);
+               break;
        case ZEBRA_IPV4_ROUTE_ADD:
                zread_ipv4_add(client, length, zvrf);
                break;
@@ -2444,14 +2371,6 @@ static int zebra_client_read(struct thread *thread)
        case ZEBRA_IPV4_ROUTE_IPV6_NEXTHOP_ADD:
                zread_ipv4_route_ipv6_nexthop_add(client, length, zvrf);
                break;
-       case ZEBRA_IPV4_NEXTHOP_ADD:
-               zread_ipv4_add(client, length,
-                              zvrf); /* LB: r1.0 merge - id was 1 */
-               break;
-       case ZEBRA_IPV4_NEXTHOP_DELETE:
-               zread_ipv4_delete(client, length,
-                                 zvrf); /* LB: r1.0 merge - id was 1 */
-               break;
        case ZEBRA_IPV6_ROUTE_ADD:
                zread_ipv6_add(client, length, zvrf);
                break;