diff options
41 files changed, 754 insertions, 139 deletions
diff --git a/bgpd/bgp_community.c b/bgpd/bgp_community.c index b034ec9f7b..2aa6a56a5e 100644 --- a/bgpd/bgp_community.c +++ b/bgpd/bgp_community.c @@ -451,9 +451,11 @@ static void set_community_string(struct community *com, bool make_json) val = comval & 0xFFFF; char buf[32]; snprintf(buf, sizeof(buf), "%u:%d", as, val); - strlcat(str, bgp_community2alias(buf), len); + const char *com2alias = bgp_community2alias(buf); + + strlcat(str, com2alias, len); if (make_json) { - json_string = json_object_new_string(buf); + json_string = json_object_new_string(com2alias); json_object_array_add(json_community_list, json_string); } diff --git a/bgpd/bgp_lcommunity.c b/bgpd/bgp_lcommunity.c index ff34937efc..fa4d4aee28 100644 --- a/bgpd/bgp_lcommunity.c +++ b/bgpd/bgp_lcommunity.c @@ -232,11 +232,13 @@ static void set_lcommunity_string(struct lcommunity *lcom, bool make_json) snprintf(lcsb, sizeof(lcsb), "%u:%u:%u", global, local1, local2); - len = strlcat(str_buf, bgp_community2alias(lcsb), str_buf_sz); + const char *com2alias = bgp_community2alias(lcsb); + + len = strlcat(str_buf, com2alias, str_buf_sz); assert((unsigned int)len < str_buf_sz); if (make_json) { - json_string = json_object_new_string(lcsb); + json_string = json_object_new_string(com2alias); json_object_array_add(json_lcommunity_list, json_string); } diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 2c792b7abf..c61aedb560 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -23,6 +23,7 @@ #include <math.h> #include "printfrr.h" +#include "frrstr.h" #include "prefix.h" #include "linklist.h" #include "memory.h" @@ -7806,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" @@ -7896,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" @@ -10570,7 +10571,6 @@ static int bgp_show_community(struct vty *vty, struct bgp *bgp, const char *comstr, int exact, afi_t afi, safi_t safi, uint8_t show_flags); - static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi, struct bgp_table *table, enum bgp_show_type type, void *output_arg, char *rd, int is_last, @@ -10647,6 +10647,48 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi, continue; } + if (type == bgp_show_type_community_alias) { + char *alias = output_arg; + char **communities; + int num; + bool found = false; + + if (pi->attr->community) { + frrstr_split(pi->attr->community->str, + " ", &communities, &num); + for (int i = 0; i < num; i++) { + const char *com2alias = + bgp_community2alias( + communities[i]); + if (strncmp(alias, com2alias, + strlen(com2alias)) + == 0) { + found = true; + break; + } + } + } + + if (!found && pi->attr->lcommunity) { + frrstr_split(pi->attr->lcommunity->str, + " ", &communities, &num); + for (int i = 0; i < num; i++) { + const char *com2alias = + bgp_community2alias( + communities[i]); + if (strncmp(alias, com2alias, + strlen(com2alias)) + == 0) { + found = true; + break; + } + } + } + + if (!found) + continue; + } + if (type == bgp_show_type_rpki) { if (dest_p->family == AF_INET || dest_p->family == AF_INET6) @@ -11920,9 +11962,10 @@ DEFPY(show_ip_bgp, show_ip_bgp_cmd, } /* BGP route print out function with JSON */ -DEFPY (show_ip_bgp_json, - show_ip_bgp_json_cmd, - "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\ +DEFPY(show_ip_bgp_json, show_ip_bgp_json_cmd, + "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR + " [" BGP_SAFI_WITH_LABEL_CMD_STR + "]]\ [all$all]\ [cidr-only\ |dampening <flap-statistics|dampened-paths>\ @@ -11933,44 +11976,41 @@ DEFPY (show_ip_bgp_json, |route-filter-translated-v4] [exact-match]\ |rpki <invalid|valid|notfound>\ |version (1-4294967295)\ + |alias WORD\ ] [json$uj [detail$detail] | wide$wide]", - SHOW_STR - IP_STR - BGP_STR - BGP_INSTANCE_HELP_STR - BGP_AFI_HELP_STR - BGP_SAFI_WITH_LABEL_HELP_STR - "Display the entries for all address families\n" - "Display only routes with non-natural netmasks\n" - "Display detailed information about dampening\n" - "Display flap statistics of routes\n" - "Display paths suppressed due to dampening\n" - "Display routes matching the communities\n" - COMMUNITY_AANN_STR - "Do not send outside local AS (well-known community)\n" - "Do not advertise to any peer (well-known community)\n" - "Do not export to next AS (well-known community)\n" - "Graceful shutdown (well-known community)\n" - "Do not export to any peer (well-known community)\n" - "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n" - "Staled Long-lived Graceful Restart VPN route (well-known community)\n" - "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n" - "Should accept local VPN route if exported and imported into different VRF (well-known community)\n" - "Should accept VPN route with local nexthop (well-known community)\n" - "RT VPNv6 route filtering (well-known community)\n" - "RT VPNv4 route filtering (well-known community)\n" - "RT translated VPNv6 route filtering (well-known community)\n" - "RT translated VPNv4 route filtering (well-known community)\n" - "Exact match of the communities\n" - "RPKI route types\n" - "A valid path as determined by rpki\n" - "A invalid path as determined by rpki\n" - "A path that has no rpki data\n" - "Display prefixes with matching version numbers\n" - "Version number and above\n" - JSON_STR - "Display detailed version of JSON output\n" - "Increase table width for longer prefixes\n") + SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR + BGP_SAFI_WITH_LABEL_HELP_STR + "Display the entries for all address families\n" + "Display only routes with non-natural netmasks\n" + "Display detailed information about dampening\n" + "Display flap statistics of routes\n" + "Display paths suppressed due to dampening\n" + "Display routes matching the communities\n" COMMUNITY_AANN_STR + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "Graceful shutdown (well-known community)\n" + "Do not export to any peer (well-known community)\n" + "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n" + "Staled Long-lived Graceful Restart VPN route (well-known community)\n" + "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n" + "Should accept local VPN route if exported and imported into different VRF (well-known community)\n" + "Should accept VPN route with local nexthop (well-known community)\n" + "RT VPNv6 route filtering (well-known community)\n" + "RT VPNv4 route filtering (well-known community)\n" + "RT translated VPNv6 route filtering (well-known community)\n" + "RT translated VPNv4 route filtering (well-known community)\n" + "Exact match of the communities\n" + "RPKI route types\n" + "A valid path as determined by rpki\n" + "A invalid path as determined by rpki\n" + "A path that has no rpki data\n" + "Display prefixes with matching version numbers\n" + "Version number and above\n" + "Display prefixes with matching BGP community alias\n" + "BGP community alias\n" JSON_STR + "Display detailed version of JSON output\n" + "Increase table width for longer prefixes\n") { afi_t afi = AFI_IP6; safi_t safi = SAFI_UNICAST; @@ -11980,6 +12020,7 @@ DEFPY (show_ip_bgp_json, int exact_match = 0; char *community = NULL; char *prefix_version = NULL; + char *bgp_community_alias = NULL; bool first = true; uint8_t show_flags = 0; enum rpki_states rpki_target_state = RPKI_NOT_BEING_USED; @@ -12056,6 +12097,12 @@ DEFPY (show_ip_bgp_json, prefix_version = argv[idx + 1]->arg; } + /* Display prefixes with matching BGP community alias */ + if (argv_find(argv, argc, "alias", &idx)) { + sh_type = bgp_show_type_community_alias; + bgp_community_alias = argv[idx + 1]->arg; + } + if (!all) { /* show bgp: AFI_IP6, show ip bgp: AFI_IP */ if (community) @@ -12066,6 +12113,10 @@ DEFPY (show_ip_bgp_json, return bgp_show(vty, bgp, afi, safi, sh_type, prefix_version, show_flags, rpki_target_state); + else if (bgp_community_alias) + return bgp_show(vty, bgp, afi, safi, sh_type, + bgp_community_alias, show_flags, + rpki_target_state); else return bgp_show(vty, bgp, afi, safi, sh_type, NULL, show_flags, rpki_target_state); @@ -12108,6 +12159,11 @@ DEFPY (show_ip_bgp_json, sh_type, prefix_version, show_flags, rpki_target_state); + else if (bgp_community_alias) + return bgp_show( + vty, bgp, afi, safi, sh_type, + bgp_community_alias, show_flags, + rpki_target_state); else bgp_show(vty, bgp, afi, safi, sh_type, NULL, show_flags, diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index e58213a688..6d6008ff55 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -42,6 +42,7 @@ enum bgp_show_type { bgp_show_type_neighbor, bgp_show_type_cidr_only, bgp_show_type_prefix_longer, + bgp_show_type_community_alias, bgp_show_type_community_all, bgp_show_type_community, bgp_show_type_community_exact, diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index e73ec20448..77f1aadff7 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -5070,7 +5070,7 @@ ALIAS_HIDDEN(neighbor_set_peer_group, neighbor_set_peer_group_hidden_cmd, DEFUN_YANG (no_neighbor_set_peer_group, no_neighbor_set_peer_group_cmd, - "no neighbor <A.B.C.D|X:X::X:X|WORD> peer-group [PGNAME]", + "no neighbor <A.B.C.D|X:X::X:X|WORD> peer-group PGNAME", NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 @@ -5091,7 +5091,7 @@ DEFUN_YANG (no_neighbor_set_peer_group, } ALIAS_HIDDEN(no_neighbor_set_peer_group, no_neighbor_set_peer_group_hidden_cmd, - "no neighbor <A.B.C.D|X:X::X:X|WORD> peer-group [PGNAME]", + "no neighbor <A.B.C.D|X:X::X:X|WORD> peer-group PGNAME", NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 "Member of the peer-group\n" "Peer-group name\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/developer/grpc.rst b/doc/developer/grpc.rst index 8029a08b73..cb164bdabf 100644 --- a/doc/developer/grpc.rst +++ b/doc/developer/grpc.rst @@ -4,6 +4,17 @@ Northbound gRPC *************** +To enable gRPC support one needs to add `--enable-grpc` when running +`configure`. Additionally, when launching each daemon one needs to request +the gRPC module be loaded and which port to bind to. This can be done by adding +`-M grpc:<port>` to the daemon's CLI arguments. + +Currently there is no gRPC "routing" so you will need to bind your gRPC +`channel` to the particular daemon's gRPC port to interact with that daemon's +gRPC northbound interface. + +The minimum version of gRPC known to work is 1.16.1. + .. _grpc-languages-bindings: Programming Language Bindings @@ -17,14 +28,277 @@ next step is to generate the FRR northbound bindings. To generate the northbound bindings you'll need the programming language binding generator tools and those are language specific. -Next sections will use Ruby as an example for writing scripts to use +C++ Example +----------- + +The next sections will use C++ as an example for accessing FRR +northbound through gRPC. + +.. _grpc-c++-generate: + +Generating C++ FRR Bindings +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Generating FRR northbound bindings for C++ example: + +:: + # Install gRPC (e.g., on Ubuntu 20.04) + sudo apt-get install libgrpc++-dev libgrpc-dev + + mkdir /tmp/frr-cpp + cd grpc + + protoc --cpp_out=/tmp/frr-cpp \ + --grpc_out=/tmp/frr-cpp \ + -I $(pwd) \ + --plugin=protoc-gen-grpc=`which grpc_cpp_plugin` \ + frr-northbound.proto + + +.. _grpc-c++-if-sample: + +Using C++ To Get Version and Interfaces State +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Below is a sample program to print all interfaces discovered. + +:: + + # test.cpp + #include <string> + #include <sstream> + #include <grpc/grpc.h> + #include <grpcpp/create_channel.h> + #include "frr-northbound.pb.h" + #include "frr-northbound.grpc.pb.h" + + int main() { + frr::GetRequest request; + frr::GetResponse reply; + grpc::ClientContext context; + grpc::Status status; + + auto channel = grpc::CreateChannel("localhost:50051", + grpc::InsecureChannelCredentials()); + auto stub = frr::Northbound::NewStub(channel); + + request.set_type(frr::GetRequest::ALL); + request.set_encoding(frr::JSON); + request.set_with_defaults(true); + request.add_path("/frr-interface:lib"); + auto stream = stub->Get(&context, request); + + std::ostringstream ss; + while (stream->Read(&reply)) + ss << reply.data().data() << std::endl; + + status = stream->Finish(); + assert(status.ok()); + std::cout << "Interface Info:\n" << ss.str() << std::endl; + } + +Below is how to compile and run the program, with the example output: + +:: + + $ g++ -o test test.cpp frr-northbound.grpc.pb.cc frr-northbound.pb.cc -lgrpc++ -lprotobuf + $ ./test + Interface Info: + { + "frr-interface:lib": { + "interface": [ + { + "name": "lo", + "vrf": "default", + "state": { + "if-index": 1, + "mtu": 0, + "mtu6": 65536, + "speed": 0, + "metric": 0, + "phy-address": "00:00:00:00:00:00" + }, + "frr-zebra:zebra": { + "state": { + "up-count": 0, + "down-count": 0, + "ptm-status": "disabled" + } + } + }, + { + "name": "r1-eth0", + "vrf": "default", + "state": { + "if-index": 2, + "mtu": 1500, + "mtu6": 1500, + "speed": 10000, + "metric": 0, + "phy-address": "02:37:ac:63:59:b9" + }, + "frr-zebra:zebra": { + "state": { + "up-count": 0, + "down-count": 0, + "ptm-status": "disabled" + } + } + } + ] + }, + "frr-zebra:zebra": { + "mcast-rpf-lookup": "mrib-then-urib", + "workqueue-hold-timer": 10, + "zapi-packets": 1000, + "import-kernel-table": { + "distance": 15 + }, + "dplane-queue-limit": 200 + } + } + + + +.. _grpc-python-example: + +Python Example +-------------- + +The next sections will use Python as an example for writing scripts to use the northbound. +.. _grpc-python-generate: + +Generating Python FRR Bindings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Generating FRR northbound bindings for Python example: + +:: + + # Install python3 virtual environment capability e.g., + sudo apt-get install python3-venv + + # Create a virtual environment for python grpc and activate + python3 -m venv venv-grpc + source venv-grpc/bin/activate + + # Install grpc requirements + pip install grpcio grpcio-tools + + mkdir /tmp/frr-python + cd grpc + + python3 -m grpc_tools.protoc \ + --python_out=/tmp/frr-python \ + --grpc_python_out=/tmp/frr-python \ + -I $(pwd) \ + frr-northbound.proto + +.. _grpc-python-if-sample: + +Using Python To Get Capabilities and Interfaces State +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Below is a sample script to print capabilities and all interfaces Python +discovered. This demostrates the 2 different RPC results one gets from gRPC, +Unary (`GetCapabilities`) and Streaming (`Get`) for the interface state. + +:: + + import grpc + import frr_northbound_pb2 + import frr_northbound_pb2_grpc + + channel = grpc.insecure_channel('localhost:50051') + stub = frr_northbound_pb2_grpc.NorthboundStub(channel) + + # Print Capabilities + request = frr_northbound_pb2.GetCapabilitiesRequest() + response = stub.GetCapabilities(request) + print(response) + + # Print Interface State and Config + request = frr_northbound_pb2.GetRequest() + request.path.append("/frr-interface:lib") + request.type=frr_northbound_pb2.GetRequest.ALL + request.encoding=frr_northbound_pb2.XML + + for r in stub.Get(request): + print(r.data.data) + +The previous script will output something like: + +:: + + frr_version: "7.7-dev-my-manual-build" + rollback_support: true + supported_modules { + name: "frr-filter" + organization: "FRRouting" + revision: "2019-07-04" + } + supported_modules { + name: "frr-interface" + organization: "FRRouting" + revision: "2020-02-05" + } + [...] + supported_encodings: JSON + supported_encodings: XML + + <lib xmlns="http://frrouting.org/yang/interface"> + <interface> + <name>lo</name> + <vrf>default</vrf> + <state> + <if-index>1</if-index> + <mtu>0</mtu> + <mtu6>65536</mtu6> + <speed>0</speed> + <metric>0</metric> + <phy-address>00:00:00:00:00:00</phy-address> + </state> + <zebra xmlns="http://frrouting.org/yang/zebra"> + <state> + <up-count>0</up-count> + <down-count>0</down-count> + </state> + </zebra> + </interface> + <interface> + <name>r1-eth0</name> + <vrf>default</vrf> + <state> + <if-index>2</if-index> + <mtu>1500</mtu> + <mtu6>1500</mtu6> + <speed>10000</speed> + <metric>0</metric> + <phy-address>f2:62:2e:f3:4c:e4</phy-address> + </state> + <zebra xmlns="http://frrouting.org/yang/zebra"> + <state> + <up-count>0</up-count> + <down-count>0</down-count> + </state> + </zebra> + </interface> + </lib> + +.. _grpc-ruby-example: + +Ruby Example +------------ + +Next sections will use Ruby as an example for writing scripts to use +the northbound. .. _grpc-ruby-generate: Generating Ruby FRR Bindings ----------------------------- +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Generating FRR northbound bindings for Ruby example: @@ -52,7 +326,7 @@ Generating FRR northbound bindings for Ruby example: .. _grpc-ruby-if-sample: Using Ruby To Get Interfaces State ----------------------------------- +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Here is a sample script to print all interfaces FRR discovered: @@ -141,7 +415,7 @@ The previous script will output something like this: .. _grpc-ruby-bfd-profile-sample: Using Ruby To Create BFD Profiles ---------------------------------- +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ In this example you'll learn how to edit configuration using JSON and programmatic (XPath) format. diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst index f6aa5d1ca0..7f653cb7b7 100644 --- a/doc/user/bgp.rst +++ b/doc/user/bgp.rst @@ -2111,6 +2111,10 @@ things on the wire. Large Community: lcommunity-1 65001:123:2 Last update: Fri Apr 16 12:51:27 2021 +.. clicmd:: show bgp [afi] [safi] [all] alias WORD [wide|json] + + Display prefixes with matching BGP community alias. + .. _bgp-using-communities-in-route-map: Using Communities in Route Maps 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/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index 04b6bdd961..fb2d790532 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -8926,7 +8926,7 @@ DEFUN (ip_ospf_area, argv_find(argv, argc, "area", &idx); areaid = argv[idx + 1]->arg; - if (ifp->vrf_id && !instance) + if (!instance) ospf = ospf_lookup_by_vrf_id(ifp->vrf_id); else ospf = ospf_lookup_instance(instance); @@ -9050,7 +9050,7 @@ DEFUN (no_ip_ospf_area, if (argv_find(argv, argc, "(1-65535)", &idx)) instance = strtol(argv[idx]->arg, NULL, 10); - if (ifp->vrf_id && !instance) + if (!instance) ospf = ospf_lookup_by_vrf_id(ifp->vrf_id); else ospf = ospf_lookup_instance(instance); diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c index f2b909e268..73dcdbddb4 100644 --- a/pimd/pim_igmp.c +++ b/pimd/pim_igmp.c @@ -1028,8 +1028,8 @@ struct igmp_sock *pim_igmp_sock_add(struct list *igmp_sock_list, sin.sin_addr = ifaddr; sin.sin_port = 0; if (bind(fd, (struct sockaddr *) &sin, sizeof(sin)) != 0) { - zlog_warn("Could not bind IGMP socket for %pI4 on %s", - &ifaddr, ifp->name); + zlog_warn("Could not bind IGMP socket for %pI4 on %s: %s(%d)", + &ifaddr, ifp->name, strerror(errno), errno); close(fd); return NULL; diff --git a/pimd/pim_oil.c b/pimd/pim_oil.c index 0a4e3e1a6f..a3ca44bb50 100644 --- a/pimd/pim_oil.c +++ b/pimd/pim_oil.c @@ -426,9 +426,11 @@ static void pim_channel_update_mute(struct channel_oil *c_oil) struct pim_interface *pim_reg_ifp; struct pim_interface *vxlan_ifp; - pim_reg_ifp = c_oil->pim->regiface->info; - if (pim_reg_ifp) - pim_channel_update_oif_mute(c_oil, pim_reg_ifp); + if (c_oil->pim->regiface) { + pim_reg_ifp = c_oil->pim->regiface->info; + if (pim_reg_ifp) + pim_channel_update_oif_mute(c_oil, pim_reg_ifp); + } vxlan_ifp = pim_vxlan_get_term_ifp(c_oil->pim); if (vxlan_ifp) pim_channel_update_oif_mute(c_oil, vxlan_ifp); diff --git a/tests/topotests/bgp_community_alias/r1/bgpd.conf b/tests/topotests/bgp_community_alias/r1/bgpd.conf index 2cf84d0b70..06113bdd2a 100644 --- a/tests/topotests/bgp_community_alias/r1/bgpd.conf +++ b/tests/topotests/bgp_community_alias/r1/bgpd.conf @@ -1,7 +1,7 @@ ! -bgp community alias 65002:1 community-r2-1 +bgp community alias 65001:1 community-r2-1 bgp community alias 65002:2 community-r2-2 -bgp community alias 65002:1:1 large-community-r2-1 +bgp community alias 65001:1:1 large-community-r2-1 ! router bgp 65001 no bgp ebgp-requires-policy diff --git a/tests/topotests/bgp_community_alias/r2/bgpd.conf b/tests/topotests/bgp_community_alias/r2/bgpd.conf index 517ef70f2a..fc67ff2ad2 100644 --- a/tests/topotests/bgp_community_alias/r2/bgpd.conf +++ b/tests/topotests/bgp_community_alias/r2/bgpd.conf @@ -6,7 +6,14 @@ router bgp 65002 neighbor 192.168.1.1 route-map r1 out exit-address-family ! +ip prefix-list p1 permit 172.16.16.1/32 +ip prefix-list p2 permit 172.16.16.2/32 +! route-map r1 permit 10 + match ip address prefix-list p1 + set community 65001:1 65001:2 + set large-community 65001:1:1 65001:1:2 +route-map r1 permit 20 + match ip address prefix-list p2 set community 65002:1 65002:2 - set large-community 65002:1:1 65002:2:1 ! diff --git a/tests/topotests/bgp_community_alias/r2/zebra.conf b/tests/topotests/bgp_community_alias/r2/zebra.conf index cffe827363..a806628a8e 100644 --- a/tests/topotests/bgp_community_alias/r2/zebra.conf +++ b/tests/topotests/bgp_community_alias/r2/zebra.conf @@ -1,4 +1,8 @@ ! +int lo + ip address 172.16.16.1/32 + ip address 172.16.16.2/32 +! int r2-eth0 ip address 192.168.1.2/24 ! diff --git a/tests/topotests/bgp_community_alias/test_bgp-community-alias.py b/tests/topotests/bgp_community_alias/test_bgp-community-alias.py index a43e5f937e..90eeaaa731 100644 --- a/tests/topotests/bgp_community_alias/test_bgp-community-alias.py +++ b/tests/topotests/bgp_community_alias/test_bgp-community-alias.py @@ -84,12 +84,14 @@ def test_bgp_community_alias(): router = tgen.gears["r1"] def _bgp_converge(router): - output = json.loads(router.vtysh_cmd("show ip bgp 192.168.1.0/24 json")) + output = json.loads( + router.vtysh_cmd("show bgp ipv4 unicast 172.16.16.1/32 json") + ) expected = { "paths": [ { - "community": {"string": "community-r2-1 community-r2-2"}, - "largeCommunity": {"string": "large-community-r2-1 65002:2:1"}, + "community": {"string": "community-r2-1 65001:2"}, + "largeCommunity": {"string": "large-community-r2-1 65001:1:2"}, } ] } @@ -97,9 +99,25 @@ def test_bgp_community_alias(): 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) + def _bgp_show_prefixes_by_alias(router): + output = json.loads( + router.vtysh_cmd("show bgp ipv4 unicast alias community-r2-2 json detail") + ) + expected = { + "routes": { + "172.16.16.2/32": [{"community": {"string": "65002:1 community-r2-2"}}] + } + } + return topotest.json_cmp(output, expected) + + test_func = functools.partial(_bgp_show_prefixes_by_alias, router) + success, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5) + assert result is None, 'Cannot see BGP prefixes by community alias "{}"'.format( + router + ) + if __name__ == "__main__": args = ["-s"] + sys.argv[1:] diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_linux_vrf.py b/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_linux_vrf.py index 650ba20b8c..f7b9bad5fa 100644 --- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_linux_vrf.py +++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_linux_vrf.py @@ -59,8 +59,8 @@ luCommand( "VRF cust1 IP config", ) luCommand( - rtr, - "ip route show vrf r4-cust2".format(rtr), + "r4", + "ip route show vrf r4-cust2", "192.168...0/24 dev r.-eth", "pass", "VRF cust2 interface route", diff --git a/tests/topotests/ospf_sr_topo1/rt1/ospfd.conf b/tests/topotests/ospf_sr_topo1/rt1/ospfd.conf index 94dba7c061..6a12ae5011 100644 --- a/tests/topotests/ospf_sr_topo1/rt1/ospfd.conf +++ b/tests/topotests/ospf_sr_topo1/rt1/ospfd.conf @@ -12,6 +12,8 @@ interface lo ! interface eth-sw1 ip ospf network broadcast + ip ospf hello-interval 2 + ip ospf dead-interval 10 ! router ospf ospf router-id 1.1.1.1 diff --git a/tests/topotests/ospf_sr_topo1/rt2/ospfd.conf b/tests/topotests/ospf_sr_topo1/rt2/ospfd.conf index b47e788062..adf4d09235 100644 --- a/tests/topotests/ospf_sr_topo1/rt2/ospfd.conf +++ b/tests/topotests/ospf_sr_topo1/rt2/ospfd.conf @@ -12,12 +12,18 @@ interface lo ! interface eth-sw1 ip ospf network broadcast + ip ospf hello-interval 2 + ip ospf dead-interval 10 ! interface eth-rt4-1 ip ospf network point-to-point + ip ospf hello-interval 2 + ip ospf dead-interval 10 ! interface eth-rt4-2 ip ospf network point-to-point + ip ospf hello-interval 2 + ip ospf dead-interval 10 ! router ospf ospf router-id 2.2.2.2 diff --git a/tests/topotests/ospf_sr_topo1/rt3/ospfd.conf b/tests/topotests/ospf_sr_topo1/rt3/ospfd.conf index 238d82ff97..c45c1069fb 100644 --- a/tests/topotests/ospf_sr_topo1/rt3/ospfd.conf +++ b/tests/topotests/ospf_sr_topo1/rt3/ospfd.conf @@ -12,12 +12,18 @@ interface lo ! interface eth-sw1 ip ospf network broadcast + ip ospf hello-interval 2 + ip ospf dead-interval 10 ! interface eth-rt5-1 ip ospf network point-to-point + ip ospf hello-interval 2 + ip ospf dead-interval 10 ! interface eth-rt5-2 ip ospf network point-to-point + ip ospf hello-interval 2 + ip ospf dead-interval 10 ! router ospf ospf router-id 3.3.3.3 diff --git a/tests/topotests/ospf_sr_topo1/rt4/ospfd.conf b/tests/topotests/ospf_sr_topo1/rt4/ospfd.conf index b12e0729ad..9853ce64cf 100644 --- a/tests/topotests/ospf_sr_topo1/rt4/ospfd.conf +++ b/tests/topotests/ospf_sr_topo1/rt4/ospfd.conf @@ -12,15 +12,23 @@ interface lo ! interface eth-rt2-1 ip ospf network point-to-point + ip ospf hello-interval 2 + ip ospf dead-interval 10 ! interface eth-rt2-2 ip ospf network point-to-point + ip ospf hello-interval 2 + ip ospf dead-interval 10 ! interface eth-rt5 ip ospf network point-to-point + ip ospf hello-interval 2 + ip ospf dead-interval 10 ! interface eth-rt6 ip ospf network point-to-point + ip ospf hello-interval 2 + ip ospf dead-interval 10 ! router ospf ospf router-id 4.4.4.4 diff --git a/tests/topotests/ospf_sr_topo1/rt5/ospfd.conf b/tests/topotests/ospf_sr_topo1/rt5/ospfd.conf index 4e7b24c03a..e6a755c430 100644 --- a/tests/topotests/ospf_sr_topo1/rt5/ospfd.conf +++ b/tests/topotests/ospf_sr_topo1/rt5/ospfd.conf @@ -12,15 +12,23 @@ interface lo ! interface eth-rt3-1 ip ospf network point-to-point + ip ospf hello-interval 2 + ip ospf dead-interval 10 ! interface eth-rt3-2 ip ospf network point-to-point + ip ospf hello-interval 2 + ip ospf dead-interval 10 ! interface eth-rt4 ip ospf network point-to-point + ip ospf hello-interval 2 + ip ospf dead-interval 10 ! interface eth-rt6 ip ospf network point-to-point + ip ospf hello-interval 2 + ip ospf dead-interval 10 ! router ospf ospf router-id 5.5.5.5 diff --git a/tests/topotests/ospf_sr_topo1/rt6/ospfd.conf b/tests/topotests/ospf_sr_topo1/rt6/ospfd.conf index c6d07d169e..1ec71e4454 100644 --- a/tests/topotests/ospf_sr_topo1/rt6/ospfd.conf +++ b/tests/topotests/ospf_sr_topo1/rt6/ospfd.conf @@ -12,9 +12,13 @@ interface lo ! interface eth-rt4 ip ospf network point-to-point + ip ospf hello-interval 2 + ip ospf dead-interval 10 ! interface eth-rt5 ip ospf network point-to-point + ip ospf hello-interval 2 + ip ospf dead-interval 10 ! router ospf ospf router-id 6.6.6.6 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/yang/frr-bgp-neighbor.yang b/yang/frr-bgp-neighbor.yang index d6688eed29..03af643ba2 100644 --- a/yang/frr-bgp-neighbor.yang +++ b/yang/frr-bgp-neighbor.yang @@ -90,8 +90,6 @@ submodule frr-bgp-neighbor { "Don't send open messages to this neighbor."; } - uses structure-neighbor-group-capability-options; - uses neighbor-update-source; uses structure-neighbor-group-ebgp-multihop; diff --git a/yang/frr-bgp-peer-group.yang b/yang/frr-bgp-peer-group.yang index 746ced30cc..80c9ecff2a 100644 --- a/yang/frr-bgp-peer-group.yang +++ b/yang/frr-bgp-peer-group.yang @@ -76,6 +76,8 @@ submodule frr-bgp-peer-group { uses neighbor-remote-as; uses neighbor-parameters; + + uses structure-neighbor-group-capability-options; } grouping bgp-peer-group-list { diff --git a/yang/frr-bgp.yang b/yang/frr-bgp.yang index a779bb2054..0e15195dd5 100644 --- a/yang/frr-bgp.yang +++ b/yang/frr-bgp.yang @@ -11,10 +11,6 @@ module frr-bgp { prefix inet; } - import ietf-routing-types { - prefix rt-types; - } - import frr-interface { prefix frr-interface; } @@ -23,6 +19,10 @@ module frr-bgp { prefix frr-bt; } + import frr-route-types { + prefix frr-route-types; + } + include "frr-bgp-common"; include "frr-bgp-common-structure"; @@ -230,6 +230,8 @@ module frr-bgp { } uses neighbor-parameters; + + uses structure-neighbor-group-capability-options; } list unnumbered-neighbor { @@ -264,6 +266,12 @@ module frr-bgp { uses neighbor-remote-as; uses neighbor-parameters; + + uses structure-neighbor-group-capability-options { + refine "frr-bgp:capability-options/extended-nexthop-capability" { + default "true"; + } + } } } @@ -405,7 +413,7 @@ module frr-bgp { description "A list of network routes."; leaf prefix { - type rt-types:ipv4-multicast-group-address; + type frr-route-types:ipv4-multicast-group-prefix; description "IPv4 multicast destination prefix."; } @@ -425,7 +433,7 @@ module frr-bgp { description "A list of aggregated routes."; leaf prefix { - type rt-types:ipv4-multicast-group-address; + type frr-route-types:ipv4-multicast-group-prefix; description "IPv4 multicast destination prefix."; } @@ -438,7 +446,7 @@ module frr-bgp { description "A list of routes with a particular admin distance."; leaf prefix { - type rt-types:ipv4-multicast-group-address; + type frr-route-types:ipv4-multicast-group-prefix; description "IPv4 multicast destination prefix."; } @@ -459,7 +467,7 @@ module frr-bgp { description "A list of network routes."; leaf prefix { - type rt-types:ipv6-multicast-group-address; + type frr-route-types:ipv6-multicast-group-prefix; description "IPv6 multicast destination prefix."; } @@ -479,7 +487,7 @@ module frr-bgp { description "A list of aggregated routes."; leaf prefix { - type rt-types:ipv6-multicast-group-address; + type frr-route-types:ipv6-multicast-group-prefix; description "IPv6 multicast destination prefix."; } @@ -492,7 +500,7 @@ module frr-bgp { description "A list of routes with a particular admin distance."; leaf prefix { - type rt-types:ipv6-multicast-group-address; + type frr-route-types:ipv6-multicast-group-prefix; description "IPv6 multicast destination prefix."; } diff --git a/yang/frr-pim-rp.yang b/yang/frr-pim-rp.yang index a2eca5100a..33b453b299 100644 --- a/yang/frr-pim-rp.yang +++ b/yang/frr-pim-rp.yang @@ -8,10 +8,6 @@ module frr-pim-rp { prefix "inet"; } - import ietf-routing-types { - prefix "rt-types"; - } - import frr-routing { prefix "frr-rt"; } @@ -20,6 +16,10 @@ module frr-pim-rp { prefix "frr-pim"; } + import frr-route-types { + prefix frr-route-types; + } + organization "FRRouting"; @@ -63,37 +63,6 @@ module frr-pim-rp { "RFC XXXX: A YANG Data Model for PIM RP"; } - typedef ipv4-multicast-group-address-prefix { - type inet:ipv4-prefix{ - pattern '(2((2[4-9])|(3[0-9]))\.)(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){2}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(/(([4-9])|([1-2][0-9])|(3[0-2])))'; - } - description - "This type represents an IPv4 multicast group prefix, - which is in the range from 224.0.0.0 to 239.255.255.255."; - } - - typedef ipv6-multicast-group-address-prefix { - type inet:ipv6-prefix { - pattern - '(((FF|ff)[0-9a-fA-F]{2}):)([0-9a-fA-F]{0,4}:){0,5}((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))(/((1[6-9])|([2-9][0-9])|(1[0-1][0-9])|(12[0-8])))'; - pattern - '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)(/.+)'; - } - description - "This type represents an IPv6 multicast group prefix, - which is in the range of FF00::/8."; - } - - typedef ip-multicast-group-address-prefix { - description "The IP-Multicast-Group-Address-Prefix type represents an IP multicast address - prefix and is IP version neutral. The format of the textual representations implies the IP - version. It includes a prefix-length, separated by a '/' sign."; - type union { - type ipv4-multicast-group-address-prefix; - type ipv6-multicast-group-address-prefix; - } - } // typedef ip-multicast-group-address-prefix - typedef plist-ref { type string; } @@ -124,7 +93,7 @@ module frr-pim-rp { description "Use group-list or prefix-list"; case group-list { leaf-list group-list{ - type ip-multicast-group-address-prefix; + type frr-route-types:ip-multicast-group-prefix; description "List of multicast group address."; } diff --git a/yang/frr-route-types.yang b/yang/frr-route-types.yang index 5a0f58071f..aeb52a6520 100644 --- a/yang/frr-route-types.yang +++ b/yang/frr-route-types.yang @@ -3,6 +3,10 @@ module frr-route-types { namespace "http://frrouting.org/yang/route-types"; prefix frr-route-types; + import ietf-inet-types { + prefix inet; + } + organization "FRRouting"; contact @@ -145,4 +149,35 @@ module frr-route-types { type frr-route-types-v6; } } + + typedef ipv4-multicast-group-prefix { + type inet:ipv4-prefix { + pattern '(2((2[4-9])|(3[0-9]))\.)(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){2}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(/(([4-9])|([1-2][0-9])|(3[0-2])))'; + } + description + "This type represents an IPv4 multicast group prefix, + which is in the range from 224.0.0.0 to 239.255.255.255."; + } + + typedef ipv6-multicast-group-prefix { + type inet:ipv6-prefix { + pattern + '(((FF|ff)[0-9a-fA-F]{2}):)([0-9a-fA-F]{0,4}:){0,5}((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))(/((1[6-9])|([2-9][0-9])|(1[0-1][0-9])|(12[0-8])))'; + pattern + '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)(/.+)'; + } + description + "This type represents an IPv6 multicast group prefix, + which is in the range of FF00::/8."; + } + + typedef ip-multicast-group-prefix { + description "The IP-Multicast-Group-Address-Prefix type represents an IP multicast address + prefix and is IP version neutral. The format of the textual representations implies the IP + version. It includes a prefix-length, separated by a '/' sign."; + type union { + type ipv4-multicast-group-prefix; + type ipv6-multicast-group-prefix; + } + } } 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, |
