]> git.proxmox.com Git - mirror_frr.git/commitdiff
Merge pull request #4821 from vishaldhingra/lcomm_json
authorDonatas Abraitis <donatas.abraitis@gmail.com>
Mon, 26 Aug 2019 08:23:30 +0000 (11:23 +0300)
committerGitHub <noreply@github.com>
Mon, 26 Aug 2019 08:23:30 +0000 (11:23 +0300)
bgpd : Ambiguous command: show bgp large-community-list 1

40 files changed:
bgpd/bgp_aspath.c
bgpd/bgp_evpn_vty.c
bgpd/bgp_fsm.c
bgpd/bgp_nexthop.c
bgpd/bgp_packet.h
bgpd/bgp_rpki.c
bgpd/bgp_table.c
bgpd/bgp_vty.c
doc/user/bgp.rst
isisd/isis_cli.c
lib/libfrr.c
lib/stream.c
lib/stream.h
lib/thread.c
lib/zebra.h
ospf6d/ospf6_zebra.c
ospfd/ospf_errors.c
pbrd/pbrd.conf.sample
pimd/pim_bsm.c
pimd/pim_nht.c
redhat/frr.spec.in
sharpd/sharpd.conf.sample
staticd/staticd.conf.sample
tests/bgpd/test_bgp_table.c
tests/bgpd/test_bgp_table.py
tests/topotests/all-protocol-startup/r1/ipv4_routes.ref
tests/topotests/all-protocol-startup/r1/zebra.conf
yang/frr-bfdd.yang
yang/frr-isisd.yang
zebra/redistribute.c
zebra/rt.h
zebra/rt_netlink.c
zebra/rt_socket.c
zebra/zebra_dplane.c
zebra/zebra_dplane.h
zebra/zebra_errors.c
zebra/zebra_mpls_openbsd.c
zebra/zebra_rib.c
zebra/zebra_vxlan.c
zebra/zebra_vxlan.h

index 1385345d6486e231ff019b1b626f294e6ce01f9a..f5652b07c5e46cb66ef3a1ea2c5fbd26dd4b6411 100644 (file)
@@ -1466,7 +1466,7 @@ struct aspath *aspath_prepend(struct aspath *as1, struct aspath *as2)
        /* Not reached */
 }
 
-/* Iterate over AS_PATH segments and wipe all occurences of the
+/* Iterate over AS_PATH segments and wipe all occurrences of the
  * listed AS numbers. Hence some segments may lose some or even
  * all data on the way, the operation is implemented as a smarter
  * version of aspath_dup(), which allocates memory to hold the new
index d031d34f1f9975c3c404af640ae0684be3c49b2d..e6d81e54c4c33e27e7c26252a94b491a394edbbe 100644 (file)
@@ -3757,9 +3757,9 @@ DEFUN(show_bgp_l2vpn_evpn_route,
                        type = BGP_EVPN_MAC_IP_ROUTE;
                else if (strncmp(argv[type_idx + 1]->arg, "mu", 2) == 0)
                        type = BGP_EVPN_IMET_ROUTE;
-               else if (strncmp(argv[type_idx + 1]->arg, "es", 2) == 0)
+               else if (strncmp(argv[type_idx + 1]->arg, "e", 1) == 0)
                        type = BGP_EVPN_ES_ROUTE;
-               else if (strncmp(argv[type_idx + 1]->arg, "pr", 2) == 0)
+               else if (strncmp(argv[type_idx + 1]->arg, "p", 1) == 0)
                        type = BGP_EVPN_IP_PREFIX_ROUTE;
                else
                        return CMD_WARNING;
index 4348e6b240c68185c80a7745b58d88d1d551dbe8..c9c6fc157e63fdf6f6e353fc2b2e5e83c29c0514 100644 (file)
@@ -96,6 +96,21 @@ static int bgp_holdtime_timer(struct thread *);
 /* BGP FSM functions. */
 static int bgp_start(struct peer *);
 
