]> git.proxmox.com Git - mirror_frr.git/commitdiff
Merge pull request #12415 from donaldsharp/bgp_use_after_free
authorRuss White <russ@riw.us>
Tue, 6 Dec 2022 16:29:31 +0000 (11:29 -0500)
committerGitHub <noreply@github.com>
Tue, 6 Dec 2022 16:29:31 +0000 (11:29 -0500)
Bgp use after free

62 files changed:
bgpd/bgp_aspath.c
bgpd/bgp_aspath.h
bgpd/bgp_attr.c
bgpd/bgp_keepalives.c
bgpd/bgp_route.c
bgpd/bgp_vty.c
bgpd/bgpd.c
doc/user/basic.rst
doc/user/vrrp.rst
ldpd/ldpe.c
lib/if.c
ospf6d/ospf6_lsa.c
ospfclient/ospf_apiclient.c
ospfclient/subdir.am
ospfd/ospf_apiserver.c
ospfd/ospf_apiserver.h
ospfd/ospf_snmp.c
ospfd/subdir.am
tests/topotests/bgp_confed1/__init__.py [new file with mode: 0644]
tests/topotests/bgp_confed1/r1/bgp_ipv4_unicast.json [new file with mode: 0644]
tests/topotests/bgp_confed1/r1/bgp_summary.json [new file with mode: 0644]
tests/topotests/bgp_confed1/r1/bgpd.conf [new file with mode: 0644]
tests/topotests/bgp_confed1/r1/isisd.conf [new file with mode: 0644]
tests/topotests/bgp_confed1/r1/zebra.conf [new file with mode: 0644]
tests/topotests/bgp_confed1/r2/bgp_ipv4_unicast.json [new file with mode: 0644]
tests/topotests/bgp_confed1/r2/bgp_summary.json [new file with mode: 0644]
tests/topotests/bgp_confed1/r2/bgpd.conf [new file with mode: 0644]
tests/topotests/bgp_confed1/r2/isisd.conf [new file with mode: 0644]
tests/topotests/bgp_confed1/r2/zebra.conf [new file with mode: 0644]
tests/topotests/bgp_confed1/r3/bgp_ipv4_unicast.json [new file with mode: 0644]
tests/topotests/bgp_confed1/r3/bgp_summary.json [new file with mode: 0644]
tests/topotests/bgp_confed1/r3/bgpd.conf [new file with mode: 0644]
tests/topotests/bgp_confed1/r3/isisd.conf [new file with mode: 0644]
tests/topotests/bgp_confed1/r3/zebra.conf [new file with mode: 0644]
tests/topotests/bgp_confed1/r4/bgp_ipv4_unicast.json [new file with mode: 0644]
tests/topotests/bgp_confed1/r4/bgp_summary.json [new file with mode: 0644]
tests/topotests/bgp_confed1/r4/bgpd.conf [new file with mode: 0644]
tests/topotests/bgp_confed1/r4/isisd.conf [new file with mode: 0644]
tests/topotests/bgp_confed1/r4/zebra.conf [new file with mode: 0644]
tests/topotests/bgp_confed1/test_bgp_confed1.py [new file with mode: 0644]
vrrpd/vrrp.c
vrrpd/vrrp.h
vrrpd/vrrp_northbound.c
vrrpd/vrrp_packet.c
vrrpd/vrrp_packet.h
vrrpd/vrrp_vty.c
vrrpd/vrrp_vty.h
vtysh/vtysh.c
vtysh/vtysh_config.c
vtysh/vtysh_main.c
yang/frr-vrrpd.yang
zebra/if_netlink.c
zebra/interface.c
zebra/interface.h
zebra/irdp_interface.c
zebra/zapi_msg.c
zebra/zebra_gr.c
zebra/zebra_ns.c
zebra/zebra_pbr.c
zebra/zebra_pbr.h
zebra/zserv.c
zebra/zserv.h

index 06f6073781773be2e8255bf5711cc5bada11c976..85f09ccf0b6572b7c90566480b5e11ccca085dfd 100644 (file)
@@ -1187,6 +1187,33 @@ int aspath_loop_check(struct aspath *aspath, as_t asno)
        return count;
 }
 
