diff options
| -rw-r--r-- | bgpd/bgp_route.c | 8 | ||||
| -rw-r--r-- | bgpd/bgp_zebra.c | 20 | ||||
| -rw-r--r-- | doc/user/ospfd.rst | 2 | ||||
| -rw-r--r-- | doc/user/pathd.rst | 4 | ||||
| -rw-r--r-- | isisd/isisd.c | 6 | ||||
| -rw-r--r-- | lib/route_opaque.h | 38 | ||||
| -rw-r--r-- | lib/subdir.am | 1 | ||||
| -rw-r--r-- | lib/vrf.c | 2 | ||||
| -rw-r--r-- | ospf6d/ospf6_asbr.c | 2 | ||||
| -rw-r--r-- | tests/topotests/zebra_opaque/__init__.py | 0 | ||||
| -rw-r--r-- | tests/topotests/zebra_opaque/r1/bgpd.conf | 5 | ||||
| -rw-r--r-- | tests/topotests/zebra_opaque/r1/zebra.conf | 4 | ||||
| -rw-r--r-- | tests/topotests/zebra_opaque/r2/bgpd.conf | 12 | ||||
| -rw-r--r-- | tests/topotests/zebra_opaque/r2/zebra.conf | 4 | ||||
| -rw-r--r-- | tests/topotests/zebra_opaque/test_zebra_opaque.py | 104 | ||||
| -rw-r--r-- | zebra/zebra_vty.c | 35 |
16 files changed, 223 insertions, 24 deletions
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index dd1e8471e6..c61aedb560 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -7807,14 +7807,14 @@ int bgp_aggregate_set(struct bgp *bgp, struct prefix *prefix, afi_t afi, DEFPY_YANG( aggregate_addressv4, aggregate_addressv4_cmd, - "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> {" + "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{" "as-set$as_set_s" "|summary-only$summary_only" "|route-map WORD$rmap_name" "|origin <egp|igp|incomplete>$origin_s" "|matching-MED-only$match_med" "|suppress-map WORD$suppress_map" - "}", + "}]", NO_STR "Configure BGP aggregate entries\n" "Aggregate prefix\n" @@ -7897,14 +7897,14 @@ DEFPY_YANG( } DEFPY_YANG(aggregate_addressv6, aggregate_addressv6_cmd, - "[no] aggregate-address X:X::X:X/M$prefix {" + "[no] aggregate-address X:X::X:X/M$prefix [{" "as-set$as_set_s" "|summary-only$summary_only" "|route-map WORD$rmap_name" "|origin <egp|igp|incomplete>$origin_s" "|matching-MED-only$match_med" "|suppress-map WORD$suppress_map" - "}", + "}]", NO_STR "Configure BGP aggregate entries\n" "Aggregate prefix\n" diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 2bf57130be..97f781b2bf 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -33,6 +33,7 @@ #include "memory.h" #include "lib/json.h" #include "lib/bfd.h" +#include "lib/route_opaque.h" #include "filter.h" #include "mpls.h" #include "vxlan.h" @@ -1400,11 +1401,24 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p, is_add = (valid_nh_count || nhg_id) ? true : false; if (is_add && CHECK_FLAG(bm->flags, BM_FLAG_SEND_EXTRA_DATA_TO_ZEBRA)) { - struct aspath *aspath = info->attr->aspath; + struct bgp_zebra_opaque bzo = {}; + + strlcpy(bzo.aspath, info->attr->aspath->str, + sizeof(bzo.aspath)); + + if (info->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) + strlcpy(bzo.community, info->attr->community->str, + sizeof(bzo.community)); + + if (info->attr->flag + & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) + strlcpy(bzo.lcommunity, info->attr->lcommunity->str, + sizeof(bzo.lcommunity)); SET_FLAG(api.message, ZAPI_MESSAGE_OPAQUE); - api.opaque.length = strlen(aspath->str) + 1; - memcpy(api.opaque.data, aspath->str, api.opaque.length); + api.opaque.length = MIN(sizeof(struct bgp_zebra_opaque), + ZAPI_MESSAGE_OPAQUE_LENGTH); + memcpy(api.opaque.data, &bzo, api.opaque.length); } if (allow_recursion) diff --git a/doc/user/ospfd.rst b/doc/user/ospfd.rst index b321d99ad8..c8b25db8af 100644 --- a/doc/user/ospfd.rst +++ b/doc/user/ospfd.rst @@ -855,7 +855,7 @@ Traffic Engineering flood in AREA <area-id> with Opaque Type-10, respectively in AS with Opaque Type-11. In all case, Opaque-LSA TLV=6. -.. clicmd:: no mpls-te export +.. clicmd:: mpls-te export Export Traffic Engineering Data Base to other daemons through the ZAPI Opaque Link State messages. diff --git a/doc/user/pathd.rst b/doc/user/pathd.rst index 4c7611bc04..f27360cca7 100644 --- a/doc/user/pathd.rst +++ b/doc/user/pathd.rst @@ -104,11 +104,11 @@ Configuration Commands Configure segment routing traffic engineering. -.. clicmd:: [no] mpls-te <on|off> +.. clicmd:: mpls-te <on|off> Activate/Deactivate use of internal Traffic Engineering Database -.. clicmd:: [no] mpls-te import <ospfv2|ospfv3|isis> +.. clicmd:: mpls-te import <ospfv2|ospfv3|isis> Load data from the selected igp diff --git a/isisd/isisd.c b/isisd/isisd.c index bda2295ae1..77b18f9cf7 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -1920,9 +1920,9 @@ DEFUN(no_debug_isis_ldp_sync, no_debug_isis_ldp_sync_cmd, DEFUN (show_hostname, show_hostname_cmd, - "show " PROTO_NAME " hostname", - SHOW_STR - PROTO_HELP + "show " PROTO_NAME " [vrf <NAME|all>] hostname", + SHOW_STR PROTO_HELP VRF_CMD_HELP_STR + "All VRFs\n" "IS-IS Dynamic hostname mapping\n") { struct listnode *node; diff --git a/lib/route_opaque.h b/lib/route_opaque.h new file mode 100644 index 0000000000..599a0363eb --- /dev/null +++ b/lib/route_opaque.h @@ -0,0 +1,38 @@ +/* Opaque data for Zebra from other daemons. + * + * Copyright (C) 2021 Donatas Abraitis <donatas.abraitis@gmail.com> + * + * This file is part of FRRouting (FRR). + * + * FRR is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2, or (at your option) any later version. + * + * FRR is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef FRR_ROUTE_OPAQUE_H +#define FRR_ROUTE_OPAQUE_H + +#include "bgpd/bgp_aspath.h" +#include "bgpd/bgp_community.h" +#include "bgpd/bgp_lcommunity.h" + +struct bgp_zebra_opaque { + char aspath[ASPATH_STR_DEFAULT_LEN]; + + /* Show at least 10 communities AA:BB */ + char community[COMMUNITY_SIZE * 20]; + + /* Show at least 10 large-communities AA:BB:CC */ + char lcommunity[LCOMMUNITY_SIZE * 30]; +}; + +#endif /* FRR_ROUTE_OPAQUE_H */ diff --git a/lib/subdir.am b/lib/subdir.am index 480c2938d0..4015c67ea8 100644 --- a/lib/subdir.am +++ b/lib/subdir.am @@ -247,6 +247,7 @@ pkginclude_HEADERS += \ lib/queue.h \ lib/ringbuf.h \ lib/routemap.h \ + lib/route_opaque.h \ lib/sbuf.h \ lib/seqlock.h \ lib/sha256.h \ @@ -675,7 +675,7 @@ int vrf_handler_create(struct vty *vty, const char *vrfname, if (strlen(vrfname) > VRF_NAMSIZ) { if (vty) vty_out(vty, - "%% VRF name %s invalid: length exceeds %d bytes", + "%% VRF name %s invalid: length exceeds %d bytes\n", vrfname, VRF_NAMSIZ); else flog_warn( diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c index 96dcdba68f..245e5dcd3d 100644 --- a/ospf6d/ospf6_asbr.c +++ b/ospf6d/ospf6_asbr.c @@ -1282,7 +1282,7 @@ void ospf6_asbr_redistribute_add(int type, ifindex_t ifindex, /* create new entry */ route = ospf6_route_create(); route->type = OSPF6_DEST_TYPE_NETWORK; - memcpy(&route->prefix, prefix, sizeof(struct prefix)); + prefix_copy(&route->prefix, prefix); info = (struct ospf6_external_info *)XCALLOC( MTYPE_OSPF6_EXTERNAL_INFO, sizeof(struct ospf6_external_info)); diff --git a/tests/topotests/zebra_opaque/__init__.py b/tests/topotests/zebra_opaque/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/topotests/zebra_opaque/__init__.py diff --git a/tests/topotests/zebra_opaque/r1/bgpd.conf b/tests/topotests/zebra_opaque/r1/bgpd.conf new file mode 100644 index 0000000000..b0eac45bba --- /dev/null +++ b/tests/topotests/zebra_opaque/r1/bgpd.conf @@ -0,0 +1,5 @@ +! +router bgp 65001 + no bgp ebgp-requires-policy + neighbor 192.168.1.2 remote-as external +! diff --git a/tests/topotests/zebra_opaque/r1/zebra.conf b/tests/topotests/zebra_opaque/r1/zebra.conf new file mode 100644 index 0000000000..b29940f46a --- /dev/null +++ b/tests/topotests/zebra_opaque/r1/zebra.conf @@ -0,0 +1,4 @@ +! +int r1-eth0 + ip address 192.168.1.1/24 +! diff --git a/tests/topotests/zebra_opaque/r2/bgpd.conf b/tests/topotests/zebra_opaque/r2/bgpd.conf new file mode 100644 index 0000000000..517ef70f2a --- /dev/null +++ b/tests/topotests/zebra_opaque/r2/bgpd.conf @@ -0,0 +1,12 @@ +router bgp 65002 + no bgp ebgp-requires-policy + neighbor 192.168.1.1 remote-as external + address-family ipv4 unicast + redistribute connected + neighbor 192.168.1.1 route-map r1 out + exit-address-family +! +route-map r1 permit 10 + set community 65002:1 65002:2 + set large-community 65002:1:1 65002:2:1 +! diff --git a/tests/topotests/zebra_opaque/r2/zebra.conf b/tests/topotests/zebra_opaque/r2/zebra.conf new file mode 100644 index 0000000000..cffe827363 --- /dev/null +++ b/tests/topotests/zebra_opaque/r2/zebra.conf @@ -0,0 +1,4 @@ +! +int r2-eth0 + ip address 192.168.1.2/24 +! diff --git a/tests/topotests/zebra_opaque/test_zebra_opaque.py b/tests/topotests/zebra_opaque/test_zebra_opaque.py new file mode 100644 index 0000000000..cc52fbd1a7 --- /dev/null +++ b/tests/topotests/zebra_opaque/test_zebra_opaque.py @@ -0,0 +1,104 @@ +#!/usr/bin/env python + +# Copyright (c) 2021 by +# Donatas Abraitis <donatas.abraitis@gmail.com> +# +# 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 NETDEF DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF 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 if Opaque Data is accessable from other daemons in Zebra +""" + +import os +import sys +import json +import time +import pytest +import functools + +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(CWD, "../")) + +# pylint: disable=C0413 +from lib import topotest +from lib.topogen import Topogen, TopoRouter, get_topogen +from lib.topolog import logger +from mininet.topo import Topo + + +class TemplateTopo(Topo): + def build(self, *_args, **_opts): + tgen = get_topogen(self) + + for routern in range(1, 3): + tgen.add_router("r{}".format(routern)) + + switch = tgen.add_switch("s1") + switch.add_link(tgen.gears["r1"]) + switch.add_link(tgen.gears["r2"]) + + +def setup_module(mod): + tgen = Topogen(TemplateTopo, mod.__name__) + tgen.start_topology() + + router_list = tgen.routers() + + for i, (rname, router) in enumerate(router_list.items(), 1): + router.load_config( + TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname)) + ) + router.load_config( + TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname)) + ) + + tgen.start_router() + + +def teardown_module(mod): + tgen = get_topogen() + tgen.stop_topology() + + +def test_zebra_opaque(): + tgen = get_topogen() + + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + router = tgen.gears["r1"] + + def _bgp_converge(router): + output = json.loads(router.vtysh_cmd("show ip route 192.168.1.0/24 json")) + expected = { + "192.168.1.0/24": [ + { + "communities": "65002:1 65002:2", + "largeCommunities": "65002:1:1 65002:2:1", + } + ] + } + return topotest.json_cmp(output, expected) + + test_func = functools.partial(_bgp_converge, router) + success, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5) + + assert result is None, 'Cannot see BGP community aliases "{}"'.format(router) + + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index 8061f34d2b..861600596e 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -42,6 +42,7 @@ #include "zebra/redistribute.h" #include "zebra/zebra_routemap.h" #include "lib/json.h" +#include "lib/route_opaque.h" #include "zebra/zebra_vxlan.h" #include "zebra/zebra_evpn_mh.h" #ifndef VTYSH_EXTRACT_PL @@ -421,6 +422,8 @@ static void show_nexthop_detail_helper(struct vty *vty, static void zebra_show_ip_route_opaque(struct vty *vty, struct route_entry *re, struct json_object *json) { + struct bgp_zebra_opaque bzo = {}; + if (!re->opaque) return; @@ -433,13 +436,27 @@ static void zebra_show_ip_route_opaque(struct vty *vty, struct route_entry *re, vty_out(vty, " Opaque Data: %s", (char *)re->opaque->data); break; - case ZEBRA_ROUTE_BGP: - if (json) - json_object_string_add(json, "asPath", - (char *)re->opaque->data); - else - vty_out(vty, " AS-Path: %s", - (char *)re->opaque->data); + case ZEBRA_ROUTE_BGP: { + memcpy(&bzo, re->opaque->data, re->opaque->length); + + if (json) { + json_object_string_add(json, "asPath", bzo.aspath); + json_object_string_add(json, "communities", + bzo.community); + json_object_string_add(json, "largeCommunities", + bzo.lcommunity); + } else { + vty_out(vty, " AS-Path : %s\n", bzo.aspath); + + if (bzo.community[0] != '\0') + vty_out(vty, " Communities : %s\n", + bzo.community); + + if (bzo.lcommunity[0] != '\0') + vty_out(vty, " Large-Communities: %s\n", + bzo.lcommunity); + } + } default: break; } @@ -2530,8 +2547,8 @@ DEFPY (evpn_mh_neigh_holdtime, "Duration in seconds\n") { - return zebra_evpn_mh_neigh_holdtime_update(vty, duration, - no ? true : false); + return zebra_evpn_mh_neigh_holdtime_update(vty, duration, + no ? true : false); } DEFPY (evpn_mh_startup_delay, |