+/* Register peer with NHT */
+static int bgp_peer_reg_with_nht(struct peer *peer)
+{
+       int connected = 0;
+
+       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))
+               connected = 1;
+
+       return bgp_find_or_add_nexthop(
+               peer->bgp, peer->bgp, family2afi(peer->su.sa.sa_family),
+               NULL, peer, connected);
+}
+
 static void peer_xfer_stats(struct peer *peer_dst, struct peer *peer_src)
 {
        /* Copy stats over. These are only the pre-established state stats */
@@ -293,6 +308,11 @@ static struct peer *peer_xfer_conn(struct peer *from_peer)
        if (from_peer)
                peer_xfer_stats(peer, from_peer);
 
+       /* Register peer for NHT. This is to allow RAs to be enabled when
+        * needed, even on a passive connection.
+        */
+       bgp_peer_reg_with_nht(peer);
+
        bgp_reads_on(peer);
        bgp_writes_on(peer);
        thread_add_timer_msec(bm->master, bgp_process_packet, peer, 0,
@@ -1382,7 +1402,6 @@ static int bgp_connect_fail(struct peer *peer)
 int bgp_start(struct peer *peer)
 {
        int status;
-       int connected = 0;
 
        bgp_peer_conf_if_to_su_update(peer);
 
@@ -1439,17 +1458,10 @@ int bgp_start(struct peer *peer)
                return -1;
        }
 
-       /* Register to be notified on peer up */
-       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))
-               connected = 1;
-       else
-               connected = 0;
-
-       if (!bgp_find_or_add_nexthop(peer->bgp, peer->bgp,
-                                    family2afi(peer->su.sa.sa_family), NULL,
-                                    peer, connected)) {
+       /* Register peer for NHT. If next hop is already resolved, proceed
+        * with connection setup, else wait.
+        */
+       if (!bgp_peer_reg_with_nht(peer)) {
                if (bgp_zebra_num_connects()) {
                        if (bgp_debug_neighbor_events(peer))
                                zlog_debug("%s [FSM] Waiting for NHT",
index a8c507832cce14cf5ec1461cfc8e5ee35060903b..812f0ce16e47429d9cd6e3f7f76984158d1fa328 100644 (file)
@@ -680,17 +680,23 @@ static void bgp_show_nexthops(struct vty *vty, struct bgp *bgp, int detail,
                        continue;
                for (rn = bgp_table_top(table[afi]); rn;
                     rn = bgp_route_next(rn)) {
+                       struct peer *peer;
+
                        bnc = bgp_node_get_bgp_nexthop_info(rn);
                        if (!bnc)
                                continue;
+                       peer = (struct peer *)bnc->nht_info;
 
                        if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID)) {
                                vty_out(vty,
-                                       " %s valid [IGP metric %d], #paths %d\n",
+                                       " %s valid [IGP metric %d], #paths %d",
                                        inet_ntop(rn->p.family,
                                                  &rn->p.u.prefix, buf,
                                                  sizeof(buf)),
                                        bnc->metric, bnc->path_count);
+                               if (peer)
+                                       vty_out(vty, ", peer %s", peer->host);
+                               vty_out(vty, "\n");
 
                                if (!detail)
                                        continue;
@@ -698,10 +704,13 @@ static void bgp_show_nexthops(struct vty *vty, struct bgp *bgp, int detail,
                                bgp_show_nexthops_detail(vty, bgp, bnc);
 
                        } else {
-                               vty_out(vty, " %s invalid\n",
+                               vty_out(vty, " %s invalid",
                                        inet_ntop(rn->p.family,
                                                  &rn->p.u.prefix, buf,
                                                  sizeof(buf)));
+                               if (peer)
+                                       vty_out(vty, ", peer %s", peer->host);
+                               vty_out(vty, "\n");
                                if (CHECK_FLAG(bnc->flags,
                                               BGP_NEXTHOP_CONNECTED))
                                        vty_out(vty, "  Must be Connected\n");
index e8eacee5895ecd865608c7fa154d6e080b882d7b..fc6fc66a4c3259a43765472924010b062cf59859 100644 (file)
@@ -57,9 +57,6 @@ extern void bgp_notify_send_with_data(struct peer *, uint8_t, uint8_t,
 extern void bgp_route_refresh_send(struct peer *, afi_t, safi_t, uint8_t,
                                   uint8_t, int);
 extern void bgp_capability_send(struct peer *, afi_t, safi_t, int, int);
-extern void bgp_default_update_send(struct peer *, struct attr *, afi_t, safi_t,
-                                   struct peer *);
-extern void bgp_default_withdraw_send(struct peer *, afi_t, safi_t);
 
 extern int bgp_capability_receive(struct peer *, bgp_size_t);
 
index 408d423aac32456257fd7df195db2de2266231e5..22840d54c6f8c0b908ea633ba0552a3ab532dc43 100644 (file)
@@ -142,7 +142,6 @@ static struct rtr_mgr_config *rtr_config;
 static struct list *cache_list;
 static int rtr_is_running;
 static int rtr_is_stopping;
-static int rtr_is_starting;
 static _Atomic int rtr_update_overflow;
 static int rpki_debug;
 static unsigned int polling_period;
@@ -478,7 +477,7 @@ static void rpki_update_cb_sync_rtr(struct pfx_table *p __attribute__((unused)),
                                    const struct pfx_record rec,
                                    const bool added __attribute__((unused)))
 {
-       if (rtr_is_stopping || rtr_is_starting
+       if (rtr_is_stopping
            || atomic_load_explicit(&rtr_update_overflow, memory_order_seq_cst))
                return;
 
@@ -570,11 +569,9 @@ static int bgp_rpki_module_init(void)
 
 static int start(void)
 {
-       unsigned int waiting_time = 0;
        int ret;
 
        rtr_is_stopping = 0;
-       rtr_is_starting = 1;
        rtr_update_overflow = 0;
 
        if (list_isempty(cache_list)) {
@@ -603,23 +600,6 @@ static int start(void)
                return ERROR;
        }
        rtr_is_running = 1;
-       RPKI_DEBUG("Waiting for rtr connection to synchronize.");
-       while (waiting_time++ <= initial_synchronisation_timeout) {
-               if (rtr_mgr_conf_in_sync(rtr_config))
-                       break;
-
-               sleep(1);
-       }
-       if (rtr_mgr_conf_in_sync(rtr_config)) {
-               RPKI_DEBUG("Got synchronisation with at least one RPKI cache!");
-               RPKI_DEBUG("Forcing revalidation.");
-               rtr_is_starting = 0;
-               revalidate_all_routes();
-       } else {
-               RPKI_DEBUG(
-                       "Timeout expired! Proceeding without RPKI validation data.");
-               rtr_is_starting = 0;
-       }
 
        XFREE(MTYPE_BGP_RPKI_CACHE_GROUP, groups);
 
@@ -1200,7 +1180,7 @@ DEFPY (show_rpki_prefix,
 {
 
        if (!is_synchronized()) {
-               vty_out(vty, "No Conection to RPKI cache server.\n");
+               vty_out(vty, "No Connection to RPKI cache server.\n");
                return CMD_WARNING;
        }
 
index ecde71279d2deed6f5b6e96d49cea506afd5c5f2..53175bfccf05828d513c1c0626541053ac35c2f1 100644 (file)
@@ -156,8 +156,10 @@ void bgp_table_range_lookup(const struct bgp_table *table, struct prefix *p,
        struct bgp_node *node = bgp_node_from_rnode(table->route_table->top);
        struct bgp_node *matched = NULL;
 
-       while (node && node->p.prefixlen <= p->prefixlen
-              && prefix_match(&node->p, p)) {
+       if (node == NULL)
+               return;
+
+       while (node->p.prefixlen <= p->prefixlen && prefix_match(&node->p, p)) {
                if (bgp_node_has_bgp_path_info_data(node)
                    && node->p.prefixlen == p->prefixlen) {
                        matched = node;
@@ -167,10 +169,10 @@ void bgp_table_range_lookup(const struct bgp_table *table, struct prefix *p,
                        &p->u.prefix, node->p.prefixlen)]);
        }
 
-       if (node == NULL)
-               return;
-
-       if ((matched == NULL && node->p.prefixlen > maxlen) || !node->parent)
+       if (matched == NULL && node->p.prefixlen <= maxlen
+           && prefix_match(p, &node->p) && node->parent == NULL)
+               matched = node;
+       else if ((matched == NULL && node->p.prefixlen > maxlen) || !node->parent)
                return;
        else if (matched == NULL)
                matched = node = bgp_node_from_rnode(node->parent);
index f63325812c99c21818aa08ba68ee90c016ebe3af..0d0e433980a49964c778e6cedf47fbce94426565 100644 (file)
@@ -596,12 +596,61 @@ static void bgp_clear_vty_error(struct vty *vty, struct peer *peer, afi_t afi,
        }
 }
 
+static int bgp_peer_clear(struct peer *peer, afi_t afi, safi_t safi,
+                         struct listnode *nnode, enum bgp_clear_type stype)
+{
+       int ret = 0;
+
+       /* if afi/.safi not specified, spin thru all of them */
+       if ((afi == AFI_UNSPEC) && (safi == SAFI_UNSPEC)) {
+               afi_t tmp_afi;
+               safi_t tmp_safi;
+
+               FOREACH_AFI_SAFI (tmp_afi, tmp_safi) {
+                       if (!peer->afc[tmp_afi][tmp_safi])
+                               continue;
+
+                       if (stype == BGP_CLEAR_SOFT_NONE)
+                               ret = peer_clear(peer, &nnode);
+                       else
+                               ret = peer_clear_soft(peer, tmp_afi, tmp_safi,
+                                                     stype);
+               }
+       /* if afi specified and safi not, spin thru safis on this afi */
+       } else if (safi == SAFI_UNSPEC) {
+               safi_t tmp_safi;
+
+               for (tmp_safi = SAFI_UNICAST;
+                    tmp_safi < SAFI_MAX; tmp_safi++) {
+                       if (!peer->afc[afi][tmp_safi])
+                               continue;
+
+                       if (stype == BGP_CLEAR_SOFT_NONE)
+                               ret = peer_clear(peer, &nnode);
+                       else
+                               ret = peer_clear_soft(peer, afi,
+                                                     tmp_safi, stype);
+               }
+       /* both afi/safi specified, let the caller know if not defined */
+       } else {
+               if (!peer->afc[afi][safi])
+                       return 1;
+
+               if (stype == BGP_CLEAR_SOFT_NONE)
+                       ret = peer_clear(peer, &nnode);
+               else
+                       ret = peer_clear_soft(peer, afi, safi, stype);
+       }
+
+       return ret;
+}
+
 /* `clear ip bgp' functions. */
 static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
                     enum clear_sort sort, enum bgp_clear_type stype,
                     const char *arg)
 {
-       int ret;
+       int ret = 0;
        bool found = false;
        struct peer *peer;
        struct listnode *node, *nnode;
@@ -614,13 +663,8 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
         */
        if (sort == clear_all) {
                for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
-                       if (!peer->afc[afi][safi])
-                               continue;
-
-                       if (stype == BGP_CLEAR_SOFT_NONE)
-                               ret = peer_clear(peer, &nnode);
-                       else
-                               ret = peer_clear_soft(peer, afi, safi, stype);
+                       ret = bgp_peer_clear(peer, afi, safi, nnode,
+                                                         stype);
 
                        if (ret < 0)
                                bgp_clear_vty_error(vty, peer, afi, safi, ret);
@@ -660,12 +704,11 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
                        }
                }
 
-               if (!peer->afc[afi][safi])
+               ret = bgp_peer_clear(peer, afi, safi, NULL, stype);
+
+               /* if afi/safi not defined for this peer, let caller know */
+               if (ret == 1)
                        ret = BGP_ERR_AF_UNCONFIGURED;
-               else if (stype == BGP_CLEAR_SOFT_NONE)
-                       ret = peer_clear(peer, NULL);
-               else
-                       ret = peer_clear_soft(peer, afi, safi, stype);
 
                if (ret < 0)
                        bgp_clear_vty_error(vty, peer, afi, safi, ret);
@@ -684,13 +727,7 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
                }
 
                for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
-                       if (!peer->afc[afi][safi])
-                               continue;
-
-                       if (stype == BGP_CLEAR_SOFT_NONE)
-                               ret = peer_clear(peer, NULL);
-                       else
-                               ret = peer_clear_soft(peer, afi, safi, stype);
+                       ret = bgp_peer_clear(peer, afi, safi, nnode, stype);
 
                        if (ret < 0)
                                bgp_clear_vty_error(vty, peer, afi, safi, ret);
@@ -712,13 +749,7 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
                        if (peer->sort == BGP_PEER_IBGP)
                                continue;
 
-                       if (!peer->afc[afi][safi])
-                               continue;
-
-                       if (stype == BGP_CLEAR_SOFT_NONE)
-                               ret = peer_clear(peer, &nnode);
-                       else
-                               ret = peer_clear_soft(peer, afi, safi, stype);
+                       ret = bgp_peer_clear(peer, afi, safi, nnode, stype);
 
                        if (ret < 0)
                                bgp_clear_vty_error(vty, peer, afi, safi, ret);
@@ -742,12 +773,7 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
                        if (peer->as != as)
                                continue;
 
-                       if (!peer->afc[afi][safi])
-                               ret = BGP_ERR_AF_UNCONFIGURED;
-                       else if (stype == BGP_CLEAR_SOFT_NONE)
-                               ret = peer_clear(peer, &nnode);
-                       else
-                               ret = peer_clear_soft(peer, afi, safi, stype);
+                       ret = bgp_peer_clear(peer, afi, safi, nnode, stype);
 
                        if (ret < 0)
                                bgp_clear_vty_error(vty, peer, afi, safi, ret);
@@ -6069,7 +6095,7 @@ DEFUN (neighbor_allowas_in,
        NEIGHBOR_STR
        NEIGHBOR_ADDR_STR2
        "Accept as-path with my AS present in it\n"
-       "Number of occurences of AS number\n"
+       "Number of occurrences of AS number\n"
        "Only accept my AS in the as-path if the route was originated in my AS\n")
 {
        int idx_peer = 1;
@@ -6103,7 +6129,7 @@ ALIAS_HIDDEN(
        "neighbor <A.B.C.D|X:X::X:X|WORD> allowas-in [<(1-10)|origin>]",
        NEIGHBOR_STR NEIGHBOR_ADDR_STR2
        "Accept as-path with my AS present in it\n"
-       "Number of occurences of AS number\n"
+       "Number of occurrences of AS number\n"
        "Only accept my AS in the as-path if the route was originated in my AS\n")
 
 DEFUN (no_neighbor_allowas_in,
@@ -6113,7 +6139,7 @@ DEFUN (no_neighbor_allowas_in,
        NEIGHBOR_STR
        NEIGHBOR_ADDR_STR2
        "allow local ASN appears in aspath attribute\n"
-       "Number of occurences of AS number\n"
+       "Number of occurrences of AS number\n"
        "Only accept my AS in the as-path if the route was originated in my AS\n")
 {
        int idx_peer = 2;
@@ -6135,7 +6161,7 @@ ALIAS_HIDDEN(
        "no neighbor <A.B.C.D|X:X::X:X|WORD> allowas-in [<(1-10)|origin>]",
        NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2
        "allow local ASN appears in aspath attribute\n"
-       "Number of occurences of AS number\n"
+       "Number of occurrences of AS number\n"
        "Only accept my AS in the as-path if the route was originated in my AS\n")
 
 DEFUN (neighbor_ttl_security,
@@ -7238,8 +7264,8 @@ DEFUN (clear_ip_bgp_all,
 {
        char *vrf = NULL;
 
-       afi_t afi = AFI_IP6;
-       safi_t safi = SAFI_UNICAST;
+       afi_t afi = AFI_UNSPEC;
+       safi_t safi = SAFI_UNSPEC;
        enum clear_sort clr_sort = clear_peer;
        enum bgp_clear_type clr_type;
        char *clr_arg = NULL;
@@ -14607,28 +14633,6 @@ CPP_NOTICE("bgpd: remove deprecated 'ip large-community-list <(1-99)|(100-500)|s
 #endif
 DEFUN (lcommunity_list_standard,
        bgp_lcommunity_list_standard_cmd,
-       "bgp large-community-list (1-99) <deny|permit>",
-       BGP_STR
-       LCOMMUNITY_LIST_STR
-       "Large Community list number (standard)\n"
-       "Specify large community to reject\n"
-       "Specify large community to accept\n")
-{
-       return lcommunity_list_set_vty(vty, argc, argv,
-                                      LARGE_COMMUNITY_LIST_STANDARD, 0);
-}
-
-ALIAS (lcommunity_list_standard,
-       ip_lcommunity_list_standard_cmd,
-       "ip large-community-list (1-99) <deny|permit>",
-       IP_STR
-       LCOMMUNITY_LIST_STR
-       "Large Community list number (standard)\n"
-       "Specify large community to reject\n"
-       "Specify large community to accept\n")
-
-DEFUN (lcommunity_list_standard1,
-       bgp_lcommunity_list_standard1_cmd,
        "bgp large-community-list (1-99) <deny|permit> AA:BB:CC...",
        BGP_STR
        LCOMMUNITY_LIST_STR
@@ -14641,8 +14645,8 @@ DEFUN (lcommunity_list_standard1,
                                       LARGE_COMMUNITY_LIST_STANDARD, 0);
 }
 
-ALIAS (lcommunity_list_standard1,
-       ip_lcommunity_list_standard1_cmd,
+ALIAS (lcommunity_list_standard,
+       ip_lcommunity_list_standard_cmd,
        "ip large-community-list (1-99) <deny|permit> AA:BB:CC...",
        IP_STR
        LCOMMUNITY_LIST_STR
@@ -14677,30 +14681,6 @@ ALIAS (lcommunity_list_expanded,
 
 DEFUN (lcommunity_list_name_standard,
        bgp_lcommunity_list_name_standard_cmd,
-       "bgp large-community-list standard WORD <deny|permit>",
-       BGP_STR
-       LCOMMUNITY_LIST_STR
-       "Specify standard large-community-list\n"
-       "Large Community list name\n"
-       "Specify large community to reject\n"
-       "Specify large community to accept\n")
-{
-       return lcommunity_list_set_vty(vty, argc, argv,
-                                      LARGE_COMMUNITY_LIST_STANDARD, 1);
-}
-
-ALIAS (lcommunity_list_name_standard,
-       ip_lcommunity_list_name_standard_cmd,
-       "ip large-community-list standard WORD <deny|permit>",
-       IP_STR
-       LCOMMUNITY_LIST_STR
-       "Specify standard large-community-list\n"
-       "Large Community list name\n"
-       "Specify large community to reject\n"
-       "Specify large community to accept\n")
-
-DEFUN (lcommunity_list_name_standard1,
-       bgp_lcommunity_list_name_standard1_cmd,
        "bgp large-community-list standard WORD <deny|permit> AA:BB:CC...",
        BGP_STR
        LCOMMUNITY_LIST_STR
@@ -14714,8 +14694,8 @@ DEFUN (lcommunity_list_name_standard1,
                                       LARGE_COMMUNITY_LIST_STANDARD, 1);
 }
 
-ALIAS (lcommunity_list_name_standard1,
-       ip_lcommunity_list_name_standard1_cmd,
+ALIAS (lcommunity_list_name_standard,
+       ip_lcommunity_list_name_standard_cmd,
        "ip large-community-list standard WORD <deny|permit> AA:BB:CC...",
        IP_STR
        LCOMMUNITY_LIST_STR
@@ -15543,10 +15523,8 @@ static void community_list_vty(void)
 
        /* Large Community List */
        install_element(CONFIG_NODE, &bgp_lcommunity_list_standard_cmd);
-       install_element(CONFIG_NODE, &bgp_lcommunity_list_standard1_cmd);
        install_element(CONFIG_NODE, &bgp_lcommunity_list_expanded_cmd);
        install_element(CONFIG_NODE, &bgp_lcommunity_list_name_standard_cmd);
-       install_element(CONFIG_NODE, &bgp_lcommunity_list_name_standard1_cmd);
        install_element(CONFIG_NODE, &bgp_lcommunity_list_name_expanded_cmd);
        install_element(CONFIG_NODE, &no_bgp_lcommunity_list_standard_all_cmd);
        install_element(CONFIG_NODE,
@@ -15558,10 +15536,8 @@ static void community_list_vty(void)
        install_element(VIEW_NODE, &show_bgp_lcommunity_list_cmd);
        install_element(VIEW_NODE, &show_bgp_lcommunity_list_arg_cmd);
        install_element(CONFIG_NODE, &ip_lcommunity_list_standard_cmd);
-       install_element(CONFIG_NODE, &ip_lcommunity_list_standard1_cmd);
        install_element(CONFIG_NODE, &ip_lcommunity_list_expanded_cmd);
        install_element(CONFIG_NODE, &ip_lcommunity_list_name_standard_cmd);
-       install_element(CONFIG_NODE, &ip_lcommunity_list_name_standard1_cmd);
        install_element(CONFIG_NODE, &ip_lcommunity_list_name_expanded_cmd);
        install_element(CONFIG_NODE, &no_ip_lcommunity_list_standard_all_cmd);
        install_element(CONFIG_NODE,
index f2b132807529f980f3fa35099355c144207342a3..c329ab6d9fb98d3fbd9875d3856ce9fb5bab4a9f 100644 (file)
@@ -2138,20 +2138,40 @@ Dumping Messages and Routing Tables
 Other BGP Commands
 ------------------
 
+.. index:: clear bgp \*
+.. clicmd:: clear bgp \*
+
+   Clear all peers.
+
 .. index:: clear bgp ipv4|ipv6 \*
 .. clicmd:: clear bgp ipv4|ipv6 \*
 
-   Clear all address family peers.
+   Clear all peers with this address-family activated.
+
+.. index:: clear bgp ipv4|ipv6 unicast \*
+.. clicmd:: clear bgp ipv4|ipv6 unicast \*
+
+   Clear all peers with this address-family and sub-address-family activated.
 
 .. index:: clear bgp ipv4|ipv6 PEER
 .. clicmd:: clear bgp ipv4|ipv6 PEER
 
-   Clear peers which have addresses of X.X.X.X
+   Clear peers with address of X.X.X.X and this address-family activated.
+
+.. index:: clear bgp ipv4|ipv6 unicast PEER
+.. clicmd:: clear bgp ipv4|ipv6 unicast PEER
+
+   Clear peer with address of X.X.X.X and this address-family and sub-address-family activated.
+
+.. index:: clear bgp ipv4|ipv6 PEER soft|in|out
+.. clicmd:: clear bgp ipv4|ipv6 PEER soft|in|out
+
+   Clear peer using soft reconfiguration in this address-family.
 
-.. index:: clear bgp ipv4|ipv6 PEER soft in
-.. clicmd:: clear bgp ipv4|ipv6 PEER soft in
+.. index:: clear bgp ipv4|ipv6 unicast PEER soft|in|out
+.. clicmd:: clear bgp ipv4|ipv6 unicast PEER soft|in|out
 
-   Clear peer using soft reconfiguration.
+   Clear peer using soft reconfiguration in this address-family and sub-address-family.
 
 
 .. _bgp-displaying-bgp-information:
index 4b432607731af74447825fe9d39288ea29c3f4a3..bd06286755910d3563515c84c3d6a8e4bb8fdacc 100644 (file)
@@ -363,7 +363,7 @@ void cli_show_ip_isis_bfd_monitoring(struct vty *vty, struct lyd_node *dnode,
        if (!yang_dnode_get_bool(dnode, NULL))
                vty_out(vty, " no");
 
-       vty_out(vty, "isis bfd\n");
+       vty_out(vty, " isis bfd\n");
 }
 
 /*
index 35c6092140cd11b16e9c05f45478585b4ede1364..4301dc20ad957c95661e6d67075df516f4ada59f 100644 (file)
@@ -410,7 +410,7 @@ static int frr_opt(int opt)
                }
                if (di->zpathspace)
                        fprintf(stderr,
-                               "-N option overriden by -z for zebra named socket path\n");
+                               "-N option overridden by -z for zebra named socket path\n");
 
                if (strchr(optarg, '/') || strchr(optarg, '.')) {
                        fprintf(stderr,
index c67bc3c99338fdf60e0459454d15d0d739739679..dfd13ca186445a375d85564058831253076efc05 100644 (file)
@@ -186,14 +186,6 @@ size_t stream_resize_inplace(struct stream **sptr, size_t newsize)
        return orig->size;
 }
 
-size_t __attribute__((deprecated))stream_resize_orig(struct stream *s,
-                                                    size_t newsize)
-{
-       assert("stream_resize: Switch code to use stream_resize_inplace" == NULL);
-
-       return stream_resize_inplace(&s, newsize);
-}
-
 size_t stream_get_getp(struct stream *s)
 {
        STREAM_VERIFY_SANE(s);
index a903ec0ea51a21248b0b5a3f3ba7d025cfa0ac1c..1144e43ef0e84736e3195c5697db3ddddcaae4f3 100644 (file)
@@ -153,11 +153,6 @@ extern void stream_free(struct stream *);
 extern struct stream *stream_copy(struct stream *, struct stream *src);
 extern struct stream *stream_dup(struct stream *);
 
-#if CONFDATE > 20190821
-CPP_NOTICE("lib: time to remove stream_resize_orig")
-#endif
-extern size_t stream_resize_orig(struct stream *s, size_t newsize);
-#define stream_resize stream_resize_orig
 extern size_t stream_resize_inplace(struct stream **sptr, size_t newsize);
 
 extern size_t stream_get_getp(struct stream *);
index 5756ebc1f99920b0eaaa02fab8ad48689e8b303c..943b849ebf10d5bd00d207adb5bf1e25a5e7fa0a 100644 (file)
@@ -714,7 +714,7 @@ static int fd_poll(struct thread_master *m, struct pollfd *pfds, nfds_t pfdsize,
 {
        /* If timer_wait is null here, that means poll() should block
         * indefinitely,
-        * unless the thread_master has overriden it by setting
+        * unless the thread_master has overridden it by setting
         * ->selectpoll_timeout.
         * If the value is positive, it specifies the maximum number of
         * milliseconds
index 352887eca8c78212b7e6d7a96b97559f849994a8..789a93a3c475eab9e7e4666c6eaaa0ba960a7ef2 100644 (file)
@@ -360,6 +360,7 @@ typedef enum {
 
 /* Subsequent Address Family Identifier. */
 typedef enum {
+       SAFI_UNSPEC = 0,
        SAFI_UNICAST = 1,
        SAFI_MULTICAST = 2,
        SAFI_MPLS_VPN = 3,
index af16c5aa7cded703f57dfca72dfd986a0347f913..8454016b2e0ed111c79b58a7e69e3953fa948416 100644 (file)
@@ -258,7 +258,7 @@ DEFUN (show_zebra,
                return CMD_SUCCESS;
        }
 
-       vty_out(vty, "Zebra Infomation\n");
+       vty_out(vty, "Zebra Information\n");
        vty_out(vty, "  fail: %d\n", zclient->fail);
        vty_out(vty, "  redistribute default: %d\n",
                vrf_bitmap_check(zclient->default_information[AFI_IP6],
index dd0216019588fe25fe483810e3cc0168f65a6496..a985efc668b65972d8b09acd57ca21baff4fdd25 100644 (file)
@@ -39,7 +39,7 @@ static struct log_ref ferr_ospf_warn[] = {
        },
        {
                .code = EC_OSPF_PACKET,
-               .title = "OSPF has detected packet information missmatch",
+               .title = "OSPF has detected packet information mismatch",
                .description = "OSPF has detected that packet information received is incorrect",
                .suggestion = "Ensure interface configuration is correct, gather log files from here and the peer and open an Issue",
        },
index bb1c2edca825cf36f04f262d3b033b6b9ba3945f..c9e7dce01fb5c0739043677437eb2bcfddf2d2f3 100644 (file)
@@ -1,3 +1,19 @@
+! Sample pbrd configuration file
+!
+! A quick example of what a pbr configuration might look like
 !
 !
 log stdout
+!
+! nexthop-group TEST
+!   nexthop 4.5.6.7
+!   nexthop 5.6.7.8
+! !
+! pbr-map BLUE seq 100
+!   match dst-ip 9.9.9.0/24
+!   match src-ip 10.10.10.0/24
+!   set nexthop-group TEST
+! !
+! int swp1
+!   pbr-policy BLUE
+!
index 62f13b5b534199ee90ee20f7ebd4be714594ddb6..675092dbec18e748bff8aa0f66dbe53bd7595d9e 100644 (file)
@@ -711,11 +711,11 @@ static bool pim_bsm_frag_send(uint8_t *buf, uint32_t len, struct interface *ifp,
        /* MTU  passed here is PIM MTU (IP MTU less IP Hdr) */
        if (pim_mtu < (PIM_MIN_BSM_LEN)) {
                zlog_warn(
-                       "%s: mtu(pim mtu: %d) size less than minimum bootsrap len",
+                       "%s: mtu(pim mtu: %d) size less than minimum bootstrap len",
                        __PRETTY_FUNCTION__, pim_mtu);
                if (PIM_DEBUG_BSM)
                        zlog_debug(
-                               "%s: mtu (pim mtu:%d) less than minimum bootsrap len",
+                               "%s: mtu (pim mtu:%d) less than minimum bootstrap len",
                                __PRETTY_FUNCTION__, pim_mtu);
                return false;
        }
index 39dc8ad2faeb92a2e1da55c4532b4fa22ba89fa2..7900e392312571a7db1ac96f25fad89d7e24ee43 100644 (file)
@@ -479,7 +479,7 @@ static int pim_update_upstream_nh_helper(struct hash_bucket *bucket, void *arg)
                zlog_debug("%s: NHT upstream %s(%s) old ifp %s new ifp %s",
                        __PRETTY_FUNCTION__, up->sg_str, pim->vrf->name,
                        old.source_nexthop.interface
-                       ? old.source_nexthop.interface->name : "Unknwon",
+                       ? old.source_nexthop.interface->name : "Unknown",
                        up->rpf.source_nexthop.interface->name);
        }
 
index 27042e197ce5debc1d6b91f79eb26835749c5582..014cae02ee8840633a7ccb80a5a76b1084546158 100644 (file)
@@ -1,6 +1,6 @@
 # configure options
 #
-# Some can be overriden on rpmbuild commandline with:
+# Some can be overridden on rpmbuild commandline with:
 # rpmbuild --define 'variable value'
 #   (use any value, ie 1 for flag "with_XXXX" definitions)
 #
index bb1c2edca825cf36f04f262d3b033b6b9ba3945f..d1cc19a51ff482cb9e630e05f988ae650ad38e6f 100644 (file)
@@ -1,3 +1,6 @@
+! Default sharpd configuration sample
 !
+! There are no `default` configuration commands for sharpd
+! all commands are at the view or enable level.
 !
 log stdout
index bb1c2edca825cf36f04f262d3b033b6b9ba3945f..3b64eb9c90d59f5e6fed241b9930516a144471cc 100644 (file)
@@ -1,3 +1,5 @@
-!
+! Default staticd configuration sample
 !
 log stdout
+!
+! ip route 4.5.6.7/32 10.10.10.10
index 7b38df5f66a27e092c4e1a96c301ec349f87e36c..819c2d728269b6e95ee593bf5d2e7cb660aae5c5 100644 (file)
@@ -183,7 +183,7 @@ static void test_range_lookup(void)
 
        do_test(table, "16.0.0.0/8", 16, "16.0.0.0/16", NULL);
 
-       do_test(table, "0.0.0.0/3", 21, "1.16.0.0/16", "1.16.128.0/18",
+       do_test(table, "0.0.0.0/2", 21, "1.16.0.0/16", "1.16.128.0/18",
                "1.16.192.0/18", "1.16.64.0/19", "1.16.160.0/19",
                "1.16.32.0/20", "1.16.32.0/21", "16.0.0.0/16", NULL);
 }
index 4423530fe0e31f49c9efe81c1570bb85e1cc5c8d..4deaf08c22e16dda9890cdc9fce53c65c57d25bd 100644 (file)
@@ -3,5 +3,5 @@ import frrtest
 class TestTable(frrtest.TestMultiOut):
     program = './test_bgp_table'
 
-for i in range(6):
+for i in range(9):
     TestTable.onesimple('Checks successfull')
index 1fb70a0e2fbe9cd69f337e4d870f8dae3a2ce41d..0a20231371d85bd3ceadf6103bea65d29e5176a6 100644 (file)
@@ -13,6 +13,8 @@ O   192.168.3.0/26 [110/10] is directly connected, r1-eth3, XX:XX:XX
 S>* 4.5.6.10/32 [1/0] via 192.168.0.2, r1-eth0, XX:XX:XX
 S>* 4.5.6.11/32 [1/0] via 192.168.0.2, r1-eth0, XX:XX:XX
 S>* 4.5.6.12/32 [1/0] is directly connected, r1-eth0, XX:XX:XX
+S>* 4.5.6.13/32 [1/0] unreachable (blackhole), XX:XX:XX
+S>* 4.5.6.14/32 [1/0] unreachable (blackhole), XX:XX:XX
 S>* 4.5.6.7/32 [1/0] unreachable (blackhole), XX:XX:XX
 S>* 4.5.6.8/32 [1/0] unreachable (blackhole), XX:XX:XX
 S>* 4.5.6.9/32 [1/0] unreachable (ICMP unreachable), XX:XX:XX
index 30e05f01e38a457c8eadd1664a2c448f991de6d7..c621593ef741805282f6e4a765d4d1a8df482ea2 100644 (file)
@@ -9,6 +9,9 @@ ip route 4.5.6.8/32 Null0
 ipv6 route 4:5::6:8/128 Null0
 ip route 4.5.6.9/32 reject
 ipv6 route 4:5::6:9/128 reject
+# Test various spellings of NULL0 to make sure we accept them
+ip route 4.5.6.13/32 null0
+ip route 4.5.6.14/32 NULL0
 # Create normal gateway routes
 ip route 4.5.6.10/32 192.168.0.2
 ipv6 route 4:5::6:10/128 fc00:0:0:0::2
index 24ca8f68a8b955876766afd7f0f30899afc5e333..f9ac2e43b0fbc50421eb5a6b38e6f436c1ea9930 100644 (file)
@@ -264,22 +264,22 @@ module frr-bfdd {
 
     leaf session-down-count {
       type uint32;
-      description "Amount of times the session went down";
+      description "Number of times the session went down";
     }
 
     leaf session-up-count {
       type uint32;
-      description "Amount of times the session went up";
+      description "Number of times the session went up";
     }
 
     leaf control-packet-input-count {
       type uint64;
-      description "Amount of control packets received";
+      description "Number of control packets received";
     }
 
     leaf control-packet-output-count {
       type uint64;
-      description "Amount of control packets sent";
+      description "Number of control packets sent";
     }
 
     /*
@@ -296,12 +296,12 @@ module frr-bfdd {
      */
     leaf echo-packet-input-count {
       type uint64;
-      description "Amount of echo packets received";
+      description "Number of echo packets received";
     }
 
     leaf echo-packet-output-count {
       type uint64;
-      description "Amount of echo packets sent";
+      description "Number of echo packets sent";
     }
   }
 
index 05a896a1dbd7d7344b12adaaee45491a4e0df58f..9180b0c5f3d2208f336b6594392a94db4805d559 100644 (file)
@@ -1024,7 +1024,7 @@ module frr-isisd {
       "This notification is sent when we attempt to propagate
        an LSP that is larger than the dataLinkBlockSize for the
        circuit.  The notification generation must be throttled
-       with at least 5 seconds betweeen successive
+       with at least 5 seconds between successive
        notifications.";
     uses notification-instance-hdr;
 
@@ -1090,7 +1090,7 @@ module frr-isisd {
       "This notification is sent when we receive a PDU
        with a different value for the System ID length.
        The notification generation must be throttled
-       with at least 5 seconds betweeen successive
+       with at least 5 seconds between successive
        notifications.";
     uses notification-instance-hdr;
 
@@ -1114,7 +1114,7 @@ module frr-isisd {
       "This notification is sent when we receive a PDU
        with a different value for the Maximum Area Addresses.
        The notification generation must be throttled
-       with at least 5 seconds betweeen successive
+       with at least 5 seconds between successive
        notifications.";
     uses notification-instance-hdr;
 
@@ -1170,7 +1170,7 @@ module frr-isisd {
       "This notification is sent when the system receives a
        PDU with the wrong authentication type field.
        The notification generation must be throttled
-       with at least 5 seconds betweeen successive
+       with at least 5 seconds between successive
        notifications.";
     uses notification-instance-hdr;
 
@@ -1188,7 +1188,7 @@ module frr-isisd {
       "This notification is sent when the system receives
        a PDU with the wrong authentication information.
        The notification generation must be throttled with
-       with at least 5 seconds betweeen successive
+       with at least 5 seconds between successive
        notifications.";
     uses notification-instance-hdr;
 
@@ -1206,7 +1206,7 @@ module frr-isisd {
       "This notification is sent when the system receives a
        PDU with a different protocol version number.
        The notification generation must be throttled
-       with at least 5 seconds betweeen successive
+       with at least 5 seconds between successive
        notifications.";
     uses notification-instance-hdr;
 
@@ -1230,7 +1230,7 @@ module frr-isisd {
       "This notification is sent when the system receives a
        Hello PDU from an IS that does not share any area
        address. The notification generation must be throttled
-       with at least 5 seconds betweeen successive
+       with at least 5 seconds between successive
        notifications.";
     uses notification-instance-hdr;
 
@@ -1248,7 +1248,7 @@ module frr-isisd {
       "This notification is sent when the system receives a
        Hello PDU from an IS but does not establish an adjacency
        for some reason. The notification generation must be
-       throttled with at least 5 seconds betweeen successive
+       throttled with at least 5 seconds between successive
        notifications.";
     uses notification-instance-hdr;
 
@@ -1273,7 +1273,7 @@ module frr-isisd {
     description
       "This notification is sent when the system  receives an
        LSP with a parse error. The notification generation must
-       be throttled with at least 5 seconds betweeen successive
+       be throttled with at least 5 seconds between successive
        notifications.";
     uses notification-instance-hdr;
 
@@ -1350,7 +1350,7 @@ module frr-isisd {
     description
       "This notification is sent when an LSP is received.
        The notification generation must be throttled with at
-       least 5 seconds betweeen successive notifications.";
+       least 5 seconds between successive notifications.";
     uses notification-instance-hdr;
 
     uses notification-interface-hdr;
@@ -1384,7 +1384,7 @@ module frr-isisd {
     description
       "This notification is sent when an LSP is regenerated.
        The notification generation must be throttled with at
-       least 5 seconds betweeen successive notifications.";
+       least 5 seconds between successive notifications.";
     uses notification-instance-hdr;
 
     leaf lsp-id {
index 0280cde238050a13dbe74ebafbf115adfee726c3..1ae2ba92b0cd513a337216bef39b82eea4938148 100644 (file)
@@ -172,6 +172,13 @@ void redistribute_update(const struct prefix *p, const struct prefix *src_p,
                          __FUNCTION__);
                return;
        }
+       if (!zebra_check_addr(p)) {
+               if (IS_ZEBRA_DEBUG_RIB)
+                       zlog_debug("Redist update filter prefix %s",
+                                  prefix2str(p, buf, sizeof(buf)));
+               return;
+       }
+
 
        for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
                send_redistribute = 0;
@@ -246,6 +253,13 @@ void redistribute_delete(const struct prefix *p, const struct prefix *src_p,
                return;
        }
 
+       if (!zebra_check_addr(p)) {
+               if (IS_ZEBRA_DEBUG_RIB)
+                       zlog_debug("Redist delete filter prefix %s",
+                                  prefix2str(p, buf, sizeof(buf)));
+               return;
+       }
+
        for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
                if ((is_default_prefix(p)
                     && vrf_bitmap_check(client->redist_default[afi],
index 04576671fe54f085409b4759a04a4ee8ecb0574f..727d2d0c55ab5476a86d63719699502bc231343b 100644 (file)
@@ -41,7 +41,7 @@ extern "C" {
        ((RKERNEL_ROUTE(type)) || (type) == ZEBRA_ROUTE_CONNECT)
 
 /*
- * Update or delete a route, LSP, or pseudowire from the kernel,
+ * Update or delete a route, LSP, pseudowire, or vxlan MAC from the kernel,
  * using info from a dataplane context.
  */
 extern enum zebra_dplane_result kernel_route_update(
@@ -55,6 +55,8 @@ enum zebra_dplane_result kernel_pw_update(struct zebra_dplane_ctx *ctx);
 enum zebra_dplane_result kernel_address_update_ctx(
        struct zebra_dplane_ctx *ctx);
 
+enum zebra_dplane_result kernel_mac_update_ctx(struct zebra_dplane_ctx *ctx);
+
 extern int kernel_neigh_update(int cmd, int ifindex, uint32_t addr, char *lla,
                               int llalen, ns_id_t ns_id);
 extern int kernel_interface_set_master(struct interface *master,
@@ -68,12 +70,6 @@ extern int kernel_add_vtep(vni_t vni, struct interface *ifp,
                           struct in_addr *vtep_ip);
 extern int kernel_del_vtep(vni_t vni, struct interface *ifp,
                           struct in_addr *vtep_ip);
-extern int kernel_add_mac(struct interface *ifp, vlanid_t vid,
-                         struct ethaddr *mac, struct in_addr vtep_ip,
-                         bool sticky);
-extern int kernel_del_mac(struct interface *ifp, vlanid_t vid,
-                         struct ethaddr *mac, struct in_addr vtep_ip);
-
 extern int kernel_add_neigh(struct interface *ifp, struct ipaddr *ip,
                            struct ethaddr *mac, uint8_t flags);
 extern int kernel_del_neigh(struct interface *ifp, struct ipaddr *ip);
index 95ac68fb90121f2d490181dc9ad550433000a0b2..36557631646ef70a7210a9c5ba378d6866558af6 100644 (file)
@@ -2292,33 +2292,70 @@ int netlink_macfdb_read_specific_mac(struct zebra_ns *zns,
 
        return ret;
 }
-static int netlink_macfdb_update(struct interface *ifp, vlanid_t vid,
-                                struct ethaddr *mac, struct in_addr vtep_ip,
-                                int cmd, bool sticky)
+
+/*
+ * Netlink-specific handler for MAC updates using dataplane context object.
+ */
+static enum zebra_dplane_result
+netlink_macfdb_update_ctx(struct zebra_dplane_ctx *ctx)
 {
-       struct zebra_ns *zns;
        struct {
                struct nlmsghdr n;
                struct ndmsg ndm;
                char buf[256];
        } req;
+       int ret;
        int dst_alen;
        struct zebra_if *zif;
        struct interface *br_if;
        struct zebra_if *br_zif;
-       char buf[ETHER_ADDR_STRLEN];
        int vid_present = 0;
        char vid_buf[20];
-       char dst_buf[30];
-       struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(ifp->vrf_id);
+       struct zebra_ns *zns;
+       struct interface *ifp;
+       int cmd;
+       struct in_addr vtep_ip;
+       vlanid_t vid;
+
+       if (dplane_ctx_get_op(ctx) == DPLANE_OP_MAC_INSTALL)
+               cmd = RTM_NEWNEIGH;
+       else
+               cmd = RTM_DELNEIGH;
+
+       /* Locate zebra ns and interface objects from context data */
+       zns = zebra_ns_lookup(dplane_ctx_get_ns(ctx)->ns_id);
+       if (zns == NULL) {
+               /* Nothing to be done */
+               if (IS_ZEBRA_DEBUG_KERNEL)
+                       zlog_debug("MAC %s on IF %s(%u) - zebra ns unknown",
+                                  (cmd == RTM_NEWNEIGH) ? "add" : "del",
+                                  dplane_ctx_get_ifname(ctx),
+                                  dplane_ctx_get_ifindex(ctx));
+
+               return ZEBRA_DPLANE_REQUEST_FAILURE;
+       }
+
+       ifp = if_lookup_by_index_per_ns(zns, dplane_ctx_get_ifindex(ctx));
+       if (ifp == NULL) {
+               /* Nothing to be done */
+               /* Nothing to be done */
+               if (IS_ZEBRA_DEBUG_KERNEL)
+                       zlog_debug("MAC %s on IF %s(%u) - interface unknown",
+                                  (cmd == RTM_NEWNEIGH) ? "add" : "del",
+                                  dplane_ctx_get_ifname(ctx),
+                                  dplane_ctx_get_ifindex(ctx));
+               return ZEBRA_DPLANE_REQUEST_FAILURE;
+       }
+
+       vid = dplane_ctx_mac_get_vlan(ctx);
 
-       zns = zvrf->zns;
        zif = ifp->info;
        if ((br_if = zif->brslave_info.br_if) == NULL) {
-               zlog_debug("MAC %s on IF %s(%u) - no mapping to bridge",
-                          (cmd == RTM_NEWNEIGH) ? "add" : "del", ifp->name,
-                          ifp->ifindex);
-               return -1;
+               if (IS_ZEBRA_DEBUG_KERNEL)
+                       zlog_debug("MAC %s on IF %s(%u) - no mapping to bridge",
+                                  (cmd == RTM_NEWNEIGH) ? "add" : "del",
+                                  ifp->name, ifp->ifindex);
+               return ZEBRA_DPLANE_REQUEST_FAILURE;
        }
 
        memset(&req, 0, sizeof(req));
@@ -2332,16 +2369,19 @@ static int netlink_macfdb_update(struct interface *ifp, vlanid_t vid,
        req.ndm.ndm_flags |= NTF_SELF | NTF_MASTER;
        req.ndm.ndm_state = NUD_REACHABLE;
 
-       if (sticky)
+       if (dplane_ctx_mac_is_sticky(ctx))
                req.ndm.ndm_state |= NUD_NOARP;
        else
                req.ndm.ndm_flags |= NTF_EXT_LEARNED;
 
-       addattr_l(&req.n, sizeof(req), NDA_LLADDR, mac, 6);
+       addattr_l(&req.n, sizeof(req), NDA_LLADDR,
+                 dplane_ctx_mac_get_addr(ctx), 6);
        req.ndm.ndm_ifindex = ifp->ifindex;
+
        dst_alen = 4; // TODO: hardcoded
+       vtep_ip = *(dplane_ctx_mac_get_vtep_ip(ctx));
        addattr_l(&req.n, sizeof(req), NDA_DST, &vtep_ip, dst_alen);
-       sprintf(dst_buf, " dst %s", inet_ntoa(vtep_ip));
+
        br_zif = (struct zebra_if *)br_if->info;
        if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif) && vid > 0) {
                addattr16(&req.n, sizeof(req), NDA_VLAN, vid);
@@ -2350,16 +2390,29 @@ static int netlink_macfdb_update(struct interface *ifp, vlanid_t vid,
        }
        addattr32(&req.n, sizeof(req), NDA_MASTER, br_if->ifindex);
 
-       if (IS_ZEBRA_DEBUG_KERNEL)
+       if (IS_ZEBRA_DEBUG_KERNEL) {
+               char ipbuf[PREFIX_STRLEN];
+               char buf[ETHER_ADDR_STRLEN];
+               char dst_buf[PREFIX_STRLEN + 10];
+
+               inet_ntop(AF_INET, &vtep_ip, ipbuf, sizeof(ipbuf));
+               snprintf(dst_buf, sizeof(dst_buf), " dst %s", ipbuf);
+               prefix_mac2str(dplane_ctx_mac_get_addr(ctx), buf, sizeof(buf));
+
                zlog_debug("Tx %s family %s IF %s(%u)%s %sMAC %s%s",
                           nl_msg_type_to_str(cmd),
                           nl_family_to_str(req.ndm.ndm_family), ifp->name,
                           ifp->ifindex, vid_present ? vid_buf : "",
-                          sticky ? "sticky " : "",
-                          prefix_mac2str(mac, buf, sizeof(buf)), dst_buf);
+                          dplane_ctx_mac_is_sticky(ctx) ? "sticky " : "",
+                          buf, dst_buf);
+       }
 
-       return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns,
-                           0);
+       ret = netlink_talk_info(netlink_talk_filter, &req.n,
+                               dplane_ctx_get_ns(ctx), 0);
+       if (ret == 0)
+               return ZEBRA_DPLANE_REQUEST_SUCCESS;
+       else
+               return ZEBRA_DPLANE_REQUEST_FAILURE;
 }
 
 /*
@@ -2772,17 +2825,12 @@ static int netlink_neigh_update2(struct interface *ifp, struct ipaddr *ip,
                            0);
 }
 
-int kernel_add_mac(struct interface *ifp, vlanid_t vid, struct ethaddr *mac,
-                  struct in_addr vtep_ip, bool sticky)
-{
-       return netlink_macfdb_update(ifp, vid, mac, vtep_ip, RTM_NEWNEIGH,
-                                    sticky);
-}
-
-int kernel_del_mac(struct interface *ifp, vlanid_t vid, struct ethaddr *mac,
-                  struct in_addr vtep_ip)
+/*
+ * Update MAC, using dataplane context object.
+ */
+enum zebra_dplane_result kernel_mac_update_ctx(struct zebra_dplane_ctx *ctx)
 {
-       return netlink_macfdb_update(ifp, vid, mac, vtep_ip, RTM_DELNEIGH, 0);
+       return netlink_macfdb_update_ctx(ctx);
 }
 
 int kernel_add_neigh(struct interface *ifp, struct ipaddr *ip,
index 8d8bdd0a6df839c09c31d89ff4b561ec722e1681..7e9a42a6177d0158429218d05607d6eb515bc8c0 100644 (file)
@@ -386,16 +386,12 @@ int kernel_del_vtep(vni_t vni, struct interface *ifp, struct in_addr *vtep_ip)
        return 0;
 }
 
-int kernel_add_mac(struct interface *ifp, vlanid_t vid, struct ethaddr *mac,
-                  struct in_addr vtep_ip, bool sticky)
-{
-       return 0;
-}
-
-int kernel_del_mac(struct interface *ifp, vlanid_t vid, struct ethaddr *mac,
-                  struct in_addr vtep_ip)
+/*
+ * Update MAC, using dataplane context object. No-op here for now.
+ */
+enum zebra_dplane_result kernel_mac_update_ctx(struct zebra_dplane_ctx *ctx)
 {
-       return 0;
+       return ZEBRA_DPLANE_REQUEST_SUCCESS;
 }
 
 int kernel_add_neigh(struct interface *ifp, struct ipaddr *ip,
index c90e027f02b225c02d0c78b030de83f6bf6301da..5414502fa3f5d4fd4b5fa2b33a42501a175ccccc 100644 (file)
@@ -109,8 +109,6 @@ struct dplane_route_info {
  * Pseudowire info for the dataplane
  */
 struct dplane_pw_info {
-       char ifname[IF_NAMESIZE];
-       ifindex_t ifindex;
        int type;
        int af;
        int status;
@@ -130,9 +128,6 @@ struct dplane_pw_info {
  */
 struct dplane_intf_info {
 
-       char ifname[INTERFACE_NAMSIZ];
-       ifindex_t ifindex;
-
        uint32_t metric;
        uint32_t flags;
 
@@ -152,6 +147,17 @@ struct dplane_intf_info {
        char label_buf[32];
 };
 
+/*
+ * MAC address info for the dataplane.
+ */
+struct dplane_mac_info {
+       vlanid_t vid;
+       struct ethaddr mac;
+       struct in_addr vtep_ip;
+       bool is_sticky;
+
+};
+
 /*
  * The context block used to exchange info about route updates across
  * the boundary between the zebra main context (and pthread) and the
@@ -188,12 +194,16 @@ struct zebra_dplane_ctx {
        vrf_id_t zd_vrf_id;
        uint32_t zd_table_id;
 
+       char zd_ifname[INTERFACE_NAMSIZ];
+       ifindex_t zd_ifindex;
+
        /* Support info for different kinds of updates */
        union {
                struct dplane_route_info rinfo;
                zebra_lsp_t lsp;
                struct dplane_pw_info pw;
                struct dplane_intf_info intf;
+               struct dplane_mac_info macinfo;
        } u;
 
        /* Namespace info, used especially for netlink kernel communication */
@@ -273,8 +283,8 @@ static struct zebra_dplane_globals {
        /* Sentinel for end of shutdown */
        volatile bool dg_run;
 
-       /* Route-update context queue inbound to the dataplane */
-       TAILQ_HEAD(zdg_ctx_q, zebra_dplane_ctx) dg_route_ctx_q;
+       /* Update context queue inbound to the dataplane */
+       TAILQ_HEAD(zdg_ctx_q, zebra_dplane_ctx) dg_update_ctx_q;
 
        /* Ordered list of providers */
        TAILQ_HEAD(zdg_prov_q, zebra_dplane_provider) dg_providers_q;
@@ -308,6 +318,9 @@ static struct zebra_dplane_globals {
        _Atomic uint32_t dg_intf_addrs_in;
        _Atomic uint32_t dg_intf_addr_errors;
 
+       _Atomic uint32_t dg_macs_in;
+       _Atomic uint32_t dg_mac_errors;
+
        _Atomic uint32_t dg_update_yields;
 
        /* Dataplane pthread */
@@ -348,6 +361,10 @@ static enum zebra_dplane_result pw_update_internal(struct zebra_pw *pw,
 static enum zebra_dplane_result intf_addr_update_internal(
        const struct interface *ifp, const struct connected *ifc,
        enum dplane_op_e op);
+static enum zebra_dplane_result mac_update_internal(
+       enum dplane_op_e op, const struct interface *ifp,
+       vlanid_t vid, const struct ethaddr *mac,
+       struct in_addr vtep_ip, bool sticky);
 
 /*
  * Public APIs
@@ -466,6 +483,8 @@ static void dplane_ctx_free(struct zebra_dplane_ctx **pctx)
                }
                break;
 
+       case DPLANE_OP_MAC_INSTALL:
+       case DPLANE_OP_MAC_DELETE:
        case DPLANE_OP_NONE:
                break;
        }
@@ -626,6 +645,12 @@ const char *dplane_op2str(enum dplane_op_e op)
                ret = "ADDR_UNINSTALL";
                break;
 
+       case DPLANE_OP_MAC_INSTALL:
+               ret = "MAC_INSTALL";
+               break;
+       case DPLANE_OP_MAC_DELETE:
+               ret = "MAC_DELETE";
+               break;
        }
 
        return ret;
@@ -744,6 +769,19 @@ void dplane_ctx_set_notif_provider(struct zebra_dplane_ctx *ctx,
 
        ctx->zd_notif_provider = id;
 }
+const char *dplane_ctx_get_ifname(const struct zebra_dplane_ctx *ctx)
+{
+       DPLANE_CTX_VALID(ctx);
+
+       return ctx->zd_ifname;
+}
+
+ifindex_t dplane_ctx_get_ifindex(const struct zebra_dplane_ctx *ctx)
+{
+       DPLANE_CTX_VALID(ctx);
+
+       return ctx->zd_ifindex;
+}
 
 void dplane_ctx_set_type(struct zebra_dplane_ctx *ctx, int type)
 {
@@ -1030,13 +1068,6 @@ uint32_t dplane_ctx_get_lsp_num_ecmp(const struct zebra_dplane_ctx *ctx)
        return ctx->u.lsp.num_ecmp;
 }
 
-const char *dplane_ctx_get_pw_ifname(const struct zebra_dplane_ctx *ctx)
-{
-       DPLANE_CTX_VALID(ctx);
-
-       return ctx->u.pw.ifname;
-}
-
 mpls_label_t dplane_ctx_get_pw_local_label(const struct zebra_dplane_ctx *ctx)
 {
        DPLANE_CTX_VALID(ctx);
@@ -1104,20 +1135,6 @@ dplane_ctx_get_pw_nhg(const struct zebra_dplane_ctx *ctx)
 }
 
 /* Accessors for interface information */
-const char *dplane_ctx_get_ifname(const struct zebra_dplane_ctx *ctx)
-{
-       DPLANE_CTX_VALID(ctx);
-
-       return ctx->u.intf.ifname;
-}
-
-ifindex_t dplane_ctx_get_ifindex(const struct zebra_dplane_ctx *ctx)
-{
-       DPLANE_CTX_VALID(ctx);
-
-       return ctx->u.intf.ifindex;
-}
-
 uint32_t dplane_ctx_get_intf_metric(const struct zebra_dplane_ctx *ctx)
 {
        DPLANE_CTX_VALID(ctx);
@@ -1187,6 +1204,33 @@ const char *dplane_ctx_get_intf_label(const struct zebra_dplane_ctx *ctx)
        return ctx->u.intf.label;
 }
 
+/* Accessors for MAC information */
+vlanid_t dplane_ctx_mac_get_vlan(const struct zebra_dplane_ctx *ctx)
+{
+       DPLANE_CTX_VALID(ctx);
+       return ctx->u.macinfo.vid;
+}
+
+bool dplane_ctx_mac_is_sticky(const struct zebra_dplane_ctx *ctx)
+{
+       DPLANE_CTX_VALID(ctx);
+       return ctx->u.macinfo.is_sticky;
+}
+
+const struct ethaddr *dplane_ctx_mac_get_addr(
+       const struct zebra_dplane_ctx *ctx)
+{
+       DPLANE_CTX_VALID(ctx);
+       return &(ctx->u.macinfo.mac);
+}
+
+const struct in_addr *dplane_ctx_mac_get_vtep_ip(
+       const struct zebra_dplane_ctx *ctx)
+{
+       DPLANE_CTX_VALID(ctx);
+       return &(ctx->u.macinfo.vtep_ip);
+}
+
 /*
  * End of dplane context accessors
  */
@@ -1422,10 +1466,10 @@ static int dplane_ctx_pw_init(struct zebra_dplane_ctx *ctx,
        memset(&ctx->u.pw, 0, sizeof(ctx->u.pw));
 
        /* This name appears to be c-string, so we use string copy. */
-       strlcpy(ctx->u.pw.ifname, pw->ifname, sizeof(ctx->u.pw.ifname));
+       strlcpy(ctx->zd_ifname, pw->ifname, sizeof(ctx->zd_ifname));
 
        ctx->zd_vrf_id = pw->vrf_id;
-       ctx->u.pw.ifindex = pw->ifindex;
+       ctx->zd_ifindex = pw->ifindex;
        ctx->u.pw.type = pw->type;
        ctx->u.pw.af = pw->af;
        ctx->u.pw.local_label = pw->local_label;
@@ -1467,10 +1511,10 @@ static int dplane_ctx_pw_init(struct zebra_dplane_ctx *ctx,
 }
 
 /*
- * Enqueue a new route update,
+ * Enqueue a new update,
  * and ensure an event is active for the dataplane pthread.
  */
-static int dplane_route_enqueue(struct zebra_dplane_ctx *ctx)
+static int dplane_update_enqueue(struct zebra_dplane_ctx *ctx)
 {
        int ret = EINVAL;
        uint32_t high, curr;
@@ -1478,7 +1522,7 @@ static int dplane_route_enqueue(struct zebra_dplane_ctx *ctx)
        /* Enqueue for processing by the dataplane pthread */
        DPLANE_LOCK();
        {
-               TAILQ_INSERT_TAIL(&zdplane_info.dg_route_ctx_q, ctx,
+               TAILQ_INSERT_TAIL(&zdplane_info.dg_update_ctx_q, ctx,
                                  zd_q_entries);
        }
        DPLANE_UNLOCK();
@@ -1558,7 +1602,7 @@ dplane_route_update_internal(struct route_node *rn,
                }
 
                /* Enqueue context for processing */
-               ret = dplane_route_enqueue(ctx);
+               ret = dplane_update_enqueue(ctx);
        }
 
        /* Update counter */
@@ -1724,7 +1768,7 @@ dplane_route_notif_update(struct route_node *rn,
        dplane_ctx_set_notif_provider(new_ctx,
                                      dplane_ctx_get_notif_provider(ctx));
 
-       dplane_route_enqueue(new_ctx);
+       dplane_update_enqueue(new_ctx);
 
        ret = ZEBRA_DPLANE_REQUEST_QUEUED;
 
@@ -1791,7 +1835,7 @@ dplane_lsp_notif_update(zebra_lsp_t *lsp,
                ctx,
                dplane_ctx_get_notif_provider(notif_ctx));
 
-       ret = dplane_route_enqueue(ctx);
+       ret = dplane_update_enqueue(ctx);
 
 done:
        /* Update counter */
@@ -1842,7 +1886,7 @@ static enum zebra_dplane_result lsp_update_internal(zebra_lsp_t *lsp,
        if (ret != AOK)
                goto done;
 
-       ret = dplane_route_enqueue(ctx);
+       ret = dplane_update_enqueue(ctx);
 
 done:
        /* Update counter */
@@ -1876,7 +1920,7 @@ static enum zebra_dplane_result pw_update_internal(struct zebra_pw *pw,
        if (ret != AOK)
                goto done;
 
-       ret = dplane_route_enqueue(ctx);
+       ret = dplane_update_enqueue(ctx);
 
 done:
        /* Update counter */
@@ -1967,8 +2011,8 @@ static enum zebra_dplane_result intf_addr_update_internal(
        /* Init the interface-addr-specific area */
        memset(&ctx->u.intf, 0, sizeof(ctx->u.intf));
 
-       strlcpy(ctx->u.intf.ifname, ifp->name, sizeof(ctx->u.intf.ifname));
-       ctx->u.intf.ifindex = ifp->ifindex;
+       strlcpy(ctx->zd_ifname, ifp->name, sizeof(ctx->zd_ifname));
+       ctx->zd_ifindex = ifp->ifindex;
        ctx->u.intf.prefix = *(ifc->address);
 
        if (if_is_broadcast(ifp))
@@ -2003,7 +2047,7 @@ static enum zebra_dplane_result intf_addr_update_internal(
                }
        }
 
-       ret = dplane_route_enqueue(ctx);
+       ret = dplane_update_enqueue(ctx);
 
        /* Increment counter */
        atomic_fetch_add_explicit(&zdplane_info.dg_intf_addrs_in, 1,
@@ -2021,6 +2065,104 @@ static enum zebra_dplane_result intf_addr_update_internal(
        return result;
 }
 
+/*
+ * Enqueue vxlan/evpn mac add (or update).
+ */
+enum zebra_dplane_result dplane_mac_add(const struct interface *ifp,
+                                       vlanid_t vid,
+                                       const struct ethaddr *mac,
+                                       struct in_addr vtep_ip,
+                                       bool sticky)
+{
+       enum zebra_dplane_result result;
+
+       /* Use common helper api */
+       result = mac_update_internal(DPLANE_OP_MAC_INSTALL, ifp, vid,
+                                    mac, vtep_ip, sticky);
+       return result;
+}
+
+/*
+ * Enqueue vxlan/evpn mac delete.
+ */
+enum zebra_dplane_result dplane_mac_del(const struct interface *ifp,
+                                       vlanid_t vid,
+                                       const struct ethaddr *mac,
+                                       struct in_addr vtep_ip)
+{
+       enum zebra_dplane_result result;
+
+       /* Use common helper api */
+       result = mac_update_internal(DPLANE_OP_MAC_DELETE, ifp, vid, mac,
+                                    vtep_ip, false);
+       return result;
+}
+
+/*
+ * Common helper api for MAC address/vxlan updates
+ */
+static enum zebra_dplane_result
+mac_update_internal(enum dplane_op_e op,
+                   const struct interface *ifp,
+                   vlanid_t vid,
+                   const struct ethaddr *mac,
+                   struct in_addr vtep_ip,
+                   bool sticky)
+{
+       enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE;
+       int ret;
+       struct zebra_dplane_ctx *ctx = NULL;
+       struct zebra_ns *zns;
+
+       if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) {
+               char buf1[ETHER_ADDR_STRLEN], buf2[PREFIX_STRLEN];
+
+               zlog_debug("init mac ctx %s: mac %s, ifp %s, vtep %s",
+                          dplane_op2str(op),
+                          prefix_mac2str(mac, buf1, sizeof(buf1)),
+                          ifp->name,
+                          inet_ntop(AF_INET, &vtep_ip, buf2, sizeof(buf2)));
+       }
+
+       ctx = dplane_ctx_alloc();
+
+       ctx->zd_op = op;
+       ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS;
+       ctx->zd_vrf_id = ifp->vrf_id;
+
+       zns = zebra_ns_lookup(ifp->vrf_id);
+       dplane_ctx_ns_init(ctx, zns, false);
+
+       strlcpy(ctx->zd_ifname, ifp->name, sizeof(ctx->zd_ifname));
+       ctx->zd_ifindex = ifp->ifindex;
+
+       /* Init the mac-specific data area */
+       memset(&ctx->u.macinfo, 0, sizeof(ctx->u.macinfo));
+
+       ctx->u.macinfo.vtep_ip = vtep_ip;
+       ctx->u.macinfo.mac = *mac;
+       ctx->u.macinfo.vid = vid;
+       ctx->u.macinfo.is_sticky = sticky;
+
+       /* Enqueue for processing on the dplane pthread */
+       ret = dplane_update_enqueue(ctx);
+
+       /* Increment counter */
+       atomic_fetch_add_explicit(&zdplane_info.dg_macs_in, 1,
+                                 memory_order_relaxed);
+
+       if (ret == AOK)
+               result = ZEBRA_DPLANE_REQUEST_QUEUED;
+       else {
+               /* Error counter */
+               atomic_fetch_add_explicit(&zdplane_info.dg_mac_errors, 1,
+                                         memory_order_relaxed);
+               dplane_ctx_free(&ctx);
+       }
+
+       return result;
+}
+
 /*
  * Handler for 'show dplane'
  */
@@ -2054,7 +2196,35 @@ int dplane_show_helper(struct vty *vty, bool detailed)
        vty_out(vty, "Route update queue limit: %"PRIu64"\n", limit);
        vty_out(vty, "Route update queue depth: %"PRIu64"\n", queued);
        vty_out(vty, "Route update queue max:   %"PRIu64"\n", queue_max);
-       vty_out(vty, "Dplane update yields:      %"PRIu64"\n", yields);
+       vty_out(vty, "Dplane update yields:     %"PRIu64"\n", yields);
+
+       incoming = atomic_load_explicit(&zdplane_info.dg_lsps_in,
+                                       memory_order_relaxed);
+       errs = atomic_load_explicit(&zdplane_info.dg_lsp_errors,
+                                   memory_order_relaxed);
+       vty_out(vty, "LSP updates:              %"PRIu64"\n", incoming);
+       vty_out(vty, "LSP update errors:        %"PRIu64"\n", errs);
+
+       incoming = atomic_load_explicit(&zdplane_info.dg_pws_in,
+                                       memory_order_relaxed);
+       errs = atomic_load_explicit(&zdplane_info.dg_pw_errors,
+                                   memory_order_relaxed);
+       vty_out(vty, "PW updates:               %"PRIu64"\n", incoming);
+       vty_out(vty, "PW update errors:         %"PRIu64"\n", errs);
+
+       incoming = atomic_load_explicit(&zdplane_info.dg_intf_addrs_in,
+                                       memory_order_relaxed);
+       errs = atomic_load_explicit(&zdplane_info.dg_intf_addr_errors,
+                                   memory_order_relaxed);
+       vty_out(vty, "Intf addr updates:        %"PRIu64"\n", incoming);
+       vty_out(vty, "Intf addr errors:         %"PRIu64"\n", errs);
+
+       incoming = atomic_load_explicit(&zdplane_info.dg_macs_in,
+                                       memory_order_relaxed);
+       errs = atomic_load_explicit(&zdplane_info.dg_mac_errors,
+                                   memory_order_relaxed);
+       vty_out(vty, "EVPN MAC updates:         %"PRIu64"\n", incoming);
+       vty_out(vty, "EVPN MAC errors:          %"PRIu64"\n", errs);
 
        return CMD_SUCCESS;
 }
@@ -2374,7 +2544,7 @@ kernel_dplane_pw_update(struct zebra_dplane_ctx *ctx)
 
        if (IS_ZEBRA_DEBUG_DPLANE_DETAIL)
                zlog_debug("Dplane pw %s: op %s af %d loc: %u rem: %u",
-                          dplane_ctx_get_pw_ifname(ctx),
+                          dplane_ctx_get_ifname(ctx),
                           dplane_op2str(ctx->zd_op),
                           dplane_ctx_get_pw_af(ctx),
                           dplane_ctx_get_pw_local_label(ctx),
@@ -2428,7 +2598,6 @@ kernel_dplane_address_update(struct zebra_dplane_ctx *ctx)
 {
        enum zebra_dplane_result res;
 
-
        if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) {
                char dest_str[PREFIX_STRLEN];
 
@@ -2449,6 +2618,34 @@ kernel_dplane_address_update(struct zebra_dplane_ctx *ctx)
        return res;
 }
 
+/*
+ * Handler for kernel-facing MAC address updates
+ */
+static enum zebra_dplane_result
+kernel_dplane_mac_update(struct zebra_dplane_ctx *ctx)
+{
+       enum zebra_dplane_result res;
+
+       if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) {
+               char buf[ETHER_ADDR_STRLEN];
+
+               prefix_mac2str(dplane_ctx_mac_get_addr(ctx), buf,
+                              sizeof(buf));
+
+               zlog_debug("Dplane %s, mac %s, ifindex %u",
+                          dplane_op2str(dplane_ctx_get_op(ctx)),
+                          buf, dplane_ctx_get_ifindex(ctx));
+       }
+
+       res = kernel_mac_update_ctx(ctx);
+
+       if (res != ZEBRA_DPLANE_REQUEST_SUCCESS)
+               atomic_fetch_add_explicit(&zdplane_info.dg_mac_errors,
+                                         1, memory_order_relaxed);
+
+       return res;
+}
+
 /*
  * Kernel provider callback
  */
@@ -2503,6 +2700,11 @@ static int kernel_dplane_process_func(struct zebra_dplane_provider *prov)
                        res = kernel_dplane_address_update(ctx);
                        break;
 
+               case DPLANE_OP_MAC_INSTALL:
+               case DPLANE_OP_MAC_DELETE:
+                       res = kernel_dplane_mac_update(ctx);
+                       break;
+
                /* Ignore 'notifications' - no-op */
                case DPLANE_OP_SYS_ROUTE_ADD:
                case DPLANE_OP_SYS_ROUTE_DELETE:
@@ -2682,7 +2884,7 @@ static bool dplane_work_pending(void)
         */
        DPLANE_LOCK();
        {
-               ctx = TAILQ_FIRST(&zdplane_info.dg_route_ctx_q);
+               ctx = TAILQ_FIRST(&zdplane_info.dg_update_ctx_q);
                prov = TAILQ_FIRST(&zdplane_info.dg_providers_q);
        }
        DPLANE_UNLOCK();
@@ -2810,9 +3012,9 @@ static int dplane_thread_loop(struct thread *event)
 
        /* Move new work from incoming list to temp list */
        for (counter = 0; counter < limit; counter++) {
-               ctx = TAILQ_FIRST(&zdplane_info.dg_route_ctx_q);
+               ctx = TAILQ_FIRST(&zdplane_info.dg_update_ctx_q);
                if (ctx) {
-                       TAILQ_REMOVE(&zdplane_info.dg_route_ctx_q, ctx,
+                       TAILQ_REMOVE(&zdplane_info.dg_update_ctx_q, ctx,
                                     zd_q_entries);
 
                        ctx->zd_provider = prov->dp_id;
@@ -2997,7 +3199,7 @@ static void zebra_dplane_init_internal(void)
 
        pthread_mutex_init(&zdplane_info.dg_mutex, NULL);
 
-       TAILQ_INIT(&zdplane_info.dg_route_ctx_q);
+       TAILQ_INIT(&zdplane_info.dg_update_ctx_q);
        TAILQ_INIT(&zdplane_info.dg_providers_q);
 
        zdplane_info.dg_updates_per_cycle = DPLANE_DEFAULT_NEW_WORK;
index 6238026bcfcf542979da3a9695fd9b957426918c..912fda45d34c6274590197c5de446bfc24502cfe 100644 (file)
@@ -25,6 +25,7 @@
 #include "lib/nexthop.h"
 #include "lib/nexthop_group.h"
 #include "lib/queue.h"
+#include "lib/vlan.h"
 #include "zebra/zebra_ns.h"
 #include "zebra/rib.h"
 #include "zebra/zserv.h"
@@ -124,6 +125,10 @@ enum dplane_op_e {
        /* Interface address update */
        DPLANE_OP_ADDR_INSTALL,
        DPLANE_OP_ADDR_UNINSTALL,
+
+       /* MAC address update */
+       DPLANE_OP_MAC_INSTALL,
+       DPLANE_OP_MAC_DELETE,
 };
 
 /* Enable system route notifications */
@@ -180,6 +185,8 @@ const char *dplane_op2str(enum dplane_op_e op);
 const struct prefix *dplane_ctx_get_dest(const struct zebra_dplane_ctx *ctx);
 void dplane_ctx_set_dest(struct zebra_dplane_ctx *ctx,
                         const struct prefix *dest);
+const char *dplane_ctx_get_ifname(const struct zebra_dplane_ctx *ctx);
+ifindex_t dplane_ctx_get_ifindex(const struct zebra_dplane_ctx *ctx);
 
 /* Retrieve last/current provider id */
 uint32_t dplane_ctx_get_provider(const struct zebra_dplane_ctx *ctx);
@@ -262,7 +269,6 @@ const zebra_nhlfe_t *dplane_ctx_set_best_nhlfe(struct zebra_dplane_ctx *ctx,
 uint32_t dplane_ctx_get_lsp_num_ecmp(const struct zebra_dplane_ctx *ctx);
 
 /* Accessors for pseudowire information */
-const char *dplane_ctx_get_pw_ifname(const struct zebra_dplane_ctx *ctx);
 mpls_label_t dplane_ctx_get_pw_local_label(const struct zebra_dplane_ctx *ctx);
 mpls_label_t dplane_ctx_get_pw_remote_label(const struct zebra_dplane_ctx *ctx);
 int dplane_ctx_get_pw_type(const struct zebra_dplane_ctx *ctx);
@@ -277,8 +283,6 @@ const struct nexthop_group *dplane_ctx_get_pw_nhg(
        const struct zebra_dplane_ctx *ctx);
 
 /* Accessors for interface information */
-const char *dplane_ctx_get_ifname(const struct zebra_dplane_ctx *ctx);
-ifindex_t dplane_ctx_get_ifindex(const struct zebra_dplane_ctx *ctx);
 uint32_t dplane_ctx_get_intf_metric(const struct zebra_dplane_ctx *ctx);
 /* Is interface addr p2p? */
 bool dplane_ctx_intf_is_connected(const struct zebra_dplane_ctx *ctx);
@@ -292,6 +296,14 @@ const struct prefix *dplane_ctx_get_intf_dest(
 bool dplane_ctx_intf_has_label(const struct zebra_dplane_ctx *ctx);
 const char *dplane_ctx_get_intf_label(const struct zebra_dplane_ctx *ctx);
 
+/* Accessors for MAC information */
+vlanid_t dplane_ctx_mac_get_vlan(const struct zebra_dplane_ctx *ctx);
+bool dplane_ctx_mac_is_sticky(const struct zebra_dplane_ctx *ctx);
+const struct ethaddr *dplane_ctx_mac_get_addr(
+       const struct zebra_dplane_ctx *ctx);
+const struct in_addr *dplane_ctx_mac_get_vtep_ip(
+       const struct zebra_dplane_ctx *ctx);
+
 /* Namespace info - esp. for netlink communication */
 const struct zebra_dplane_info *dplane_ctx_get_ns(
        const struct zebra_dplane_ctx *ctx);
@@ -353,6 +365,19 @@ enum zebra_dplane_result dplane_intf_addr_set(const struct interface *ifp,
 enum zebra_dplane_result dplane_intf_addr_unset(const struct interface *ifp,
                                                const struct connected *ifc);
 
+/*
+ * Enqueue evpn mac operations for the dataplane.
+ */
+enum zebra_dplane_result dplane_mac_add(const struct interface *ifp,
+                                       vlanid_t vid,
+                                       const struct ethaddr *mac,
+                                       struct in_addr vtep_ip,
+                                       bool sticky);
+
+enum zebra_dplane_result dplane_mac_del(const struct interface *ifp,
+                                       vlanid_t vid,
+                                       const struct ethaddr *mac,
+                                       struct in_addr vtep_ip);
 
 /* Retrieve the limit on the number of pending, unprocessed updates. */
 uint32_t dplane_get_in_queue_limit(void);
index 5f0a9ec011387dadf62e8622700d7cc6858d6625..a7e5147af3ca1171d70f802b646f5ee228bf03a9 100644 (file)
@@ -659,7 +659,7 @@ static struct log_ref ferr_zebra_err[] = {
        {
                .code = EC_ZEBRA_RTM_VERSION_MISMATCH,
                .title =
-                       "Zebra received kernel message with uknown version",
+                       "Zebra received kernel message with unknown version",
                .description =
                        "Zebra received a message from the kernel with a message version that does not match Zebra's internal version. Depending on version compatibility, this may cause issues sending and receiving messages to the kernel.",
                .suggestion =
index e7fdaf127d38ad30368f585edeb1083781db0198..9f3ea70c77aa5b4035889584e9872df4cc3edc65 100644 (file)
@@ -369,7 +369,7 @@ static enum zebra_dplane_result kmpw_install(struct zebra_dplane_ctx *ctx)
 
        /* ioctl */
        memset(&ifr, 0, sizeof(ifr));
-       strlcpy(ifr.ifr_name, dplane_ctx_get_pw_ifname(ctx),
+       strlcpy(ifr.ifr_name, dplane_ctx_get_ifname(ctx),
                sizeof(ifr.ifr_name));
        ifr.ifr_data = (caddr_t)&imr;
        if (ioctl(kr_state.ioctl_fd, SIOCSETMPWCFG, &ifr) == -1) {
@@ -388,7 +388,7 @@ static enum zebra_dplane_result kmpw_uninstall(struct zebra_dplane_ctx *ctx)
 
        memset(&ifr, 0, sizeof(ifr));
        memset(&imr, 0, sizeof(imr));
-       strlcpy(ifr.ifr_name, dplane_ctx_get_pw_ifname(ctx),
+       strlcpy(ifr.ifr_name, dplane_ctx_get_ifname(ctx),
                sizeof(ifr.ifr_name));
        ifr.ifr_data = (caddr_t)&imr;
        if (ioctl(kr_state.ioctl_fd, SIOCSETMPWCFG, &ifr) == -1) {
index 3608b887ee4b8683cf76705cf3283771a3c870be..335cc8294c531d282b6ccb2a0b4b1804963f2968 100644 (file)
@@ -3178,7 +3178,7 @@ static int handle_pw_result(struct zebra_dplane_ctx *ctx)
 
        if (dplane_ctx_get_status(ctx) != ZEBRA_DPLANE_REQUEST_SUCCESS) {
                vrf = zebra_vrf_lookup_by_id(dplane_ctx_get_vrf(ctx));
-               pw = zebra_pw_find(vrf, dplane_ctx_get_pw_ifname(ctx));
+               pw = zebra_pw_find(vrf, dplane_ctx_get_ifname(ctx));
                if (pw)
                        zebra_pw_install_failure(pw);
        }
@@ -3270,6 +3270,11 @@ static int rib_process_dplane_results(struct thread *thread)
                                dplane_ctx_fini(&ctx);
                                break;
 
+                       case DPLANE_OP_MAC_INSTALL:
+                       case DPLANE_OP_MAC_DELETE:
+                               zebra_vxlan_handle_result(ctx);
+                               break;
+
                        default:
                                /* Don't expect this: just return the struct? */
                                dplane_ctx_fini(&ctx);
index 1450072aa988eb561268985b4248a42168019679..bb31247b6a2b92fdf27ca30ad8822c733c9e6d58 100644 (file)
@@ -3733,13 +3733,14 @@ static struct interface *zvni_map_to_svi(vlanid_t vid, struct interface *br_if)
 }
 
 /*
- * Install remote MAC into the kernel.
+ * Install remote MAC into the forwarding plane.
  */
 static int zvni_mac_install(zebra_vni_t *zvni, zebra_mac_t *mac)
 {
        struct zebra_if *zif;
        struct zebra_l2info_vxlan *vxl;
        bool sticky;
+       enum zebra_dplane_result res;
 
        if (!(mac->flags & ZEBRA_MAC_REMOTE))
                return 0;
@@ -3752,12 +3753,16 @@ static int zvni_mac_install(zebra_vni_t *zvni, zebra_mac_t *mac)
        sticky = !!CHECK_FLAG(mac->flags,
                         (ZEBRA_MAC_STICKY | ZEBRA_MAC_REMOTE_DEF_GW));
 
-       return kernel_add_mac(zvni->vxlan_if, vxl->access_vlan, &mac->macaddr,
-                             mac->fwd_info.r_vtep_ip, sticky);
+       res = dplane_mac_add(zvni->vxlan_if, vxl->access_vlan, &mac->macaddr,
+                            mac->fwd_info.r_vtep_ip, sticky);
+       if (res != ZEBRA_DPLANE_REQUEST_FAILURE)
+               return 0;
+       else
+               return -1;
 }
 
 /*
- * Uninstall remote MAC from the kernel.
+ * Uninstall remote MAC from the forwarding plane.
  */
 static int zvni_mac_uninstall(zebra_vni_t *zvni, zebra_mac_t *mac)
 {
@@ -3765,6 +3770,7 @@ static int zvni_mac_uninstall(zebra_vni_t *zvni, zebra_mac_t *mac)
        struct zebra_l2info_vxlan *vxl;
        struct in_addr vtep_ip;
        struct interface *ifp;
+       enum zebra_dplane_result res;
 
        if (!(mac->flags & ZEBRA_MAC_REMOTE))
                return 0;
@@ -3783,7 +3789,11 @@ static int zvni_mac_uninstall(zebra_vni_t *zvni, zebra_mac_t *mac)
        ifp = zvni->vxlan_if;
        vtep_ip = mac->fwd_info.r_vtep_ip;
 
-       return kernel_del_mac(ifp, vxl->access_vlan, &mac->macaddr, vtep_ip);
+       res = dplane_mac_del(ifp, vxl->access_vlan, &mac->macaddr, vtep_ip);
+       if (res != ZEBRA_DPLANE_REQUEST_FAILURE)
+               return 0;
+       else
+               return -1;
 }
 
 /*
@@ -4470,12 +4480,13 @@ static int zl3vni_rmac_del(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac)
 }
 
 /*
- * Install remote RMAC into the kernel.
+ * Install remote RMAC into the forwarding plane.
  */
 static int zl3vni_rmac_install(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac)
 {
        struct zebra_if *zif = NULL;
        struct zebra_l2info_vxlan *vxl = NULL;
+       enum zebra_dplane_result res;
 
        if (!(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE))
            || !(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE_RMAC)))
@@ -4487,18 +4498,23 @@ static int zl3vni_rmac_install(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac)
 
        vxl = &zif->l2info.vxl;
 
-       return kernel_add_mac(zl3vni->vxlan_if, vxl->access_vlan,
-                             &zrmac->macaddr, zrmac->fwd_info.r_vtep_ip, 0);
+       res = dplane_mac_add(zl3vni->vxlan_if, vxl->access_vlan,
+                            &zrmac->macaddr, zrmac->fwd_info.r_vtep_ip, 0);
+       if (res != ZEBRA_DPLANE_REQUEST_FAILURE)
+               return 0;
+       else
+               return -1;
 }
 
 /*
- * Uninstall remote RMAC from the kernel.
+ * Uninstall remote RMAC from the forwarding plane.
  */
 static int zl3vni_rmac_uninstall(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac)
 {
        char buf[ETHER_ADDR_STRLEN];
        struct zebra_if *zif = NULL;
        struct zebra_l2info_vxlan *vxl = NULL;
+       enum zebra_dplane_result res;
 
        if (!(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE))
            || !(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE_RMAC)))
@@ -4518,8 +4534,12 @@ static int zl3vni_rmac_uninstall(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac)
 
        vxl = &zif->l2info.vxl;
 
-       return kernel_del_mac(zl3vni->vxlan_if, vxl->access_vlan,
-                             &zrmac->macaddr, zrmac->fwd_info.r_vtep_ip);
+       res = dplane_mac_del(zl3vni->vxlan_if, vxl->access_vlan,
+                            &zrmac->macaddr, zrmac->fwd_info.r_vtep_ip);
+       if (res != ZEBRA_DPLANE_REQUEST_FAILURE)
+               return 0;
+       else
+               return -1;
 }
 
 /* handle rmac add */
@@ -6772,7 +6792,7 @@ int zebra_vxlan_clear_dup_detect_vni_ip(struct vty *vty,
 
        if (!CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE)) {
                vty_out(vty,
-                       "%% Requsted host IP %s is not duplicate detected\n",
+                       "%% Requested host IP %s is not duplicate detected\n",
                        buf);
                return CMD_WARNING;
        }
@@ -9913,6 +9933,15 @@ static int zebra_evpn_cfg_clean_up(struct zserv *client)
        return 0;
 }
 
+/*
+ * Handle results for vxlan dataplane operations.
+ */
+extern void zebra_vxlan_handle_result(struct zebra_dplane_ctx *ctx)
+{
+       /* TODO -- anything other than freeing the context? */
+       dplane_ctx_fini(&ctx);
+}
+
 /* Cleanup BGP EVPN configuration upon client disconnect */
 extern void zebra_evpn_init(void)
 {
index c71953d6bb52bad0f847d2b0d6e12312adde4885..bb80ae1c9add110314d9ae2d45c9fa9fe9bc13d9 100644 (file)
@@ -35,6 +35,7 @@
 #include "lib/json.h"
 #include "zebra/zebra_vrf.h"
 #include "zebra/zserv.h"
+#include "zebra/zebra_dplane.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -213,6 +214,8 @@ extern int zebra_vxlan_clear_dup_detect_vni_all(struct vty *vty,
 extern int zebra_vxlan_clear_dup_detect_vni(struct vty *vty,
                                            struct zebra_vrf *zvrf,
                                            vni_t vni);
+extern void zebra_vxlan_handle_result(struct zebra_dplane_ctx *ctx);
+
 extern void zebra_evpn_init(void);
 
 #ifdef __cplusplus