+/* AS path loop check.  If aspath contains asno
+ * that is a confed id then return >= 1.
+ */
+int aspath_loop_check_confed(struct aspath *aspath, as_t asno)
+{
+       struct assegment *seg;
+       int count = 0;
+
+       if (aspath == NULL || aspath->segments == NULL)
+               return 0;
+
+       seg = aspath->segments;
+
+       while (seg) {
+               unsigned int i;
+
+               for (i = 0; i < seg->length; i++)
+                       if (seg->type != AS_CONFED_SEQUENCE &&
+                           seg->type != AS_CONFED_SET && seg->as[i] == asno)
+                               count++;
+
+               seg = seg->next;
+       }
+       return count;
+}
+
+
 /* When all of AS path is private AS return 1.  */
 bool aspath_private_as_check(struct aspath *aspath)
 {
index 0b58e1adc4a77af8ae8168aae853b0d4a450255b..97bc7c0acada5ec7fc520b1ccd798b21b1140b71 100644 (file)
@@ -111,6 +111,7 @@ extern unsigned int aspath_key_make(const void *p);
 extern unsigned int aspath_get_first_as(struct aspath *aspath);
 extern unsigned int aspath_get_last_as(struct aspath *aspath);
 extern int aspath_loop_check(struct aspath *aspath, as_t asno);
+extern int aspath_loop_check_confed(struct aspath *aspath, as_t asno);
 extern bool aspath_private_as_check(struct aspath *aspath);
 extern struct aspath *aspath_replace_specific_asn(struct aspath *aspath,
                                                  as_t target_asn,
index 1f8c7dc098f916437852f2c549c48013020dd1f7..ace7e7975331c28da2e97a608fee4c3a237fa27d 100644 (file)
@@ -2702,6 +2702,18 @@ bgp_attr_srv6_service_data(struct bgp_attr_parser_args *args)
        }
 
        if (type == BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE) {
+               if (STREAM_READABLE(peer->curr) <
+                   BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH) {
+                       flog_err(
+                               EC_BGP_ATTR_LEN,
+                               "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficient data (need %u, have %zu remaining in UPDATE)",
+                               BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH,
+                               STREAM_READABLE(peer->curr));
+                       return bgp_attr_malformed(
+                               args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
+                               args->total);
+               }
+
                loc_block_len = stream_getc(peer->curr);
                loc_node_len = stream_getc(peer->curr);
                func_len = stream_getc(peer->curr);
@@ -2774,6 +2786,17 @@ bgp_attr_srv6_service(struct bgp_attr_parser_args *args)
        }
 
        if (type == BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO) {
+               if (STREAM_READABLE(peer->curr) <
+                   BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH) {
+                       flog_err(
+                               EC_BGP_ATTR_LEN,
+                               "Malformed SRv6 Service Sub-TLV attribute - insufficent data (need %d for attribute data, have %zu remaining in UPDATE)",
+                               BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH,
+                               STREAM_READABLE(peer->curr));
+                       return bgp_attr_malformed(
+                               args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
+                               args->total);
+               }
                stream_getc(peer->curr);
                stream_get(&ipv6_sid, peer->curr, sizeof(ipv6_sid));
                sid_flags = stream_getc(peer->curr);
index b39a7daa1dc6596784ca26dfc1e379f89c545080..0e83157ecdd5f8fa193f7718e1a8327c5df74a85 100644 (file)
 #include "bgpd/bgp_keepalives.h"
 /* clang-format on */
 
+DEFINE_MTYPE_STATIC(BGPD, BGP_PKAT, "Peer KeepAlive Timer");
+DEFINE_MTYPE_STATIC(BGPD, BGP_COND, "BGP Peer pthread Conditional");
+DEFINE_MTYPE_STATIC(BGPD, BGP_MUTEX, "BGP Peer pthread Mutex");
+
 /*
  * Peer KeepAlive Timer.
  * Associates a peer with the time of its last keepalive.
@@ -54,7 +58,7 @@ static struct hash *peerhash;
 
 static struct pkat *pkat_new(struct peer *peer)
 {
-       struct pkat *pkat = XMALLOC(MTYPE_TMP, sizeof(struct pkat));
+       struct pkat *pkat = XMALLOC(MTYPE_BGP_PKAT, sizeof(struct pkat));
        pkat->peer = peer;
        monotime(&pkat->last);
        return pkat;
@@ -62,7 +66,7 @@ static struct pkat *pkat_new(struct peer *peer)
 
 static void pkat_del(void *pkat)
 {
-       XFREE(MTYPE_TMP, pkat);
+       XFREE(MTYPE_BGP_PKAT, pkat);
 }
 
 
@@ -158,8 +162,8 @@ static void bgp_keepalives_finish(void *arg)
        pthread_mutex_destroy(peerhash_mtx);
        pthread_cond_destroy(peerhash_cond);
 
-       XFREE(MTYPE_TMP, peerhash_mtx);
-       XFREE(MTYPE_TMP, peerhash_cond);
+       XFREE(MTYPE_BGP_MUTEX, peerhash_mtx);
+       XFREE(MTYPE_BGP_COND, peerhash_cond);
 }
 
 /*
@@ -184,8 +188,8 @@ void *bgp_keepalives_start(void *arg)
         */
        rcu_read_unlock();
 
-       peerhash_mtx = XCALLOC(MTYPE_TMP, sizeof(pthread_mutex_t));
-       peerhash_cond = XCALLOC(MTYPE_TMP, sizeof(pthread_cond_t));
+       peerhash_mtx = XCALLOC(MTYPE_BGP_MUTEX, sizeof(pthread_mutex_t));
+       peerhash_cond = XCALLOC(MTYPE_BGP_COND, sizeof(pthread_cond_t));
 
        /* initialize mutex */
        pthread_mutex_init(peerhash_mtx, NULL);
index 4ade647cd08582a2b0e21b0a0b67c151eb528536..9fb8d7cfee4bfa4025f8cfc67fef871e8cebcec4 100644 (file)
@@ -2197,7 +2197,7 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
 
        /* If we're a CONFED we need to loop check the CONFED ID too */
        if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
-               if (aspath_loop_check(piattr->aspath, bgp->confed_id)) {
+               if (aspath_loop_check_confed(piattr->aspath, bgp->confed_id)) {
                        if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
                                zlog_debug(
                                        "%pBP [Update:SEND] suppress announcement to peer AS %u is AS path.",
@@ -4114,16 +4114,23 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
 
        /* AS path loop check. */
        if (do_loop_check) {
-               if (aspath_loop_check(attr->aspath, bgp->as) > allowas_in ||
-                   (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION) &&
-                    (aspath_loop_check(attr->aspath, bgp->confed_id) >
-                     allowas_in))) {
+               if (aspath_loop_check(attr->aspath, bgp->as) >
+                   peer->allowas_in[afi][safi]) {
                        peer->stat_pfx_aspath_loop++;
                        reason = "as-path contains our own AS;";
                        goto filtered;
                }
        }
 
+       /* If we're a CONFED we need to loop check the CONFED ID too */
+       if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION) && do_loop_check)
+               if (aspath_loop_check_confed(attr->aspath, bgp->confed_id) >
+                   peer->allowas_in[afi][safi]) {
+                       peer->stat_pfx_aspath_loop++;
+                       reason = "as-path contains our own confed AS;";
+                       goto filtered;
+               }
+
        /* Route reflector originator ID check. If ACCEPT_OWN mechanism is
         * enabled, then take care of that too.
         */
index 90182be85f0a9daa76dea1f300b96cfa2d48fcd1..7b9400118b762e060926bf0656c7dae703a94845 100644 (file)
@@ -1960,13 +1960,6 @@ DEFUN (bgp_confederation_peers,
 
        for (i = idx_asn; i < argc; i++) {
                as = strtoul(argv[i]->arg, NULL, 10);
-
-               if (bgp->as == as) {
-                       vty_out(vty,
-                               "%% Local member-AS not allowed in confed peer list\n");
-                       continue;
-               }
-
                bgp_confederation_peers_add(bgp, as);
        }
        return CMD_SUCCESS;
index 36ff8866e65eacb68f326e75ee4e51ba62c38f72..734e44f2525d3c552a4bff48dd2b910eaf353f0a 100644 (file)
@@ -671,7 +671,7 @@ void bgp_confederation_peers_add(struct bgp *bgp, as_t as)
        struct peer *peer;
        struct listnode *node, *nnode;
 
-       if (bgp->as == as)
+       if (!bgp)
                return;
 
        if (bgp_confederation_peers_check(bgp, as))
@@ -687,8 +687,8 @@ void bgp_confederation_peers_add(struct bgp *bgp, as_t as)
        if (bgp_config_check(bgp, BGP_CONFIG_CONFEDERATION)) {
                for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
                        if (peer->as == as) {
-                               (void)peer_sort(peer);
                                peer->local_as = bgp->as;
+                               (void)peer_sort(peer);
                                if (BGP_IS_VALID_STATE_FOR_NOTIF(
                                            peer->status)) {
                                        peer->last_reset =
@@ -738,8 +738,8 @@ void bgp_confederation_peers_remove(struct bgp *bgp, as_t as)
        if (bgp_config_check(bgp, BGP_CONFIG_CONFEDERATION)) {
                for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
                        if (peer->as == as) {
-                               (void)peer_sort(peer);
                                peer->local_as = bgp->confed_id;
+                               (void)peer_sort(peer);
                                if (BGP_IS_VALID_STATE_FOR_NOTIF(
                                            peer->status)) {
                                        peer->last_reset =
index 7679a377eb5fc5dffc30abdf05b8c8a136353fec..4a64d8f949ed48aada9902a597d7033f8b609b3e 100644 (file)
@@ -617,6 +617,10 @@ Terminal Mode Commands
    usage is printed sequentially. You can specify the daemon's name to print
    only its memory usage.
 
+.. clicmd:: show motd
+
+   Show current motd banner.
+
 .. clicmd:: show history
 
    Dump the vtysh cli history.
index 44a56f2fcab9cae84bf9799915f5e41641f53f6d..ef3aebeafa08206bc6afec5646046233cdcd78c0 100644 (file)
@@ -393,6 +393,11 @@ All interface configuration commands are documented below.
    higher priority to take over Master status from the existing Master. Enabled
    by default.
 
+.. clicmd:: vrrp (1-255) checksum-with-ipv4-pseudoheader
+
+   Specify whether VRRPv3 checksum should involve IPv4 pseudoheader. This
+   command should not affect VRRPv2 and IPv6. Enabled by default.
+
 .. clicmd:: vrrp (1-255) priority (1-254)
 
    Set the router priority. The router with the highest priority is elected as
@@ -448,7 +453,7 @@ Show commands, global defaults and debugging configuration commands.
    zebra
       Logs communications with Zebra.
 
-.. clicmd:: vrrp default <advertisement-interval (1-4096)|preempt|priority (1-254)|shutdown>
+.. clicmd:: vrrp default <advertisement-interval (1-4096)|preempt|priority (1-254)|checksum-with-ipv4-pseudoheader|shutdown>
 
    Configure defaults for new VRRP routers. These values will not affect
    already configured VRRP routers, but will be applied to newly configured
@@ -550,3 +555,19 @@ feature instead, explained `here
 <https://www.virtuallyghetto.com/2018/04/native-mac-learning-in-vsphere-6-7-removes-the-need-for-promiscuous-mode-for-nested-esxi.html>`_.
 
 Issue reference: https://github.com/FRRouting/frr/issues/5386
+
+
+My router cannot interoperate with branded routers / L3 switches
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+FRR includes a pseudoheader when calculating VRRPv3 checksums by default,
+regardless of whether it's IPv4 or IPv6.
+
+Some vendors have different interpretations of `VRRPv3 RFC 5798 #5.2.8
+<https://www.rfc-editor.org/rfc/rfc5798.html#section-5.2.8>`_. In such cases,
+their checksums are calculated with a pseudoheader only when it comes to IPv6.
+
+You need to disable ``checksum-with-ipv4-pseudoheader`` so that FRR computes and
+accepts such checksums.
+
+Issue reference: https://github.com/FRRouting/frr/issues/9951
index 1b5c0e90fb6130b61b8efc3f55ef78cae50dff88..35d2bf21c97de6295a589bbf9bf246549598a5b8 100644 (file)
@@ -208,7 +208,6 @@ ldpe_shutdown(void)
        iev_main_sync->ibuf.fd = -1;
 
        control_cleanup(ctl_sock_path);
-       config_clear(leconf);
 
 #ifdef __OpenBSD__
        if (sysdep.no_pfkey == 0) {
@@ -231,6 +230,7 @@ ldpe_shutdown(void)
                adj_del(adj, S_SHUTDOWN);
        }
 
+       config_clear(leconf);
        /* clean up */
        if (iev_lde)
                free(iev_lde);
index 76568071ef842bc7c6d97f06f7b9e50593478153..70c0c18141696d3431a89b573a0641001e6c7fc5 100644 (file)
--- a/lib/if.c
+++ b/lib/if.c
@@ -38,6 +38,7 @@
 #include "lib/if_clippy.c"
 
 DEFINE_MTYPE_STATIC(LIB, IF, "Interface");
+DEFINE_MTYPE_STATIC(LIB, IFDESC, "Intf Desc");
 DEFINE_MTYPE_STATIC(LIB, CONNECTED, "Connected");
 DEFINE_MTYPE_STATIC(LIB, NBR_CONNECTED, "Neighbor Connected");
 DEFINE_MTYPE(LIB, CONNECTED_LABEL, "Connected interface label");
@@ -288,7 +289,7 @@ void if_delete(struct interface **ifp)
 
        if_link_params_free(ptr);
 
-       XFREE(MTYPE_TMP, ptr->desc);
+       XFREE(MTYPE_IFDESC, ptr->desc);
 
        XFREE(MTYPE_IF, ptr);
        *ifp = NULL;
@@ -1612,9 +1613,9 @@ static int lib_interface_description_modify(struct nb_cb_modify_args *args)
                return NB_OK;
 
        ifp = nb_running_get_entry(args->dnode, NULL, true);
-       XFREE(MTYPE_TMP, ifp->desc);
+       XFREE(MTYPE_IFDESC, ifp->desc);
        description = yang_dnode_get_string(args->dnode, NULL);
-       ifp->desc = XSTRDUP(MTYPE_TMP, description);
+       ifp->desc = XSTRDUP(MTYPE_IFDESC, description);
 
        return NB_OK;
 }
@@ -1627,7 +1628,7 @@ static int lib_interface_description_destroy(struct nb_cb_destroy_args *args)
                return NB_OK;
 
        ifp = nb_running_get_entry(args->dnode, NULL, true);
-       XFREE(MTYPE_TMP, ifp->desc);
+       XFREE(MTYPE_IFDESC, ifp->desc);
 
        return NB_OK;
 }
index 2792820a542a81419cc46e482afe2f531d9c1072..55ac7c88a5a6e38377ebb51e1e6314e79436794d 100644 (file)
@@ -573,7 +573,7 @@ void ospf6_lsa_show_dump(struct vty *vty, struct ospf6_lsa *lsa,
                json = json_object_new_object();
                size_t header_str_sz = (2 * (end - start)) + 1;
 
-               header_str = XMALLOC(MTYPE_TMP, header_str_sz);
+               header_str = XMALLOC(MTYPE_OSPF6_LSA_HEADER, header_str_sz);
 
                inet_ntop(AF_INET, &lsa->header->id, id, sizeof(id));
                inet_ntop(AF_INET, &lsa->header->adv_router, adv_router,
@@ -586,7 +586,7 @@ void ospf6_lsa_show_dump(struct vty *vty, struct ospf6_lsa *lsa,
                json_object_string_add(json, "header", header_str);
                json_object_array_add(json_array, json);
 
-               XFREE(MTYPE_TMP, header_str);
+               XFREE(MTYPE_OSPF6_LSA_HEADER, header_str);
        } else {
                vty_out(vty, "\n%s:\n", lsa->name);
 
index 05c5e7789d3ab3d5793fb562ab1283c3270ed2c0..4982cd885e6ac8c910cedb12317cbb5c65cd59c0 100644 (file)
 
 #include "ospf_apiclient.h"
 
-/* *sigh* ... can't find a better way to hammer this into automake */
-#include "ospfd/ospf_dump_api.c"
-#include "ospfd/ospf_api.c"
-
 XREF_SETUP();
 
 DEFINE_MGROUP(OSPFCLIENT, "libospfapiclient");
index b8c82c0bcfcf6599c2227224cfc7200d29fdb66c..289ddd009d0f8bbd5b6ab3bdc27d996f37460d8a 100644 (file)
@@ -27,6 +27,7 @@ endif
 
 ospfclient_ospfclient_LDADD = \
        ospfclient/libfrrospfapiclient.la \
+       ospfd/libfrrospfclient.a \
        $(LIBCAP) \
        # end
 
index 0c2ee0c4f8a934f8303dfef7211c3c9aef672207..6fd1c82c2447ab2ea406df295fb2231d271e8520 100644 (file)
 #include "ospfd/ospf_ase.h"
 #include "ospfd/ospf_zebra.h"
 #include "ospfd/ospf_errors.h"
+#include "ospfd/ospf_memory.h"
 
 #include "ospfd/ospf_api.h"
 #include "ospfd/ospf_apiserver.h"
 
+DEFINE_MTYPE_STATIC(OSPFD, APISERVER, "API Server");
+DEFINE_MTYPE_STATIC(OSPFD, APISERVER_MSGFILTER, "API Server Message Filter");
+
 /* This is an implementation of an API to the OSPF daemon that allows
  * external applications to access the OSPF daemon through socket
  * connections. The application can use this API to inject its own
@@ -245,9 +249,9 @@ static int ospf_apiserver_del_lsa_hook(struct ospf_lsa *lsa)
 struct ospf_apiserver *ospf_apiserver_new(int fd_sync, int fd_async)
 {
        struct ospf_apiserver *new =
-               XMALLOC(MTYPE_OSPF_APISERVER, sizeof(struct ospf_apiserver));
+               XMALLOC(MTYPE_APISERVER, sizeof(struct ospf_apiserver));
 
-       new->filter = XMALLOC(MTYPE_OSPF_APISERVER_MSGFILTER,
+       new->filter = XMALLOC(MTYPE_APISERVER_MSGFILTER,
                              sizeof(struct lsa_filter_type));
 
        new->fd_sync = fd_sync;
@@ -360,7 +364,7 @@ void ospf_apiserver_free(struct ospf_apiserver *apiserv)
                           (void *)apiserv, apiserver_list->count);
 
        /* And free instance. */
-       XFREE(MTYPE_OSPF_APISERVER, apiserv);
+       XFREE(MTYPE_APISERVER, apiserv);
 }
 
 void ospf_apiserver_read(struct thread *thread)
@@ -862,8 +866,8 @@ int ospf_apiserver_register_opaque_type(struct ospf_apiserver *apiserv,
           connection shuts down, we can flush all LSAs of this opaque
           type. */
 
-       regtype = XCALLOC(MTYPE_OSPF_APISERVER,
-                         sizeof(struct registered_opaque_type));
+       regtype =
+               XCALLOC(MTYPE_APISERVER, sizeof(struct registered_opaque_type));
        regtype->lsa_type = lsa_type;
        regtype->opaque_type = opaque_type;
 
@@ -1155,12 +1159,12 @@ int ospf_apiserver_handle_register_event(struct ospf_apiserver *apiserv,
        seqnum = msg_get_seq(msg);
 
        /* Free existing filter in apiserv. */
-       XFREE(MTYPE_OSPF_APISERVER_MSGFILTER, apiserv->filter);
+       XFREE(MTYPE_APISERVER_MSGFILTER, apiserv->filter);
        /* Alloc new space for filter. */
        size = ntohs(msg->hdr.msglen);
        if (size < OSPF_MAX_LSA_SIZE) {
 
-               apiserv->filter = XMALLOC(MTYPE_OSPF_APISERVER_MSGFILTER, size);
+               apiserv->filter = XMALLOC(MTYPE_APISERVER_MSGFILTER, size);
 
                /* copy it over. */
                memcpy(apiserv->filter, &rmsg->filter, size);
@@ -1365,8 +1369,7 @@ int ospf_apiserver_handle_sync_reachable(struct ospf_apiserver *apiserv,
                goto out;
 
        /* send all adds based on current reachable routers */
-       a = abuf = XCALLOC(MTYPE_OSPF_APISERVER,
-                          sizeof(struct in_addr) * rt->count);
+       a = abuf = XCALLOC(MTYPE_APISERVER, sizeof(struct in_addr) * rt->count);
        for (struct route_node *rn = route_top(rt); rn; rn = route_next(rn))
                if (listhead((struct list *)rn->info))
                        *a++ = rn->p.u.prefix4;
@@ -1385,7 +1388,7 @@ int ospf_apiserver_handle_sync_reachable(struct ospf_apiserver *apiserv,
                rc = ospf_apiserver_send_msg(apiserv, amsg);
                msg_free(amsg);
        }
-       XFREE(MTYPE_OSPF_APISERVER, abuf);
+       XFREE(MTYPE_APISERVER, abuf);
 
 out:
        /* Send a reply back to client with return code */
@@ -2616,9 +2619,9 @@ void ospf_apiserver_notify_reachable(struct route_table *ort,
                return;
        }
        if (nrt && nrt->count)
-               a = abuf = XCALLOC(MTYPE_OSPF_APISERVER, insz * nrt->count);
+               a = abuf = XCALLOC(MTYPE_APISERVER, insz * nrt->count);
        if (ort && ort->count)
-               d = dbuf = XCALLOC(MTYPE_OSPF_APISERVER, insz * ort->count);
+               d = dbuf = XCALLOC(MTYPE_APISERVER, insz * ort->count);
 
        /* walk both tables */
        orn = ort ? route_top(ort) : NULL;
@@ -2683,9 +2686,9 @@ void ospf_apiserver_notify_reachable(struct route_table *ort,
                msg_free(msg);
        }
        if (abuf)
-               XFREE(MTYPE_OSPF_APISERVER, abuf);
+               XFREE(MTYPE_APISERVER, abuf);
        if (dbuf)
-               XFREE(MTYPE_OSPF_APISERVER, dbuf);
+               XFREE(MTYPE_APISERVER, dbuf);
 }
 
 
index e28202e46f9e51e9e2c23000e4b258e750844b43..0a6b7319a04428f102aba1b2f4a861800314b461 100644 (file)
 #include "ospf_api.h"
 #include "ospf_lsdb.h"
 
-/* MTYPE definition is not reflected to "memory.h". */
-#define MTYPE_OSPF_APISERVER MTYPE_TMP
-#define MTYPE_OSPF_APISERVER_MSGFILTER MTYPE_TMP
-
 /* List of opaque types that application registered */
 struct registered_opaque_type {
        uint8_t lsa_type;
index 9727c7039c5ee0bf9c3c95000a5629de9c9f0ecc..f1b876cfbe338c3da7d96ca071778bb9d7c8233e 100644 (file)
@@ -50,6 +50,8 @@
 #include "ospfd/ospf_route.h"
 #include "ospfd/ospf_zebra.h"
 
+DEFINE_MTYPE_STATIC(OSPFD, SNMP, "OSPF SNMP");
+
 /* OSPF2-MIB. */
 #define OSPF2MIB 1,3,6,1,2,1,14
 
@@ -1321,12 +1323,12 @@ struct ospf_snmp_if {
 
 static struct ospf_snmp_if *ospf_snmp_if_new(void)
 {
-       return XCALLOC(MTYPE_TMP, sizeof(struct ospf_snmp_if));
+       return XCALLOC(MTYPE_SNMP, sizeof(struct ospf_snmp_if));
 }
 
 static void ospf_snmp_if_free(struct ospf_snmp_if *osif)
 {
-       XFREE(MTYPE_TMP, osif);
+       XFREE(MTYPE_SNMP, osif);
 }
 
 static int ospf_snmp_if_delete(struct interface *ifp)
index b67f942883d096f87af2e3a6081d08247a4da48f..e45f617dfa63a59e0f5011ea5a556803c80a7270 100644 (file)
@@ -4,6 +4,7 @@
 
 if OSPFD
 noinst_LIBRARIES += ospfd/libfrrospf.a
+noinst_LIBRARIES += ospfd/libfrrospfclient.a
 sbin_PROGRAMS += ospfd/ospfd
 vtysh_daemons += ospfd
 if SNMP
@@ -12,6 +13,11 @@ endif
 man8 += $(MANBUILD)/frr-ospfd.8
 endif
 
+ospfd_libfrrospfclient_a_SOURCES = \
+       ospfd/ospf_api.c \
+       ospfd/ospf_dump_api.c \
+       #end
+
 ospfd_libfrrospf_a_SOURCES = \
        ospfd/ospf_abr.c \
        ospfd/ospf_api.c \
@@ -104,7 +110,7 @@ noinst_HEADERS += \
        ospfd/ospf_zebra.h \
        # end
 
-ospfd_ospfd_LDADD = ospfd/libfrrospf.a lib/libfrr.la $(LIBCAP) $(LIBM)
+ospfd_ospfd_LDADD = ospfd/libfrrospf.a ospfd/libfrrospfclient.a lib/libfrr.la $(LIBCAP) $(LIBM)
 ospfd_ospfd_SOURCES = ospfd/ospf_main.c
 
 ospfd_ospfd_snmp_la_SOURCES = ospfd/ospf_snmp.c
diff --git a/tests/topotests/bgp_confed1/__init__.py b/tests/topotests/bgp_confed1/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/topotests/bgp_confed1/r1/bgp_ipv4_unicast.json b/tests/topotests/bgp_confed1/r1/bgp_ipv4_unicast.json
new file mode 100644 (file)
index 0000000..d3988eb
--- /dev/null
@@ -0,0 +1,63 @@
+{
+ "vrfId":0,
+ "vrfName":"default",
+ "routerId":"203.0.113.1",
+ "defaultLocPrf":100,
+ "localAS":100,
+ "routes":{"203.0.113.0/28":[
+  {
+    "network":"203.0.113.0\/28",
+    "peerId":"(unspec)",
+    "path":"",
+    "origin":"IGP",
+    "nexthops":[
+      {
+        "ip":"0.0.0.0",
+        "afi":"ipv4",
+        "used":true
+      }
+    ]
+  }
+],"203.0.113.16/28":[
+  {
+    "network":"203.0.113.16\/28",
+    "peerId":"192.0.2.2",
+    "path":"300",
+    "origin":"IGP",
+    "nexthops":[
+      {
+        "ip":"192.0.2.2",
+        "afi":"ipv4",
+        "used":true
+      }
+    ]
+  }
+],"203.0.113.32/28":[
+  {
+    "network":"203.0.113.32\/28",
+    "peerId":"192.0.2.2",
+    "path":"300",
+    "origin":"IGP",
+    "nexthops":[
+      {
+        "ip":"192.0.2.2",
+        "afi":"ipv4",
+        "used":true
+      }
+    ]
+  }
+],"203.0.113.48/28":[
+  {
+    "network":"203.0.113.48\/28",
+    "peerId":"192.0.2.2",
+    "path":"300 400",
+    "origin":"IGP",
+    "nexthops":[
+      {
+        "ip":"192.0.2.2",
+        "afi":"ipv4",
+        "used":true
+      }
+    ]
+  }
+] }  }
diff --git a/tests/topotests/bgp_confed1/r1/bgp_summary.json b/tests/topotests/bgp_confed1/r1/bgp_summary.json
new file mode 100644 (file)
index 0000000..f999021
--- /dev/null
@@ -0,0 +1,13 @@
+{
+    "ipv4Unicast":{
+      "routerId":"203.0.113.1",
+      "as":100,
+      "peers":{
+        "192.0.2.2":{
+          "remoteAs": 300,
+          "state": "Established",
+          "peerState":"OK"  
+      }
+    }
+  }
+}
diff --git a/tests/topotests/bgp_confed1/r1/bgpd.conf b/tests/topotests/bgp_confed1/r1/bgpd.conf
new file mode 100644 (file)
index 0000000..8413ef7
--- /dev/null
@@ -0,0 +1,13 @@
+debug bgp neighbor-events
+debug bgp nht
+debug bgp updates in
+debug bgp updates out
+!
+router bgp 100
+ no bgp ebgp-requires-policy
+!
+ neighbor 192.0.2.2 remote-as 300
+ address-family ipv4 unicast
+  network 203.0.113.0/28
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_confed1/r1/isisd.conf b/tests/topotests/bgp_confed1/r1/isisd.conf
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/topotests/bgp_confed1/r1/zebra.conf b/tests/topotests/bgp_confed1/r1/zebra.conf
new file mode 100644 (file)
index 0000000..5f76e74
--- /dev/null
@@ -0,0 +1,6 @@
+interface r1-eth0
+ ip address 192.0.2.1/28
+!
+interface lo
+ ip address 203.0.113.1/28
+!
diff --git a/tests/topotests/bgp_confed1/r2/bgp_ipv4_unicast.json b/tests/topotests/bgp_confed1/r2/bgp_ipv4_unicast.json
new file mode 100644 (file)
index 0000000..b4a0946
--- /dev/null
@@ -0,0 +1,63 @@
+{
+ "vrfId":0,
+ "vrfName":"default",
+ "routerId":"203.0.113.17",
+ "defaultLocPrf":100,
+ "localAS":200,
+ "routes":{"203.0.113.0/28": [
+  {
+    "network":"203.0.113.0\/28",
+    "peerId":"192.0.2.1",
+    "path":"100",
+    "origin":"IGP",
+    "nexthops":[
+      {
+        "ip":"192.0.2.1",
+        "afi":"ipv4",
+        "used":true
+      }
+    ]
+  }
+],"203.0.113.16/28":[
+  {
+    "network":"203.0.113.16\/28",
+    "peerId":"(unspec)",
+    "path":"",
+    "origin":"IGP",
+    "nexthops":[
+      {
+        "ip":"0.0.0.0",
+        "afi":"ipv4",
+        "used":true
+      }
+    ]
+  }
+],"203.0.113.32/28":[
+  {
+    "network":"203.0.113.32\/28",
+    "peerId":"192.0.2.18",
+    "path":"(300)",
+    "origin":"IGP",
+    "nexthops":[
+      {
+        "ip":"192.0.2.18",
+        "afi":"ipv4",
+        "used":true
+      }
+    ]
+  }
+],"203.0.113.48/28":[
+  {
+    "network":"203.0.113.48\/28",
+    "peerId":"192.0.2.18",
+    "path":"(300) 400",
+    "origin":"IGP",
+    "nexthops":[
+      {
+        "ip":"192.0.2.50",
+        "afi":"ipv4",
+        "used":true
+      }
+    ]
+  }
+] } }
diff --git a/tests/topotests/bgp_confed1/r2/bgp_summary.json b/tests/topotests/bgp_confed1/r2/bgp_summary.json
new file mode 100644 (file)
index 0000000..c2690a1
--- /dev/null
@@ -0,0 +1,18 @@
+{
+    "ipv4Unicast":{
+    "routerId":"203.0.113.17",
+    "as":200,
+    "peers":{
+      "192.0.2.1":{
+        "remoteAs":100,
+         "state":"Established",
+         "peerState":"OK"
+      },
+      "192.0.2.18":{
+        "remoteAs":300,
+         "state":"Established",
+         "peerState":"OK"
+      }
+    }
+  }
+}
diff --git a/tests/topotests/bgp_confed1/r2/bgpd.conf b/tests/topotests/bgp_confed1/r2/bgpd.conf
new file mode 100644 (file)
index 0000000..9f6a985
--- /dev/null
@@ -0,0 +1,18 @@
+debug bgp neighbor-events
+debug bgp nht
+debug bgp updates in
+debug bgp updates out
+!
+router bgp 200
+ no bgp ebgp-requires-policy
+ bgp confederation identifier 300
+ bgp confederation peers 300
+ neighbor 192.0.2.1 remote-as 100
+ neighbor 192.0.2.18 remote-as 300
+ !
+ address-family ipv4 unicast
+  network 203.0.113.16/28
+  neighbor 192.0.2.18 default-originate
+ exit-address-family
+!
+
diff --git a/tests/topotests/bgp_confed1/r2/isisd.conf b/tests/topotests/bgp_confed1/r2/isisd.conf
new file mode 100644 (file)
index 0000000..135bb00
--- /dev/null
@@ -0,0 +1,8 @@
+interface r2-eth1
+ ip router isis 1
+ isis circuit-type level-2-only
+
+router isis 1
+ is-type level-2-only
+ net 49.0001.0002.0002.0002.00
+ redistribute ipv4 connected level-2
diff --git a/tests/topotests/bgp_confed1/r2/zebra.conf b/tests/topotests/bgp_confed1/r2/zebra.conf
new file mode 100644 (file)
index 0000000..85ebe9e
--- /dev/null
@@ -0,0 +1,9 @@
+interface r2-eth0
+ ip address 192.0.2.2/28
+!
+interface r2-eth1
+ ip address 192.0.2.17/28
+!
+interface lo
+ ip address 203.0.113.17/28
+!
diff --git a/tests/topotests/bgp_confed1/r3/bgp_ipv4_unicast.json b/tests/topotests/bgp_confed1/r3/bgp_ipv4_unicast.json
new file mode 100644 (file)
index 0000000..a263a9f
--- /dev/null
@@ -0,0 +1,77 @@
+{
+ "vrfId":0,
+ "vrfName":"default",
+ "routerId":"203.0.113.33",
+ "defaultLocPrf":100,
+ "localAS":300,
+ "routes":{"0.0.0.0/0":[
+  {
+    "network":"0.0.0.0\/0",
+    "peerId":"192.0.2.17",
+    "path":"(200)",
+    "origin":"IGP",
+    "nexthops":[
+      {
+        "ip":"192.0.2.17",
+        "afi":"ipv4",
+        "used":true
+      }
+    ]
+  }
+],"203.0.113.0/28":[
+  {
+    "network":"203.0.113.0\/28",
+    "peerId":"192.0.2.17",
+    "path":"(200) 100",
+    "origin":"IGP",
+    "nexthops":[
+      {
+        "ip":"192.0.2.1",
+        "afi":"ipv4",
+        "used":true
+      }
+    ]
+  }
+],"203.0.113.16/28":[
+  {
+    "network":"203.0.113.16\/28",
+    "peerId":"192.0.2.17",
+    "path":"(200)",
+    "origin":"IGP",
+    "nexthops":[
+      {
+        "ip":"192.0.2.17",
+        "afi":"ipv4",
+        "used":true
+      }
+    ]
+  }
+],"203.0.113.32/28":[
+  {
+    "network":"203.0.113.32\/28",
+    "peerId":"(unspec)",
+    "path":"",
+    "origin":"IGP",
+    "nexthops":[
+      {
+        "ip":"0.0.0.0",
+        "afi":"ipv4",
+        "used":true
+      }
+    ]
+  }
+],"203.0.113.48/28":[
+  {
+    "network":"203.0.113.48\/28",
+    "peerId":"192.0.2.50",
+    "path":"400",
+    "origin":"IGP",
+    "nexthops":[
+      {
+        "ip":"192.0.2.50",
+        "afi":"ipv4",
+        "used":true
+      }
+    ]
+  }
+] } }
diff --git a/tests/topotests/bgp_confed1/r3/bgp_summary.json b/tests/topotests/bgp_confed1/r3/bgp_summary.json
new file mode 100644 (file)
index 0000000..0cc0d53
--- /dev/null
@@ -0,0 +1,18 @@
+{
+    "ipv4Unicast":{
+    "routerId":"203.0.113.33",
+    "as":300,
+    "peers":{
+      "192.0.2.17":{
+        "remoteAs":200,
+         "state":"Established",
+         "peerState":"OK"
+      },
+      "192.0.2.50":{
+        "remoteAs":400,
+         "state":"Established",
+         "peerState":"OK"
+      }
+    }
+  }
+}
diff --git a/tests/topotests/bgp_confed1/r3/bgpd.conf b/tests/topotests/bgp_confed1/r3/bgpd.conf
new file mode 100644 (file)
index 0000000..3a018a4
--- /dev/null
@@ -0,0 +1,17 @@
+debug bgp neighbor-events
+debug bgp nht
+debug bgp updates in
+debug bgp updates out
+!
+router bgp 300
+ no bgp ebgp-requires-policy
+ bgp confederation identifier 300
+ bgp confederation peers 200
+ neighbor 192.0.2.17 remote-as 200
+ neighbor 192.0.2.50 remote-as 400
+!
+ address-family ipv4 unicast
+  network 203.0.113.32/28
+ exit-address-family
+!
+
diff --git a/tests/topotests/bgp_confed1/r3/isisd.conf b/tests/topotests/bgp_confed1/r3/isisd.conf
new file mode 100644 (file)
index 0000000..a0b1200
--- /dev/null
@@ -0,0 +1,8 @@
+interface r3-eth1
+ ip router isis 1
+ isis circuit-type level-2-only
+
+router isis 1
+ is-type level-2-only
+ net 49.0001.0003.0003.0003.00
+ redistribute ipv4 connected level-2
diff --git a/tests/topotests/bgp_confed1/r3/zebra.conf b/tests/topotests/bgp_confed1/r3/zebra.conf
new file mode 100644 (file)
index 0000000..555c8ed
--- /dev/null
@@ -0,0 +1,10 @@
+!
+interface r3-eth0
+ ip address 192.0.2.49/28
+!
+interface r3-eth1
+ ip address 192.0.2.18/28
+!
+interface lo
+ ip address 203.0.113.33/28
+!
diff --git a/tests/topotests/bgp_confed1/r4/bgp_ipv4_unicast.json b/tests/topotests/bgp_confed1/r4/bgp_ipv4_unicast.json
new file mode 100644 (file)
index 0000000..8a1f0b6
--- /dev/null
@@ -0,0 +1,77 @@
+{
+ "vrfId":0,
+ "vrfName":"default",
+ "routerId":"203.0.113.49",
+ "defaultLocPrf":100,
+ "localAS":400,
+ "routes":{"0.0.0.0/0":[
+  {
+    "network":"0.0.0.0\/0",
+    "peerId":"192.0.2.49",
+    "path":"300",
+    "origin":"IGP",
+    "nexthops":[
+      {
+        "ip":"192.0.2.49",
+        "afi":"ipv4",
+        "used":true
+      }
+    ]
+  }
+],"203.0.113.0/28":[
+  {
+    "network":"203.0.113.0\/28",
+    "peerId":"192.0.2.49",
+    "path":"300 100",
+    "origin":"IGP",
+    "nexthops":[
+      {
+        "ip":"192.0.2.49",
+        "afi":"ipv4",
+        "used":true
+      }
+    ]
+  }
+],"203.0.113.16/28":[
+  {
+    "network":"203.0.113.16\/28",
+    "peerId":"192.0.2.49",
+    "path":"300",
+    "origin":"IGP",
+    "nexthops":[
+      {
+        "ip":"192.0.2.49",
+        "afi":"ipv4",
+        "used":true
+      }
+    ]
+  }
+],"203.0.113.32/28":[
+  {
+    "network":"203.0.113.32\/28",
+    "peerId":"192.0.2.49",
+    "path":"300",
+    "origin":"IGP",
+    "nexthops":[
+      {
+        "ip":"192.0.2.49",
+        "afi":"ipv4",
+        "used":true
+      }
+    ]
+  }
+],"203.0.113.48/28":[
+  {
+    "network":"203.0.113.48\/28",
+    "peerId":"(unspec)",
+    "path":"",
+    "origin":"IGP",
+    "nexthops":[
+      {
+        "ip":"0.0.0.0",
+        "afi":"ipv4",
+        "used":true
+      }
+    ]
+  }
+] } }
diff --git a/tests/topotests/bgp_confed1/r4/bgp_summary.json b/tests/topotests/bgp_confed1/r4/bgp_summary.json
new file mode 100644 (file)
index 0000000..11a0c45
--- /dev/null
@@ -0,0 +1,13 @@
+{
+    "ipv4Unicast":{
+    "routerId":"203.0.113.49", 
+    "as":400,
+    "peers":{
+      "192.0.2.49":{
+        "remoteAs":300,
+         "state":"Established",
+         "peerState":"OK"
+      }
+    }
+  }
+}
diff --git a/tests/topotests/bgp_confed1/r4/bgpd.conf b/tests/topotests/bgp_confed1/r4/bgpd.conf
new file mode 100644 (file)
index 0000000..134f221
--- /dev/null
@@ -0,0 +1,14 @@
+debug bgp neighbor-events
+debug bgp nht
+debug bgp updates in
+debug bgp updates out
+!
+router bgp 400
+ no bgp ebgp-requires-policy
+ bgp disable-ebgp-connected-route-check
+!
+ neighbor 192.0.2.49 remote-as 300
+ address-family ipv4 unicast
+  network 203.0.113.48/28
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_confed1/r4/isisd.conf b/tests/topotests/bgp_confed1/r4/isisd.conf
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/topotests/bgp_confed1/r4/zebra.conf b/tests/topotests/bgp_confed1/r4/zebra.conf
new file mode 100644 (file)
index 0000000..28c448e
--- /dev/null
@@ -0,0 +1,6 @@
+interface r4-eth0
+ ip address 192.0.2.50/28
+!
+interface lo
+ ip address 203.0.113.49/28
+!
diff --git a/tests/topotests/bgp_confed1/test_bgp_confed1.py b/tests/topotests/bgp_confed1/test_bgp_confed1.py
new file mode 100644 (file)
index 0000000..7a35a10
--- /dev/null
@@ -0,0 +1,129 @@
+#!/usr/bin/env python
+
+#
+# test_bgp_confed1.py
+#
+# Copyright 2022 6WIND S.A.
+#
+# Permission to use, copy, modify, and/or 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 6WIND DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL 6WIND 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.
+#
+
+"""
+test_bgp_confed1.py: Test the FRR BGP confederations with AS member
+same as confederation Id, verify BGP prefixes and path distribution  
+"""
+
+import os
+import sys
+import json
+from functools import partial
+import pytest
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.topolog import logger
+
+pytestmark = [pytest.mark.bgpd]
+
+
+def build_topo(tgen):
+    for routern in range(1, 5):  
+        tgen.add_router("r{}".format(routern))
+
+    switch = tgen.add_switch("s1")
+    switch.add_link(tgen.gears["r1"])
+    switch.add_link(tgen.gears["r2"])
+
+    switch = tgen.add_switch("s3")
+    switch.add_link(tgen.gears["r3"])
+    switch.add_link(tgen.gears["r4"])
+
+    switch = tgen.add_switch("s2")
+    switch.add_link(tgen.gears["r2"])
+    switch.add_link(tgen.gears["r3"])
+
+def setup_module(mod):
+
+    tgen = Topogen(build_topo, mod.__name__)
+    tgen.start_topology()
+
+    router_list = tgen.routers()
+    for rname, router in router_list.items():
+        router.load_config(
+            TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
+        )
+        router.load_config(
+            TopoRouter.RD_ISIS, os.path.join(CWD, "{}/isisd.conf".format(rname))
+        )
+        router.load_config(
+            TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
+        )
+
+    # Initialize all routers.
+    tgen.start_router()
+
+def teardown_module(_mod):
+    "Teardown the pytest environment"
+    tgen = get_topogen()
+    tgen.stop_topology()
+
+
+def test_bgp_convergence():
+    "Assert that BGP is converging."
+    tgen = get_topogen()
+    if tgen.routers_have_failure():
+        pytest.skip(tgen.errors)
+
+    logger.info("waiting for bgp peers to go up")
+
+    for router in tgen.routers().values():
+        ref_file = "{}/{}/bgp_summary.json".format(CWD, router.name)
+        expected = json.loads(open(ref_file).read())
+        test_func = partial(
+            topotest.router_json_cmp, router, "show ip bgp summary json", expected
+        )
+        _, res = topotest.run_and_expect(test_func, None, count=125, wait=2.0)
+        assertmsg = "{}: bgp did not converge".format(router.name)
+        assert res is None, assertmsg
+
+
+def test_bgp_confed_ipv4_unicast():
+    "Assert that BGP is exchanging BGP route."
+    tgen = get_topogen()
+    if tgen.routers_have_failure():
+        pytest.skip(tgen.errors)
+
+    logger.info("waiting for bgp peers exchanging UPDATES")
+
+    for router in tgen.routers().values():
+        ref_file = "{}/{}/bgp_ipv4_unicast.json".format(CWD, router.name)
+        expected = json.loads(open(ref_file).read())
+        test_func = partial(
+            topotest.router_json_cmp, router, "show bgp ipv4 unicast json", expected
+        )
+        _, res = topotest.run_and_expect(test_func, None, count=40, wait=2.5)
+        assertmsg = "{}: BGP UPDATE exchange failure".format(router.name)
+        assert res is None, assertmsg
+
+
+if __name__ == "__main__":
+    args = ["-s"] + sys.argv[1:]
+    sys.exit(pytest.main(args))
index 4a0356411f6594cf86d929cc41859aa5eb9e34bd..e1bb40c28d40e7108842993f4b05b226b5564a35 100644 (file)
@@ -647,6 +647,8 @@ struct vrrp_vrouter *vrrp_vrouter_create(struct interface *ifp, uint8_t vrid,
        vr->priority = vd.priority;
        vr->preempt_mode = vd.preempt_mode;
        vr->accept_mode = vd.accept_mode;
+       vr->checksum_with_ipv4_pseudoheader =
+               vd.checksum_with_ipv4_pseudoheader;
        vr->shutdown = vd.shutdown;
 
        vr->v4 = vrrp_router_create(vr, AF_INET);
@@ -789,7 +791,8 @@ static void vrrp_send_advertisement(struct vrrp_router *r)
 
        pktsz = vrrp_pkt_adver_build(&pkt, &r->src, r->vr->version, r->vr->vrid,
                                     r->priority, r->vr->advertisement_interval,
-                                    r->addrs->count, (struct ipaddr **)&addrs);
+                                    r->addrs->count, (struct ipaddr **)&addrs,
+                                    r->vr->checksum_with_ipv4_pseudoheader);
 
        if (DEBUG_MODE_CHECK(&vrrp_dbg_pkt, DEBUG_MODE_ALL))
                zlog_hexdump(pkt, (size_t)pktsz);
@@ -1027,8 +1030,10 @@ static void vrrp_read(struct thread *thread)
                zlog_hexdump(r->ibuf, nbytes);
        }
 
-       pktsize = vrrp_pkt_parse_datagram(r->family, r->vr->version, &m, nbytes,
-                                         &src, &pkt, errbuf, sizeof(errbuf));
+       pktsize = vrrp_pkt_parse_datagram(
+               r->family, r->vr->version,
+               r->vr->checksum_with_ipv4_pseudoheader, &m, nbytes, &src, &pkt,
+               errbuf, sizeof(errbuf));
 
        if (pktsize < 0)
                DEBUGD(&vrrp_dbg_pkt,
@@ -2347,6 +2352,12 @@ int vrrp_config_write_global(struct vty *vty)
                vty_out(vty, "%svrrp default accept\n",
                        !vd.accept_mode ? "no " : "");
 
+       if (vd.checksum_with_ipv4_pseudoheader !=
+                   VRRP_DEFAULT_CHECKSUM_WITH_IPV4_PSEUDOHEADER &&
+           ++writes)
+               vty_out(vty, "%svrrp default checksum-with-ipv4-pseudoheader\n",
+                       !vd.checksum_with_ipv4_pseudoheader ? "no " : "");
+
        if (vd.shutdown != VRRP_DEFAULT_SHUTDOWN && ++writes)
                vty_out(vty, "%svrrp default shutdown\n",
                        !vd.shutdown ? "no " : "");
@@ -2387,6 +2398,8 @@ void vrrp_init(void)
        vd.preempt_mode = yang_get_default_bool("%s/preempt", VRRP_XPATH_FULL);
        vd.accept_mode =
                yang_get_default_bool("%s/accept-mode", VRRP_XPATH_FULL);
+       vd.checksum_with_ipv4_pseudoheader = yang_get_default_bool(
+               "%s/checksum-with-ipv4-pseudoheader", VRRP_XPATH_FULL);
        vd.shutdown = VRRP_DEFAULT_SHUTDOWN;
 
        vrrp_autoconfig_version = 3;
index c181c2159bf10aaa032d9095d230b6d1294981f7..b3141ef318492471d313c6b020bccfea3a992259 100644 (file)
@@ -53,6 +53,7 @@
 #define VRRP_DEFAULT_ADVINT 100
 #define VRRP_DEFAULT_PREEMPT true
 #define VRRP_DEFAULT_ACCEPT true
+#define VRRP_DEFAULT_CHECKSUM_WITH_IPV4_PSEUDOHEADER true
 #define VRRP_DEFAULT_SHUTDOWN false
 
 /* User compatibility constant */
@@ -70,6 +71,7 @@ struct vrrp_defaults {
        uint16_t advertisement_interval;
        bool preempt_mode;
        bool accept_mode;
+       bool checksum_with_ipv4_pseudoheader;
        bool shutdown;
 };
 
@@ -266,6 +268,14 @@ struct vrrp_vrouter {
         */
        bool accept_mode;
 
+       /*
+        * Indicates whether this router computes and accepts VRRPv3 checksums
+        * without pseudoheader, for device interoperability.
+        *
+        * This option should only affect IPv4 virtual routers.
+        */
+       bool checksum_with_ipv4_pseudoheader;
+
        struct vrrp_router *v4;
        struct vrrp_router *v6;
 };
index d25dc0a19780821036915837d1bd5ff1ae8e4f20..76d0ad3b1b082cdac7d4e0d0e15f6043e4955ce6 100644 (file)
@@ -602,6 +602,26 @@ lib_interface_vrrp_vrrp_group_shutdown_modify(struct nb_cb_modify_args *args)
        return NB_OK;
 }
 
+/*
+ * XPath: /frr-interface:lib/interface/frr-vrrpd:vrrp/vrrp-group/checksum-with-
+ *        ipv4-pseudoheader
+ */
+static int lib_interface_vrrp_vrrp_group_checksum_with_ipv4_pseudoheader_modify(
+       struct nb_cb_modify_args *args)
+{
+       if (args->event != NB_EV_APPLY)
+               return NB_OK;
+
+       struct vrrp_vrouter *vr;
+       bool checksum_with_ipv4_ph;
+
+       vr = nb_running_get_entry(args->dnode, NULL, true);
+       checksum_with_ipv4_ph = yang_dnode_get_bool(args->dnode, NULL);
+       vr->checksum_with_ipv4_pseudoheader = checksum_with_ipv4_ph;
+
+       return NB_OK;
+}
+
 /* clang-format off */
 const struct frr_yang_module_info frr_vrrpd_info = {
        .name = "frr-vrrpd",
@@ -643,6 +663,13 @@ const struct frr_yang_module_info frr_vrrpd_info = {
                                .modify = lib_interface_vrrp_vrrp_group_accept_mode_modify,
                        }
                },
+               {
+                       .xpath = "/frr-interface:lib/interface/frr-vrrpd:vrrp/vrrp-group/checksum-with-ipv4-pseudoheader",
+                       .cbs = {
+                               .modify = lib_interface_vrrp_vrrp_group_checksum_with_ipv4_pseudoheader_modify,
+                               .cli_show = cli_show_checksum_with_ipv4_pseudoheader,
+                       }
+               },
                {
                        .xpath = "/frr-interface:lib/interface/frr-vrrpd:vrrp/vrrp-group/advertisement-interval",
                        .cbs = {
index 991c030196e975e46469dfd691dbd7ae2fba7e3f..96a19da88cad016d1123ce6eeef45cb5564c8cb2 100644 (file)
@@ -71,7 +71,7 @@ static const char *const vrrp_packet_names[16] = {
  *    VRRP checksum in network byte order.
  */
 static uint16_t vrrp_pkt_checksum(struct vrrp_pkt *pkt, size_t pktsize,
-                                 struct ipaddr *src)
+                                 struct ipaddr *src, bool ipv4_ph)
 {
        uint16_t chksum;
        bool v6 = (src->ipa_type == IPADDR_V6);
@@ -89,13 +89,16 @@ static uint16_t vrrp_pkt_checksum(struct vrrp_pkt *pkt, size_t pktsize,
                ph.next_hdr = IPPROTO_VRRP;
                chksum = in_cksum_with_ph6(&ph, pkt, pktsize);
        } else if (!v6 && ((pkt->hdr.vertype >> 4) == 3)) {
-               struct ipv4_ph ph = {};
-
-               ph.src = src->ipaddr_v4;
-               inet_pton(AF_INET, VRRP_MCASTV4_GROUP_STR, &ph.dst);
-               ph.proto = IPPROTO_VRRP;
-               ph.len = htons(pktsize);
-               chksum = in_cksum_with_ph4(&ph, pkt, pktsize);
+               if (ipv4_ph) {
+                       struct ipv4_ph ph = {};
+
+                       ph.src = src->ipaddr_v4;
+                       inet_pton(AF_INET, VRRP_MCASTV4_GROUP_STR, &ph.dst);
+                       ph.proto = IPPROTO_VRRP;
+                       ph.len = htons(pktsize);
+                       chksum = in_cksum_with_ph4(&ph, pkt, pktsize);
+               } else
+                       chksum = in_cksum(pkt, pktsize);
        } else if (!v6 && ((pkt->hdr.vertype >> 4) == 2)) {
                chksum = in_cksum(pkt, pktsize);
        } else {
@@ -110,7 +113,7 @@ static uint16_t vrrp_pkt_checksum(struct vrrp_pkt *pkt, size_t pktsize,
 ssize_t vrrp_pkt_adver_build(struct vrrp_pkt **pkt, struct ipaddr *src,
                             uint8_t version, uint8_t vrid, uint8_t prio,
                             uint16_t max_adver_int, uint8_t numip,
-                            struct ipaddr **ips)
+                            struct ipaddr **ips, bool ipv4_ph)
 {
        bool v6 = false;
        size_t addrsz = 0;
@@ -147,7 +150,7 @@ ssize_t vrrp_pkt_adver_build(struct vrrp_pkt **pkt, struct ipaddr *src,
                aptr += addrsz;
        }
 
-       (*pkt)->hdr.chksum = vrrp_pkt_checksum(*pkt, pktsize, src);
+       (*pkt)->hdr.chksum = vrrp_pkt_checksum(*pkt, pktsize, src, ipv4_ph);
 
        return pktsize;
 }
@@ -188,10 +191,10 @@ size_t vrrp_pkt_adver_dump(char *buf, size_t buflen, struct vrrp_pkt *pkt)
        return rs;
 }
 
-ssize_t vrrp_pkt_parse_datagram(int family, int version, struct msghdr *m,
-                               size_t read, struct ipaddr *src,
-                               struct vrrp_pkt **pkt, char *errmsg,
-                               size_t errmsg_len)
+ssize_t vrrp_pkt_parse_datagram(int family, int version, bool ipv4_ph,
+                               struct msghdr *m, size_t read,
+                               struct ipaddr *src, struct vrrp_pkt **pkt,
+                               char *errmsg, size_t errmsg_len)
 {
        /* Source (MAC & IP), Dest (MAC & IP) TTL validation done by kernel */
        size_t addrsz = (family == AF_INET) ? sizeof(struct in_addr)
@@ -289,7 +292,7 @@ ssize_t vrrp_pkt_parse_datagram(int family, int version, struct msghdr *m,
        VRRP_PKT_VCHECK(pktver == version, "Bad version %u", pktver);
 
        /* Checksum check */
-       uint16_t chksum = vrrp_pkt_checksum(*pkt, pktsize, src);
+       uint16_t chksum = vrrp_pkt_checksum(*pkt, pktsize, src, ipv4_ph);
 
        VRRP_PKT_VCHECK((*pkt)->hdr.chksum == chksum,
                        "Bad VRRP checksum %hx; should be %hx",
index 082935f080d4628d10e4398df5128ed833883d85..eec709593e41d1a6df0de6c379d482b8ee57c447 100644 (file)
@@ -131,7 +131,7 @@ struct vrrp_pkt {
 ssize_t vrrp_pkt_adver_build(struct vrrp_pkt **pkt, struct ipaddr *src,
                             uint8_t version, uint8_t vrid, uint8_t prio,
                             uint16_t max_adver_int, uint8_t numip,
-                            struct ipaddr **ips);
+                            struct ipaddr **ips, bool ipv4_ph);
 
 /* free memory allocated by vrrp_pkt_adver_build's pkt arg */
 void vrrp_pkt_free(struct vrrp_pkt *pkt);
@@ -195,9 +195,9 @@ size_t vrrp_pkt_adver_dump(char *buf, size_t buflen, struct vrrp_pkt *pkt);
  * Returns:
  *    Size of VRRP packet, or -1 upon error
  */
-ssize_t vrrp_pkt_parse_datagram(int family, int version, struct msghdr *m,
-                               size_t read, struct ipaddr *src,
-                               struct vrrp_pkt **pkt, char *errmsg,
-                               size_t errmsg_len);
+ssize_t vrrp_pkt_parse_datagram(int family, int version, bool ipv4_ph,
+                               struct msghdr *m, size_t read,
+                               struct ipaddr *src, struct vrrp_pkt **pkt,
+                               char *errmsg, size_t errmsg_len);
 
 #endif /* __VRRP_PACKET_H__ */
index f822b89854ab8e1bd0290050d89ebc13a31121a3..1e1edb8212bf5bdcc251c84321f39b9d09cb50fd 100644 (file)
@@ -281,6 +281,35 @@ void cli_show_preempt(struct vty *vty, const struct lyd_node *dnode,
        vty_out(vty, " %svrrp %s preempt\n", pre ? "" : "no ", vrid);
 }
 
+/*
+ * XPath: /frr-interface:lib/interface/frr-vrrpd:vrrp/vrrp-group/checksum-with-
+ *        ipv4-pseudoheader
+ */
+DEFPY_YANG(vrrp_checksum_with_ipv4_pseudoheader,
+      vrrp_checksum_with_ipv4_pseudoheader_cmd,
+      "[no] vrrp (1-255)$vrid checksum-with-ipv4-pseudoheader",
+      NO_STR
+      VRRP_STR
+      VRRP_VRID_STR
+      "Checksum mode in VRRPv3\n")
+{
+       nb_cli_enqueue_change(vty, "./checksum-with-ipv4-pseudoheader",
+                             NB_OP_MODIFY, no ? "false" : "true");
+
+       return nb_cli_apply_changes(vty, VRRP_XPATH_ENTRY, vrid);
+}
+
+void cli_show_checksum_with_ipv4_pseudoheader(struct vty *vty,
+                                             const struct lyd_node *dnode,
+                                             bool show_defaults)
+{
+       const char *vrid = yang_dnode_get_string(dnode, "../virtual-router-id");
+       const bool pre = yang_dnode_get_bool(dnode, NULL);
+
+       vty_out(vty, " %svrrp %s checksum-with-ipv4-pseudoheader\n",
+               pre ? "" : "no ", vrid);
+}
+
 /* XXX: yang conversion */
 DEFPY_YANG(vrrp_autoconfigure,
       vrrp_autoconfigure_cmd,
@@ -304,7 +333,7 @@ DEFPY_YANG(vrrp_autoconfigure,
 /* XXX: yang conversion */
 DEFPY_YANG(vrrp_default,
       vrrp_default_cmd,
-      "[no] vrrp default <advertisement-interval$adv (10-40950)$advint|preempt$p|priority$prio (1-254)$prioval|shutdown$s>",
+      "[no] vrrp default <advertisement-interval$adv (10-40950)$advint|preempt$p|priority$prio (1-254)$prioval|checksum-with-ipv4-pseudoheader$ipv4ph|shutdown$s>",
       NO_STR
       VRRP_STR
       "Configure defaults for new VRRP instances\n"
@@ -313,6 +342,7 @@ DEFPY_YANG(vrrp_default,
       "Preempt mode\n"
       VRRP_PRIORITY_STR
       "Priority value\n"
+      "Checksum mode in VRRPv3\n"
       "Force VRRP router into administrative shutdown\n")
 {
        if (adv) {
@@ -329,6 +359,8 @@ DEFPY_YANG(vrrp_default,
                vd.preempt_mode = !no;
        if (prio)
                vd.priority = no ? VRRP_DEFAULT_PRIORITY : prioval;
+       if (ipv4ph)
+               vd.checksum_with_ipv4_pseudoheader = !no;
        if (s)
                vd.shutdown = !no;
 
@@ -374,6 +406,8 @@ static struct json_object *vrrp_build_json(struct vrrp_vrouter *vr)
        json_object_boolean_add(j, "shutdown", vr->shutdown);
        json_object_boolean_add(j, "preemptMode", vr->preempt_mode);
        json_object_boolean_add(j, "acceptMode", vr->accept_mode);
+       json_object_boolean_add(j, "checksumWithIpv4Pseudoheader",
+                               vr->checksum_with_ipv4_pseudoheader);
        json_object_string_add(j, "interface", vr->ifp->name);
        json_object_int_add(j, "advertisementInterval",
                            vr->advertisement_interval * CS2MS);
@@ -499,6 +533,8 @@ static void vrrp_show(struct vty *vty, struct vrrp_vrouter *vr)
                       vr->preempt_mode ? "Yes" : "No");
        ttable_add_row(tt, "%s|%s", "Accept Mode",
                       vr->accept_mode ? "Yes" : "No");
+       ttable_add_row(tt, "%s|%s", "Checksum with IPv4 Pseudoheader",
+                      vr->checksum_with_ipv4_pseudoheader ? "Yes" : "No");
        ttable_add_row(tt, "%s|%d ms", "Advertisement Interval",
                       vr->advertisement_interval * CS2MS);
        ttable_add_row(tt, "%s|%d ms (stale)",
@@ -752,4 +788,6 @@ void vrrp_vty_init(void)
        install_element(INTERFACE_NODE, &vrrp_ip_cmd);
        install_element(INTERFACE_NODE, &vrrp_ip6_cmd);
        install_element(INTERFACE_NODE, &vrrp_preempt_cmd);
+       install_element(INTERFACE_NODE,
+                       &vrrp_checksum_with_ipv4_pseudoheader_cmd);
 }
index 587537a6f3ca983f7e944a10de3a73b423babe1a..be88349e783b21cc9d65bfc2eb2f0af9cff942d1 100644 (file)
@@ -40,5 +40,8 @@ void cli_show_ipv6(struct vty *vty, const struct lyd_node *dnode,
                   bool show_defaults);
 void cli_show_preempt(struct vty *vty, const struct lyd_node *dnode,
                      bool show_defaults);
+void cli_show_checksum_with_ipv4_pseudoheader(struct vty *vty,
+                                             const struct lyd_node *dnode,
+                                             bool show_defaults);
 
 #endif /* __VRRP_VTY_H__ */
index 30f117505a5e11c3b2b8488d311154213ff7110b..dea09fa151a889ad80abf880d38e26fd25df89b0 100644 (file)
@@ -3939,6 +3939,12 @@ DEFUN (vtysh_ping,
        return CMD_SUCCESS;
 }
 
+DEFUN(vtysh_motd, vtysh_motd_cmd, "show motd", SHOW_STR "Show motd\n")
+{
+       vty_hello(vty);
+       return CMD_SUCCESS;
+}
+
 ALIAS(vtysh_ping, vtysh_ping_ip_cmd, "ping ip WORD",
       "Send echo messages\n"
       "IP echo\n"
@@ -4907,6 +4913,7 @@ void vtysh_init_vty(void)
        install_element(VIEW_NODE, &no_vtysh_terminal_monitor_cmd);
 
        install_element(VIEW_NODE, &vtysh_ping_cmd);
+       install_element(VIEW_NODE, &vtysh_motd_cmd);
        install_element(VIEW_NODE, &vtysh_ping_ip_cmd);
        install_element(VIEW_NODE, &vtysh_traceroute_cmd);
        install_element(VIEW_NODE, &vtysh_traceroute_ip_cmd);
index ac0cdc6ffd3d06ef6d947e002bdeef72ece5a845..ac32f0a774bdb851e507ad6050cfe63a92ab2998 100644 (file)
@@ -348,9 +348,13 @@ void vtysh_config_parse_line(void *arg, const char *line)
                break;
        default:
                if (strncmp(line, "exit", strlen("exit")) == 0) {
-                       if (config)
+                       if (config) {
+                               if (config->exit)
+                                       XFREE(MTYPE_VTYSH_CONFIG_LINE,
+                                             config->exit);
                                config->exit =
                                        XSTRDUP(MTYPE_VTYSH_CONFIG_LINE, line);
+                       }
                } else if (strncmp(line, "interface", strlen("interface")) == 0)
                        config = config_get(INTERFACE_NODE, line);
                else if (strncmp(line, "pseudowire", strlen("pseudowire")) == 0)
index ca119eb9004155fdc4dc45c0d984b7ddcafcc749..a72cb6e809d8e7c888ab0b5189e8017cd915562c 100644 (file)
@@ -111,6 +111,8 @@ static void vtysh_rl_callback(char *line_read)
 
        if (!vtysh_loop_exited)
                rl_callback_handler_install(vtysh_prompt(), vtysh_rl_callback);
+
+       free(line_read);
 }
 
 /* SIGTSTP handler.  This function care user's ^Z input. */
index 200eaeb0b542faf1dae75055542c4c2fc091834c..cd04df267086e3ed3697f2163aded618e10fa4d1 100644 (file)
@@ -110,6 +110,13 @@ module frr-vrrpd {
          address is not owned by the router interface";
     }
 
+    leaf checksum-with-ipv4-pseudoheader {
+      type boolean;
+      default "true";
+      description
+        "Enabled if VRRPv3 checksum for IPv4 involves pseudoheader";
+    }
+
     leaf advertisement-interval {
       type uint16 {
         range "1..4095";
index b28c468a969dcb268f7a206895ba1fe7866a5adb..d628e47492a845ff41ea0f2b725995ce2c7a142d 100644 (file)
@@ -1081,8 +1081,8 @@ static int netlink_interface(struct nlmsghdr *h, ns_id_t ns_id, int startup)
        zif->link_ifindex = link_ifindex;
 
        if (desc) {
-               XFREE(MTYPE_TMP, zif->desc);
-               zif->desc = XSTRDUP(MTYPE_TMP, desc);
+               XFREE(MTYPE_ZIF_DESC, zif->desc);
+               zif->desc = XSTRDUP(MTYPE_ZIF_DESC, desc);
        }
 
        /* Hardware type and address. */
@@ -2136,9 +2136,9 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
 
                zif = ifp->info;
                if (zif) {
-                       XFREE(MTYPE_TMP, zif->desc);
+                       XFREE(MTYPE_ZIF_DESC, zif->desc);
                        if (desc)
-                               zif->desc = XSTRDUP(MTYPE_TMP, desc);
+                               zif->desc = XSTRDUP(MTYPE_ZIF_DESC, desc);
                }
        } else {
                /* Delete interface notification from kernel */
index 81ee995dd7cf2eb7feac0c95ca327179d487fbdc..87bb49042a30ab0df66f682475dc4037240f3a6e 100644 (file)
@@ -61,6 +61,7 @@ DEFINE_HOOK(zebra_if_extra_info, (struct vty * vty, struct interface *ifp),
 DEFINE_HOOK(zebra_if_config_wr, (struct vty * vty, struct interface *ifp),
            (vty, ifp));
 
+DEFINE_MTYPE(ZEBRA, ZIF_DESC, "Intf desc");
 
 static void if_down_del_nbr_connected(struct interface *ifp);
 
@@ -233,7 +234,7 @@ static int if_zebra_delete_hook(struct interface *ifp)
                if_nhg_dependents_release(ifp);
                zebra_if_nhg_dependents_free(zebra_if);
 
-               XFREE(MTYPE_TMP, zebra_if->desc);
+               XFREE(MTYPE_ZIF_DESC, zebra_if->desc);
 
                THREAD_OFF(zebra_if->speed_update);
 
index 801078e83d52b640a60d5fc819a5a494bc86314d..0242438dc2284a5845ced1c892fc49f69764954a 100644 (file)
@@ -109,6 +109,9 @@ enum zebra_if_flags {
 #define ZEBRA_IF_IS_PROTODOWN_ONLY_EXTERNAL(zif)                               \
        ((zif)->protodown_rc == ZEBRA_PROTODOWN_EXTERNAL)
 
+/* Mem type for zif desc */
+DECLARE_MTYPE(ZIF_DESC);
+
 /* `zebra' daemon local interface structure. */
 struct zebra_if {
        /* back pointer to the interface */
index 28db2ad87d6526619e67d79d4245fe5d8c04f9f4..36852b65b6c27f8f21c8fad231adb151cb045a33 100644 (file)
@@ -200,12 +200,12 @@ static void if_set_defaults(struct irdp_interface *irdp)
 
 static struct Adv *Adv_new(void)
 {
-       return XCALLOC(MTYPE_TMP, sizeof(struct Adv));
+       return XCALLOC(MTYPE_IRDP_IF, sizeof(struct Adv));
 }
 
 static void Adv_free(struct Adv *adv)
 {
-       XFREE(MTYPE_TMP, adv);
+       XFREE(MTYPE_IRDP_IF, adv);
 }
 
 static void irdp_if_start(struct interface *ifp, int multicast,
index d594512b3653fb29119c759cf3c590ab74922df6..a2233a6667a0e8c6fe58482904fe929263956805 100644 (file)
@@ -3698,7 +3698,7 @@ static inline void zebra_neigh_ip_del(ZAPI_HANDLER_ARGS)
 static inline void zread_iptable(ZAPI_HANDLER_ARGS)
 {
        struct zebra_pbr_iptable *zpi =
-               XCALLOC(MTYPE_TMP, sizeof(struct zebra_pbr_iptable));
+               XCALLOC(MTYPE_PBR_OBJ, sizeof(struct zebra_pbr_iptable));
        struct stream *s;
 
        s = msg;
index 56d0df569c7988ff4a9f69a3e498d7e70f9860c4..d3c104cc8054549027b90a79d7a359e3cc997db5 100644 (file)
@@ -46,6 +46,7 @@
 #include "zebra/debug.h"
 #include "zebra/zapi_msg.h"
 
+DEFINE_MTYPE_STATIC(ZEBRA, ZEBRA_GR, "GR");
 
 /*
  * Forward declaration.
@@ -111,7 +112,7 @@ static struct client_gr_info *zebra_gr_client_info_create(struct zserv *client)
 {
        struct client_gr_info *info;
 
-       info = XCALLOC(MTYPE_TMP, sizeof(struct client_gr_info));
+       info = XCALLOC(MTYPE_ZEBRA_GR, sizeof(struct client_gr_info));
 
        TAILQ_INSERT_TAIL(&(client->gr_info_queue), info, gr_info);
        return info;
@@ -127,7 +128,7 @@ static void zebra_gr_client_info_delte(struct zserv *client,
 
        THREAD_OFF(info->t_stale_removal);
 
-       XFREE(MTYPE_TMP, info->current_prefix);
+       XFREE(MTYPE_ZEBRA_GR, info->current_prefix);
 
        LOG_GR("%s: Instance info is being deleted for client %s", __func__,
               zebra_route_string(client->proto));
@@ -136,7 +137,7 @@ static void zebra_gr_client_info_delte(struct zserv *client,
        info->do_delete = true;
        zebra_gr_delete_stale_routes(info);
 
-       XFREE(MTYPE_TMP, info);
+       XFREE(MTYPE_ZEBRA_GR, info);
 }
 
 /*
@@ -222,8 +223,8 @@ static void zebra_gr_delete_stale_client(struct client_gr_info *info)
        TAILQ_INIT(&(s_client->gr_info_queue));
        listnode_delete(zrouter.stale_client_list, s_client);
        if (info->stale_client)
-               XFREE(MTYPE_TMP, s_client);
-       XFREE(MTYPE_TMP, info);
+               zserv_client_delete(s_client);
+       XFREE(MTYPE_ZEBRA_GR, info);
 }
 
 /*
@@ -288,7 +289,7 @@ void zebra_gr_client_reconnect(struct zserv *client)
        /* Delete the stale client */
        listnode_delete(zrouter.stale_client_list, old_client);
        /* Delete old client */
-       XFREE(MTYPE_TMP, old_client);
+       zserv_client_delete(old_client);
 }
 
 /*
@@ -474,7 +475,7 @@ static void zebra_gr_route_stale_delete_timer_expiry(struct thread *thread)
                LOG_GR("%s: Client %s all stale routes processed", __func__,
                       zebra_route_string(client->proto));
 
-               XFREE(MTYPE_TMP, info->current_prefix);
+               XFREE(MTYPE_ZEBRA_GR, info->current_prefix);
                info->current_afi = 0;
                zebra_gr_delete_stale_client(info);
        }
@@ -579,7 +580,7 @@ static int32_t zebra_gr_delete_stale_route(struct client_gr_info *info,
                                            && (info->do_delete == false)) {
                                                info->current_afi = afi;
                                                info->current_prefix = XCALLOC(
-                                                       MTYPE_TMP,
+                                                       MTYPE_ZEBRA_GR,
                                                        sizeof(struct prefix));
                                                prefix_copy(
                                                        info->current_prefix,
@@ -593,7 +594,7 @@ static int32_t zebra_gr_delete_stale_route(struct client_gr_info *info,
                 * Reset the current prefix to indicate processing completion
                 * of the current AFI
                 */
-               XFREE(MTYPE_TMP, info->current_prefix);
+               XFREE(MTYPE_ZEBRA_GR, info->current_prefix);
        }
        return 0;
 }
index f52c5e0058173fb34c62994e2233780576f48cd0..7b076b8a4a9fa7a30743c0be512150c839053946 100644 (file)
@@ -138,7 +138,9 @@ int zebra_ns_enable(ns_id_t ns_id, void **info)
  */
 static int zebra_ns_disable_internal(struct zebra_ns *zns, bool complete)
 {
-       route_table_finish(zns->if_table);
+       if (zns->if_table)
+               route_table_finish(zns->if_table);
+       zns->if_table = NULL;
 
        zebra_dplane_ns_enable(zns, false /*Disable*/);
 
index 43e21a6d34073068ce35ece9f3e8a4484b783bd6..405241fc22808b4ea40022a9aea1426e606aba39 100644 (file)
@@ -36,6 +36,7 @@
 
 /* definitions */
 DEFINE_MTYPE_STATIC(ZEBRA, PBR_IPTABLE_IFNAME, "PBR interface list");
+DEFINE_MTYPE(ZEBRA, PBR_OBJ, "PBR");
 
 /* definitions */
 static const struct message ipset_type_msg[] = {
@@ -163,7 +164,7 @@ void zebra_pbr_rules_free(void *arg)
        rule = (struct zebra_pbr_rule *)arg;
 
        (void)dplane_pbr_rule_delete(rule);
-       XFREE(MTYPE_TMP, rule);
+       XFREE(MTYPE_PBR_OBJ, rule);
 }
 
 uint32_t zebra_pbr_rules_hash_key(const void *arg)
@@ -275,7 +276,7 @@ void zebra_pbr_ipset_free(void *arg)
 
        ipset = (struct zebra_pbr_ipset *)arg;
        hook_call(zebra_pbr_ipset_update, 0, ipset);
-       XFREE(MTYPE_TMP, ipset);
+       XFREE(MTYPE_PBR_OBJ, ipset);
 }
 
 uint32_t zebra_pbr_ipset_hash_key(const void *arg)
@@ -319,7 +320,7 @@ void zebra_pbr_ipset_entry_free(void *arg)
 
        hook_call(zebra_pbr_ipset_entry_update, 0, ipset);
 
-       XFREE(MTYPE_TMP, ipset);
+       XFREE(MTYPE_PBR_OBJ, ipset);
 }
 
 uint32_t zebra_pbr_ipset_entry_hash_key(const void *arg)
@@ -396,7 +397,7 @@ static void _zebra_pbr_iptable_free_all(void *arg, bool all)
                }
                list_delete(&iptable->interface_name_list);
        }
-       XFREE(MTYPE_TMP, iptable);
+       XFREE(MTYPE_PBR_OBJ, iptable);
 }
 
 void zebra_pbr_iptable_free(void *arg)
@@ -478,7 +479,7 @@ static void *pbr_rule_alloc_intern(void *arg)
 
        zpr = (struct zebra_pbr_rule *)arg;
 
-       new = XCALLOC(MTYPE_TMP, sizeof(*new));
+       new = XCALLOC(MTYPE_PBR_OBJ, sizeof(*new));
 
        memcpy(new, zpr, sizeof(*zpr));
 
@@ -492,7 +493,7 @@ static struct zebra_pbr_rule *pbr_rule_free(struct zebra_pbr_rule *hash_data,
                zebra_neigh_deref(hash_data);
        hash_release(zrouter.rules_hash, hash_data);
        if (free_data) {
-               XFREE(MTYPE_TMP, hash_data);
+               XFREE(MTYPE_PBR_OBJ, hash_data);
                return NULL;
        }
 
@@ -688,7 +689,7 @@ void zebra_pbr_add_rule(struct zebra_pbr_rule *rule)
                (void)dplane_pbr_rule_update(found, new);
                /* release the old hash data */
                if (old)
-                       XFREE(MTYPE_TMP, old);
+                       XFREE(MTYPE_PBR_OBJ, old);
        } else {
                if (IS_ZEBRA_DEBUG_PBR)
                        zlog_debug(
@@ -856,7 +857,7 @@ static void *pbr_ipset_alloc_intern(void *arg)
 
        zpi = (struct zebra_pbr_ipset *)arg;
 
-       new = XCALLOC(MTYPE_TMP, sizeof(struct zebra_pbr_ipset));
+       new = XCALLOC(MTYPE_PBR_OBJ, sizeof(struct zebra_pbr_ipset));
 
        memcpy(new, zpi, sizeof(*zpi));
 
@@ -877,7 +878,7 @@ void zebra_pbr_destroy_ipset(struct zebra_pbr_ipset *ipset)
        (void)dplane_pbr_ipset_delete(ipset);
        if (lookup) {
                hash_release(zrouter.ipset_hash, lookup);
-               XFREE(MTYPE_TMP, lookup);
+               XFREE(MTYPE_PBR_OBJ, lookup);
        } else
                zlog_debug(
                        "%s: IPSet Entry being deleted we know nothing about",
@@ -930,7 +931,7 @@ static void *pbr_ipset_entry_alloc_intern(void *arg)
 
        zpi = (struct zebra_pbr_ipset_entry *)arg;
 
-       new = XCALLOC(MTYPE_TMP, sizeof(struct zebra_pbr_ipset_entry));
+       new = XCALLOC(MTYPE_PBR_OBJ, sizeof(struct zebra_pbr_ipset_entry));
 
        memcpy(new, zpi, sizeof(*zpi));
 
@@ -952,7 +953,7 @@ void zebra_pbr_del_ipset_entry(struct zebra_pbr_ipset_entry *ipset)
        (void)dplane_pbr_ipset_entry_delete(ipset);
        if (lookup) {
                hash_release(zrouter.ipset_entry_hash, lookup);
-               XFREE(MTYPE_TMP, lookup);
+               XFREE(MTYPE_PBR_OBJ, lookup);
        } else
                zlog_debug("%s: IPSet being deleted we know nothing about",
                           __func__);
@@ -967,7 +968,7 @@ static void *pbr_iptable_alloc_intern(void *arg)
 
        zpi = (struct zebra_pbr_iptable *)arg;
 
-       new = XCALLOC(MTYPE_TMP, sizeof(struct zebra_pbr_iptable));
+       new = XCALLOC(MTYPE_PBR_OBJ, sizeof(struct zebra_pbr_iptable));
 
        /* Deep structure copy */
        memcpy(new, zpi, sizeof(*zpi));
@@ -1009,7 +1010,7 @@ void zebra_pbr_del_iptable(struct zebra_pbr_iptable *iptable)
                                         node);
                }
                list_delete(&iptable->interface_name_list);
-               XFREE(MTYPE_TMP, lookup);
+               XFREE(MTYPE_PBR_OBJ, lookup);
        } else
                zlog_debug("%s: IPTable being deleted we know nothing about",
                           __func__);
index baa8755fa5320e65934916ab41ff5d1c43c0e712..60457914cc2439d4e160941db0d6e506da403c29 100644 (file)
@@ -36,6 +36,9 @@
 extern "C" {
 #endif
 
+/* Memory type for PBR objects. */
+DECLARE_MTYPE(PBR_OBJ);
+
 struct zebra_pbr_action {
        afi_t afi;
 
index ebe246ffbcc127542d08c23bb89ca34353a6ebd3..d788811d3dd0274d8bda08eeca06a4ae329837b4 100644 (file)
@@ -78,6 +78,8 @@ static struct zserv *find_client_internal(uint8_t proto,
                                          unsigned short instance,
                                          uint32_t session_id);
 
+/* Mem type for zclients. */
+DEFINE_MTYPE_STATIC(ZEBRA, ZSERV_CLIENT, "ZClients");
 
 /*
  * Client thread events.
@@ -145,6 +147,14 @@ static void zserv_event(struct zserv *client, enum zserv_event event);
 
 /* Client thread lifecycle -------------------------------------------------- */
 
+/*
+ * Free a zserv client object.
+ */
+void zserv_client_delete(struct zserv *client)
+{
+       XFREE(MTYPE_ZSERV_CLIENT, client);
+}
+
 /*
  * Log zapi message to zlog.
  *
@@ -644,7 +654,7 @@ static void zserv_client_free(struct zserv *client)
                if (IS_ZEBRA_DEBUG_EVENT)
                        zlog_debug("%s: Deleting client %s", __func__,
                                   zebra_route_string(client->proto));
-               XFREE(MTYPE_TMP, client);
+               zserv_client_delete(client);
        } else {
                /* Handle cases where client has GR instance. */
                if (IS_ZEBRA_DEBUG_EVENT)
@@ -733,7 +743,7 @@ static struct zserv *zserv_client_create(int sock)
        int i;
        afi_t afi;
 
-       client = XCALLOC(MTYPE_TMP, sizeof(struct zserv));
+       client = XCALLOC(MTYPE_ZSERV_CLIENT, sizeof(struct zserv));
 
        /* Make client input/output buffer. */
        client->sock = sock;
index db7b70d7c45fe4d96d9c503ac48dc391f50c0db8..de784e382a09d94cef208bcd9839ccd0a39d8305 100644 (file)
@@ -363,6 +363,13 @@ extern void zserv_release_client(struct zserv *client);
  */
 extern void zserv_close_client(struct zserv *client);
 
+/*
+ * Free memory for a zserv client object - note that this does not
+ * clean up the internal allocations associated with the zserv client,
+ * this just free the struct's memory.
+ */
+void zserv_client_delete(struct zserv *client);
+
 /*
  * Log a ZAPI message hexdump.
  *