diff options
77 files changed, 1098 insertions, 456 deletions
diff --git a/bgpd/bgp_nb.c b/bgpd/bgp_nb.c index 71824cd6d3..a4249990ae 100644 --- a/bgpd/bgp_nb.c +++ b/bgpd/bgp_nb.c @@ -635,9 +635,9 @@ const struct frr_yang_module_info frr_bgp_info = { } }, { - .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-bgp:bgp/neighbors/neighbor/local-as/no-replace-as", + .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-bgp:bgp/neighbors/neighbor/local-as/replace-as", .cbs = { - .modify = bgp_neighbors_neighbor_local_as_no_replace_as_modify, + .modify = bgp_neighbors_neighbor_local_as_replace_as_modify, } }, { @@ -925,9 +925,9 @@ const struct frr_yang_module_info frr_bgp_info = { } }, { - .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-bgp:bgp/neighbors/unnumbered-neighbor/local-as/no-replace-as", + .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-bgp:bgp/neighbors/unnumbered-neighbor/local-as/replace-as", .cbs = { - .modify = bgp_neighbors_unnumbered_neighbor_local_as_no_replace_as_modify, + .modify = bgp_neighbors_unnumbered_neighbor_local_as_replace_as_modify, } }, { @@ -1216,9 +1216,9 @@ const struct frr_yang_module_info frr_bgp_info = { } }, { - .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-bgp:bgp/peer-groups/peer-group/local-as/no-replace-as", + .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-bgp:bgp/peer-groups/peer-group/local-as/replace-as", .cbs = { - .modify = bgp_peer_groups_peer_group_local_as_no_replace_as_modify, + .modify = bgp_peer_groups_peer_group_local_as_replace_as_modify, } }, { diff --git a/bgpd/bgp_nb.h b/bgpd/bgp_nb.h index f8bb31aad6..ec4a4b6ab7 100644 --- a/bgpd/bgp_nb.h +++ b/bgpd/bgp_nb.h @@ -233,7 +233,7 @@ int bgp_neighbors_neighbor_local_as_local_as_destroy( struct nb_cb_destroy_args *args); int bgp_neighbors_neighbor_local_as_no_prepend_modify( struct nb_cb_modify_args *args); -int bgp_neighbors_neighbor_local_as_no_replace_as_modify( +int bgp_neighbors_neighbor_local_as_replace_as_modify( struct nb_cb_modify_args *args); int bgp_neighbors_neighbor_bfd_options_enable_modify( struct nb_cb_modify_args *args); @@ -365,7 +365,7 @@ int bgp_neighbors_unnumbered_neighbor_local_as_local_as_destroy( struct nb_cb_destroy_args *args); int bgp_neighbors_unnumbered_neighbor_local_as_no_prepend_modify( struct nb_cb_modify_args *args); -int bgp_neighbors_unnumbered_neighbor_local_as_no_replace_as_modify( +int bgp_neighbors_unnumbered_neighbor_local_as_replace_as_modify( struct nb_cb_modify_args *args); int bgp_neighbors_unnumbered_neighbor_bfd_options_enable_modify( struct nb_cb_modify_args *args); @@ -497,7 +497,7 @@ int bgp_peer_groups_peer_group_local_as_local_as_destroy( struct nb_cb_destroy_args *args); int bgp_peer_groups_peer_group_local_as_no_prepend_modify( struct nb_cb_modify_args *args); -int bgp_peer_groups_peer_group_local_as_no_replace_as_modify( +int bgp_peer_groups_peer_group_local_as_replace_as_modify( struct nb_cb_modify_args *args); int bgp_peer_groups_peer_group_bfd_options_enable_modify( struct nb_cb_modify_args *args); diff --git a/bgpd/bgp_nb_config.c b/bgpd/bgp_nb_config.c index a430124b51..3b7d95c0f3 100644 --- a/bgpd/bgp_nb_config.c +++ b/bgpd/bgp_nb_config.c @@ -3472,9 +3472,8 @@ void bgp_neighbors_neighbor_local_as_apply_finish( as = yang_dnode_get_uint32(args->dnode, "./local-as"); if (yang_dnode_exists(args->dnode, "./no-prepend")) no_prepend = yang_dnode_get_bool(args->dnode, "./no-prepend"); - if (yang_dnode_exists(args->dnode, "./no-replace-as")) - replace_as = - yang_dnode_get_bool(args->dnode, "./no-replace-as"); + if (yang_dnode_exists(args->dnode, "./replace-as")) + replace_as = yang_dnode_get_bool(args->dnode, "./replace-as"); if (!as && !no_prepend && !replace_as) ret = peer_local_as_unset(peer); @@ -3557,9 +3556,9 @@ int bgp_neighbors_neighbor_local_as_no_prepend_modify( /* * XPath: - * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-bgp:bgp/neighbors/neighbor/local-as/no-replace-as + * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-bgp:bgp/neighbors/neighbor/local-as/replace-as */ -int bgp_neighbors_neighbor_local_as_no_replace_as_modify( +int bgp_neighbors_neighbor_local_as_replace_as_modify( struct nb_cb_modify_args *args) { switch (args->event) { @@ -5491,9 +5490,8 @@ void bgp_neighbors_unnumbered_neighbor_local_as_apply_finish( as = yang_dnode_get_uint32(args->dnode, "./local-as"); if (yang_dnode_exists(args->dnode, "./no-prepend")) no_prepend = yang_dnode_get_bool(args->dnode, "./no-prepend"); - if (yang_dnode_exists(args->dnode, "./no-replace-as")) - replace_as = - yang_dnode_get_bool(args->dnode, "./no-replace-as"); + if (yang_dnode_exists(args->dnode, "./replace-as")) + replace_as = yang_dnode_get_bool(args->dnode, "./replace-as"); if (!as && !no_prepend && !replace_as) ret = peer_local_as_unset(peer); @@ -5558,9 +5556,9 @@ int bgp_neighbors_unnumbered_neighbor_local_as_no_prepend_modify( /* * XPath: - * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-bgp:bgp/neighbors/unnumbered-neighbor/local-as/no-replace-as + * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-bgp:bgp/neighbors/unnumbered-neighbor/local-as/replace-as */ -int bgp_neighbors_unnumbered_neighbor_local_as_no_replace_as_modify( +int bgp_neighbors_unnumbered_neighbor_local_as_replace_as_modify( struct nb_cb_modify_args *args) { switch (args->event) { @@ -7378,9 +7376,8 @@ void bgp_peer_groups_peer_group_local_as_apply_finish( as = yang_dnode_get_uint32(args->dnode, "./local-as"); if (yang_dnode_exists(args->dnode, "./no-prepend")) no_prepend = yang_dnode_get_bool(args->dnode, "./no-prepend"); - if (yang_dnode_exists(args->dnode, "./no-replace-as")) - replace_as = - yang_dnode_get_bool(args->dnode, "./no-replace-as"); + if (yang_dnode_exists(args->dnode, "./replace-as")) + replace_as = yang_dnode_get_bool(args->dnode, "./replace-as"); if (!as && !no_prepend && !replace_as) ret = peer_local_as_unset(peer); @@ -7460,9 +7457,9 @@ int bgp_peer_groups_peer_group_local_as_no_prepend_modify( /* * XPath: - * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-bgp:bgp/peer-groups/peer-group/local-as/no-replace-as + * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-bgp:bgp/peer-groups/peer-group/local-as/replace-as */ -int bgp_peer_groups_peer_group_local_as_no_replace_as_modify( +int bgp_peer_groups_peer_group_local_as_replace_as_modify( struct nb_cb_modify_args *args) { switch (args->event) { diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 9c02dba6cc..77f1aadff7 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -4829,7 +4829,7 @@ DEFUN_YANG( argv[idx_number]->arg); nb_cli_enqueue_change(vty, "./local-as/no-prepend", NB_OP_MODIFY, "true"); - nb_cli_enqueue_change(vty, "./local-as/no-replace-as", NB_OP_MODIFY, + nb_cli_enqueue_change(vty, "./local-as/replace-as", NB_OP_MODIFY, "true"); return nb_cli_apply_changes(vty, base_xpath); @@ -4855,7 +4855,7 @@ DEFUN_YANG(no_neighbor_local_as, nb_cli_enqueue_change(vty, "./local-as/local-as", NB_OP_DESTROY, NULL); nb_cli_enqueue_change(vty, "./local-as/no-prepend", NB_OP_MODIFY, "false"); - nb_cli_enqueue_change(vty, "./local-as/no-replace-as", NB_OP_MODIFY, + nb_cli_enqueue_change(vty, "./local-as/replace-as", NB_OP_MODIFY, "false"); return nb_cli_apply_changes(vty, base_xpath); diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 63214c5676..2bf57130be 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -2609,6 +2609,9 @@ static void bgp_zebra_connected(struct zclient *zclient) zclient_num_connects++; /* increment even if not responding */ + /* Send the client registration */ + bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER, VRF_DEFAULT); + /* At this point, we may or may not have BGP instances configured, but * we're only interested in the default VRF (others wouldn't have learnt * the VRF from Zebra yet.) @@ -2619,9 +2622,6 @@ static void bgp_zebra_connected(struct zclient *zclient) bgp_zebra_instance_register(bgp); - /* Send the client registration */ - bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER, bgp->vrf_id); - /* tell label pool that zebra is connected */ bgp_lp_event_zebra_up(); diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 5991bff752..6f2f2c9f34 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -671,6 +671,7 @@ int bgp_confederation_peers_add(struct bgp *bgp, as_t as) if (bgp_config_check(bgp, BGP_CONFIG_CONFEDERATION)) { for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { if (peer->as == as) { + (void)peer_sort(peer); peer->local_as = bgp->as; if (BGP_IS_VALID_STATE_FOR_NOTIF( peer->status)) { @@ -722,6 +723,7 @@ int bgp_confederation_peers_remove(struct bgp *bgp, as_t as) if (bgp_config_check(bgp, BGP_CONFIG_CONFEDERATION)) { for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { if (peer->as == as) { + (void)peer_sort(peer); peer->local_as = bgp->confed_id; if (BGP_IS_VALID_STATE_FOR_NOTIF( peer->status)) { 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/pathd.rst b/doc/user/pathd.rst index c40efffc88..4c7611bc04 100644 --- a/doc/user/pathd.rst +++ b/doc/user/pathd.rst @@ -149,7 +149,7 @@ Configuration Commands Delete or start a dynamic candidate path definition. -.. clicmd:: affinity {exclude-any|include-any|include-all} BITPATTERN +.. clicmd:: affinity <exclude-any|include-any|include-all> BITPATTERN Delete or specify an affinity constraint for a dynamic candidate path. diff --git a/isisd/isis_main.c b/isisd/isis_main.c index c93bbb83af..acfa1a29d4 100644 --- a/isisd/isis_main.c +++ b/isisd/isis_main.c @@ -265,9 +265,6 @@ int main(int argc, char **argv, char **envp) lsp_init(); mt_init(); - /* create the global 'isis' instance */ - isis_global_instance_create(VRF_DEFAULT_NAME); - isis_zebra_init(master, instance); isis_bfd_init(master); isis_ldp_sync_init(); diff --git a/isisd/isis_nb_config.c b/isisd/isis_nb_config.c index 68a4581a46..a00c86eeaf 100644 --- a/isisd/isis_nb_config.c +++ b/isisd/isis_nb_config.c @@ -68,7 +68,7 @@ int isis_instance_create(struct nb_cb_create_args *args) return NB_OK; vrf_name = yang_dnode_get_string(args->dnode, "./vrf"); area_tag = yang_dnode_get_string(args->dnode, "./area-tag"); - isis_global_instance_create(vrf_name); + area = isis_area_lookup_by_vrf(area_tag, vrf_name); if (area) return NB_ERR_INCONSISTENCY; diff --git a/isisd/isis_redist.c b/isisd/isis_redist.c index c33d56e625..2f5e490da1 100644 --- a/isisd/isis_redist.c +++ b/isisd/isis_redist.c @@ -56,7 +56,7 @@ static int redist_protocol(int family) return 0; } -static afi_t afi_for_redist_protocol(int protocol) +afi_t afi_for_redist_protocol(int protocol) { if (protocol == 0) return AFI_IP; @@ -350,6 +350,9 @@ static void isis_redist_update_zebra_subscriptions(struct isis *isis) int level; int protocol; + if (isis->vrf_id == VRF_UNKNOWN) + return; + char do_subscribe[REDIST_PROTOCOL_COUNT][ZEBRA_ROUTE_MAX + 1]; memset(do_subscribe, 0, sizeof(do_subscribe)); @@ -359,8 +362,9 @@ static void isis_redist_update_zebra_subscriptions(struct isis *isis) for (type = 0; type < ZEBRA_ROUTE_MAX + 1; type++) for (level = 0; level < ISIS_LEVELS; level++) if (area->redist_settings[protocol] - [type] - [level].redist) + [type][level] + .redist + == 1) do_subscribe[protocol][type] = 1; @@ -377,20 +381,29 @@ static void isis_redist_update_zebra_subscriptions(struct isis *isis) afi_t afi = afi_for_redist_protocol(protocol); if (do_subscribe[protocol][type]) - isis_zebra_redistribute_set(afi, type); + isis_zebra_redistribute_set(afi, type, + isis->vrf_id); else - isis_zebra_redistribute_unset(afi, type); + isis_zebra_redistribute_unset(afi, type, + isis->vrf_id); } } void isis_redist_free(struct isis *isis) { + struct route_node *rn; int i; for (i = 0; i < REDIST_PROTOCOL_COUNT; i++) { if (!isis->ext_info[i]) continue; + for (rn = route_top(isis->ext_info[i]); rn; + rn = srcdest_route_next(rn)) { + if (rn->info) + XFREE(MTYPE_ISIS_EXT_INFO, rn->info); + } + route_table_finish(isis->ext_info[i]); isis->ext_info[i] = NULL; } @@ -498,6 +511,7 @@ void isis_redist_unset(struct isis_area *area, int level, int family, int type) void isis_redist_area_finish(struct isis_area *area) { + struct route_node *rn; int protocol; int level; int type; @@ -512,7 +526,15 @@ void isis_redist_area_finish(struct isis_area *area) redist->redist = 0; XFREE(MTYPE_ISIS_RMAP_NAME, redist->map_name); } + if (!area->ext_reach[protocol][level]) + continue; + for (rn = route_top(area->ext_reach[protocol][level]); + rn; rn = srcdest_route_next(rn)) { + if (rn->info) + XFREE(MTYPE_ISIS_EXT_INFO, rn->info); + } route_table_finish(area->ext_reach[protocol][level]); + area->ext_reach[protocol][level] = NULL; } isis_redist_update_zebra_subscriptions(area->isis); diff --git a/isisd/isis_redist.h b/isisd/isis_redist.h index fcc4ceadf4..10dccbc518 100644 --- a/isisd/isis_redist.h +++ b/isisd/isis_redist.h @@ -47,6 +47,8 @@ struct prefix; struct prefix_ipv6; struct vty; +afi_t afi_for_redist_protocol(int protocol); + struct route_table *get_ext_reach(struct isis_area *area, int family, int level); void isis_redist_add(struct isis *isis, int type, struct prefix *p, diff --git a/isisd/isis_snmp.c b/isisd/isis_snmp.c index dfc865162f..fa2f9a7669 100644 --- a/isisd/isis_snmp.c +++ b/isisd/isis_snmp.c @@ -616,11 +616,44 @@ static uint8_t isis_null_sysid[ISIS_SYS_ID_LEN]; #define ISIS_SNMP_ADJ_STATE_UP (3) #define ISIS_SNMP_ADJ_STATE_FAILED (4) +static inline uint32_t isis_snmp_adj_state(enum isis_adj_state state) +{ + switch (state) { + case ISIS_ADJ_UNKNOWN: + return ISIS_SNMP_ADJ_STATE_DOWN; + case ISIS_ADJ_INITIALIZING: + return ISIS_SNMP_ADJ_STATE_INITIALIZING; + case ISIS_ADJ_UP: + return ISIS_SNMP_ADJ_STATE_UP; + case ISIS_ADJ_DOWN: + return ISIS_SNMP_ADJ_STATE_FAILED; + } + + return 0; /* not reached */ +} + #define ISIS_SNMP_ADJ_NEIGHTYPE_IS_L1 (1) #define ISIS_SNMP_ADJ_NEIGHTYPE_IS_L2 (2) #define ISIS_SNMP_ADJ_NEIGHTYPE_IS_L1_L2 (3) #define ISIS_SNMP_ADJ_NEIGHTYPE_UNKNOWN (4) +static inline uint32_t isis_snmp_adj_neightype(enum isis_system_type type) +{ + switch (type) { + case ISIS_SYSTYPE_UNKNOWN: + case ISIS_SYSTYPE_ES: + return ISIS_SNMP_ADJ_NEIGHTYPE_UNKNOWN; + case ISIS_SYSTYPE_IS: + return ISIS_SNMP_ADJ_NEIGHTYPE_IS_L1_L2; + case ISIS_SYSTYPE_L1_IS: + return ISIS_SNMP_ADJ_NEIGHTYPE_IS_L1; + case ISIS_SYSTYPE_L2_IS: + return ISIS_SNMP_ADJ_NEIGHTYPE_IS_L2; + } + + return 0; /* not reached */ +} + #define ISIS_SNMP_INET_TYPE_V4 (1) #define ISIS_SNMP_INET_TYPE_V6 (2) @@ -2510,23 +2543,7 @@ static uint8_t *isis_snmp_find_isadj(struct variable *v, oid *name, switch (v->magic) { case ISIS_ISADJ_STATE: - - switch (adj->adj_state) { - case ISIS_ADJ_UNKNOWN: - case ISIS_ADJ_DOWN: - val = ISIS_SNMP_ADJ_STATE_DOWN; - break; - - case ISIS_ADJ_INITIALIZING: - val = ISIS_SNMP_ADJ_STATE_INITIALIZING; - break; - - case ISIS_ADJ_UP: - val = ISIS_SNMP_ADJ_STATE_UP; - break; - } - - return SNMP_INTEGER(val); + return SNMP_INTEGER(isis_snmp_adj_state(adj->adj_state)); case ISIS_ISADJ_3WAYSTATE: return SNMP_INTEGER(adj->threeway_state); @@ -2538,27 +2555,7 @@ static uint8_t *isis_snmp_find_isadj(struct variable *v, oid *name, } case ISIS_ISADJ_NEIGHSYSTYPE: - - switch (adj->sys_type) { - case ISIS_SYSTYPE_UNKNOWN: - case ISIS_SYSTYPE_ES: - val = ISIS_SNMP_ADJ_NEIGHTYPE_UNKNOWN; - break; - - case ISIS_SYSTYPE_IS: - val = ISIS_SNMP_ADJ_NEIGHTYPE_IS_L1_L2; - break; - - case ISIS_SYSTYPE_L1_IS: - val = ISIS_SNMP_ADJ_NEIGHTYPE_IS_L1; - break; - - case ISIS_SYSTYPE_L2_IS: - val = ISIS_SNMP_ADJ_NEIGHTYPE_IS_L2; - break; - } - - return SNMP_INTEGER(val); + return SNMP_INTEGER(isis_snmp_adj_neightype(adj->sys_type)); case ISIS_ISADJ_NEIGHSYSID: *var_len = sizeof(adj->sysid); @@ -3345,25 +3342,7 @@ static int isis_snmp_adj_state_change_update(const struct isis_adjacency *adj) lsp_id[ISIS_SYS_ID_LEN] = 0; lsp_id[ISIS_SYS_ID_LEN + 1] = 0; - val = ISIS_SNMP_ADJ_STATE_DOWN; - - switch (adj->adj_state) { - case ISIS_ADJ_UNKNOWN: - val = ISIS_SNMP_ADJ_STATE_DOWN; - break; - - case ISIS_ADJ_INITIALIZING: - val = ISIS_SNMP_ADJ_STATE_INITIALIZING; - break; - - case ISIS_ADJ_UP: - val = ISIS_SNMP_ADJ_STATE_UP; - break; - - case ISIS_ADJ_DOWN: - val = ISIS_SNMP_ADJ_STATE_FAILED; - break; - } + val = isis_snmp_adj_state(adj->adj_state); isis_snmp_update_worker_b( adj->circuit, ISIS_TRAP_ADJ_STATE_CHANGE, diff --git a/isisd/isis_zebra.c b/isisd/isis_zebra.c index 4bd42ead86..0142e30b2b 100644 --- a/isisd/isis_zebra.c +++ b/isisd/isis_zebra.c @@ -523,24 +523,24 @@ int isis_distribute_list_update(int routetype) return 0; } -void isis_zebra_redistribute_set(afi_t afi, int type) +void isis_zebra_redistribute_set(afi_t afi, int type, vrf_id_t vrf_id) { if (type == DEFAULT_ROUTE) zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_ADD, - zclient, afi, VRF_DEFAULT); + zclient, afi, vrf_id); else zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, afi, type, - 0, VRF_DEFAULT); + 0, vrf_id); } -void isis_zebra_redistribute_unset(afi_t afi, int type) +void isis_zebra_redistribute_unset(afi_t afi, int type, vrf_id_t vrf_id) { if (type == DEFAULT_ROUTE) zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_DELETE, - zclient, afi, VRF_DEFAULT); + zclient, afi, vrf_id); else zclient_redistribute(ZEBRA_REDISTRIBUTE_DELETE, zclient, afi, - type, 0, VRF_DEFAULT); + type, 0, vrf_id); } /** @@ -724,6 +724,18 @@ void isis_zebra_vrf_register(struct isis *isis) } } +void isis_zebra_vrf_deregister(struct isis *isis) +{ + if (!zclient || zclient->sock < 0 || !isis) + return; + + if (isis->vrf_id != VRF_UNKNOWN) { + if (IS_DEBUG_EVENTS) + zlog_debug("%s: Deregister VRF %s id %u", __func__, + isis->name, isis->vrf_id); + zclient_send_dereg_requests(zclient, isis->vrf_id); + } +} static void isis_zebra_connected(struct zclient *zclient) { diff --git a/isisd/isis_zebra.h b/isisd/isis_zebra.h index b44ec4f085..348d7b3eab 100644 --- a/isisd/isis_zebra.h +++ b/isisd/isis_zebra.h @@ -57,8 +57,8 @@ void isis_zebra_prefix_sid_uninstall(struct isis_area *area, struct isis_sr_psid_info *psid); void isis_zebra_send_adjacency_sid(int cmd, const struct sr_adjacency *sra); int isis_distribute_list_update(int routetype); -void isis_zebra_redistribute_set(afi_t afi, int type); -void isis_zebra_redistribute_unset(afi_t afi, int type); +void isis_zebra_redistribute_set(afi_t afi, int type, vrf_id_t vrf_id); +void isis_zebra_redistribute_unset(afi_t afi, int type, vrf_id_t vrf_id); int isis_zebra_rlfa_register(struct isis_spftree *spftree, struct rlfa *rlfa); void isis_zebra_rlfa_unregister_all(struct isis_spftree *spftree); bool isis_zebra_label_manager_ready(void); @@ -66,5 +66,6 @@ int isis_zebra_label_manager_connect(void); int isis_zebra_request_label_range(uint32_t base, uint32_t chunk_size); int isis_zebra_release_label_range(uint32_t start, uint32_t end); void isis_zebra_vrf_register(struct isis *isis); +void isis_zebra_vrf_deregister(struct isis *isis); #endif /* _ZEBRA_ISIS_ZEBRA_H */ diff --git a/isisd/isisd.c b/isisd/isisd.c index cb3734bd41..bda2295ae1 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -175,15 +175,6 @@ void isis_master_init(struct thread_master *master) im->master = master; } -void isis_global_instance_create(const char *vrf_name) -{ - struct isis *isis; - - isis = isis_lookup_by_vrfname(vrf_name); - if (isis == NULL) - isis_new(vrf_name); -} - struct isis *isis_new(const char *vrf_name) { struct vrf *vrf; @@ -200,6 +191,8 @@ struct isis *isis_new(const char *vrf_name) else isis->vrf_id = VRF_UNKNOWN; + isis_zebra_vrf_register(isis); + if (IS_DEBUG_EVENTS) zlog_debug( "%s: Create new isis instance with vrf_name %s vrf_id %u", @@ -227,6 +220,8 @@ void isis_finish(struct isis *isis) listnode_delete(im->isis, isis); + isis_zebra_vrf_deregister(isis); + vrf = vrf_lookup_by_name(isis->name); if (vrf) isis_vrf_unlink(isis, vrf); @@ -567,8 +562,7 @@ void isis_area_destroy(struct isis_area *area) area_mt_finish(area); if (listcount(area->isis->area_list) == 0) { - memset(area->isis->sysid, 0, ISIS_SYS_ID_LEN); - area->isis->sysid_set = 0; + isis_finish(area->isis); } XFREE(MTYPE_ISIS_AREA, area); @@ -595,6 +589,68 @@ static int isis_vrf_delete(struct vrf *vrf) return 0; } +static void isis_set_redist_vrf_bitmaps(struct isis *isis, bool set) +{ + struct listnode *node; + struct isis_area *area; + int type; + int level; + int protocol; + + char do_subscribe[REDIST_PROTOCOL_COUNT][ZEBRA_ROUTE_MAX + 1]; + + memset(do_subscribe, 0, sizeof(do_subscribe)); + + for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) + for (protocol = 0; protocol < REDIST_PROTOCOL_COUNT; protocol++) + for (type = 0; type < ZEBRA_ROUTE_MAX + 1; type++) + for (level = 0; level < ISIS_LEVELS; level++) + if (area->redist_settings[protocol] + [type][level] + .redist + == 1) + do_subscribe[protocol][type] = + 1; + + for (protocol = 0; protocol < REDIST_PROTOCOL_COUNT; protocol++) + for (type = 0; type < ZEBRA_ROUTE_MAX + 1; type++) { + /* This field is actually controlling transmission of + * the IS-IS + * routes to Zebra and has nothing to do with + * redistribution, + * so skip it. */ + if (type == PROTO_TYPE) + continue; + + if (!do_subscribe[protocol][type]) + continue; + + afi_t afi = afi_for_redist_protocol(protocol); + + if (type == DEFAULT_ROUTE) { + if (set) + vrf_bitmap_set( + zclient->default_information + [afi], + isis->vrf_id); + else + vrf_bitmap_unset( + zclient->default_information + [afi], + isis->vrf_id); + } else { + if (set) + vrf_bitmap_set( + zclient->redist[afi][type], + isis->vrf_id); + else + vrf_bitmap_unset( + zclient->redist[afi][type], + isis->vrf_id); + } + } +} + static int isis_vrf_enable(struct vrf *vrf) { struct isis *isis; @@ -614,13 +670,10 @@ static int isis_vrf_enable(struct vrf *vrf) "%s: isis linked to vrf %s vrf_id %u (old id %u)", __func__, vrf->name, isis->vrf_id, old_vrf_id); if (old_vrf_id != isis->vrf_id) { - frr_with_privs (&isisd_privs) { - /* stop zebra redist to us for old vrf */ - zclient_send_dereg_requests(zclient, - old_vrf_id); - /* start zebra redist to us for new vrf */ - isis_zebra_vrf_register(isis); - } + /* start zebra redist to us for new vrf */ + isis_set_redist_vrf_bitmaps(isis, true); + + isis_zebra_vrf_register(isis); } } @@ -642,6 +695,10 @@ static int isis_vrf_disable(struct vrf *vrf) if (isis) { old_vrf_id = isis->vrf_id; + isis_zebra_vrf_deregister(isis); + + isis_set_redist_vrf_bitmaps(isis, false); + /* We have instance configured, unlink * from VRF and make it "down". */ diff --git a/lib/northbound.c b/lib/northbound.c index 3634fed04f..1ce815ea1e 100644 --- a/lib/northbound.c +++ b/lib/northbound.c @@ -336,7 +336,7 @@ int nb_config_merge(struct nb_config *config_dst, struct nb_config *config_src, { int ret; - ret = lyd_merge_tree(&config_dst->dnode, config_src->dnode, 0); + ret = lyd_merge_siblings(&config_dst->dnode, config_src->dnode, 0); if (ret != 0) flog_warn(EC_LIB_LIBYANG, "%s: lyd_merge() failed", __func__); @@ -599,6 +599,7 @@ static void nb_config_diff(const struct nb_config *config1, * the diff tree. */ target = yang_dnode_get(config2->dnode, path); + assert(target); nb_config_diff_created(target, &seq, changes); /* Skip rest of sub-tree, move to next sibling @@ -607,6 +608,7 @@ static void nb_config_diff(const struct nb_config *config1, break; case 'd': /* delete */ target = yang_dnode_get(config1->dnode, path); + assert(target); nb_config_diff_deleted(target, &seq, changes); /* Skip rest of sub-tree, move to next sibling diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c index c37d89bcb8..96dcdba68f 100644 --- a/ospf6d/ospf6_asbr.c +++ b/ospf6d/ospf6_asbr.c @@ -579,7 +579,7 @@ void ospf6_asbr_lsa_remove(struct ospf6_lsa *lsa, if (ospf6_is_router_abr(ospf6)) oa = ospf6->backbone; else - oa = listgetdata(listhead(ospf6->area_list)); + oa = listnode_head(ospf6->area_list); if (oa == NULL) return; @@ -2302,10 +2302,14 @@ void ospf6_asbr_redistribute_reset(struct ospf6 *ospf6) continue; if (type == ZEBRA_ROUTE_OSPF6) continue; - if (ospf6_zebra_is_redistribute(type, ospf6->vrf_id)) { - ospf6_asbr_redistribute_unset(ospf6, red, type); - ospf6_redist_del(ospf6, red, type); - } + ospf6_asbr_redistribute_unset(ospf6, red, type); + ospf6_redist_del(ospf6, red, type); + } + red = ospf6_redist_lookup(ospf6, DEFAULT_ROUTE, 0); + if (red) { + ospf6_asbr_routemap_unset(red); + ospf6_redist_del(ospf6, red, type); + ospf6_redistribute_default_set(ospf6, DEFAULT_ORIGINATE_NONE); } } diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c index a5c188c465..2376409ccd 100644 --- a/ospf6d/ospf6_top.c +++ b/ospf6d/ospf6_top.c @@ -156,6 +156,16 @@ static void ospf6_set_redist_vrf_bitmaps(struct ospf6 *ospf6, bool set) vrf_bitmap_unset(zclient->redist[AFI_IP6][type], ospf6->vrf_id); } + + red_list = ospf6->redist[DEFAULT_ROUTE]; + if (red_list) { + if (set) + vrf_bitmap_set(zclient->default_information[AFI_IP6], + ospf6->vrf_id); + else + vrf_bitmap_unset(zclient->default_information[AFI_IP6], + ospf6->vrf_id); + } } /* Disable OSPF6 VRF instance */ diff --git a/ospfd/ospf_api.c b/ospfd/ospf_api.c index 7e7236a3b6..81de882754 100644 --- a/ospfd/ospf_api.c +++ b/ospfd/ospf_api.c @@ -58,7 +58,7 @@ /* For debugging only, will be removed */ -void api_opaque_lsa_print(struct lsa_header *data) +void api_opaque_lsa_print(struct ospf_lsa *lsa) { struct opaque_lsa { struct lsa_header header; @@ -69,11 +69,11 @@ void api_opaque_lsa_print(struct lsa_header *data) int opaquelen; int i; - ospf_lsa_header_dump(data); + ospf_lsa_header_dump(lsa->data); - olsa = (struct opaque_lsa *)data; + olsa = (struct opaque_lsa *)lsa->data; - opaquelen = ntohs(data->length) - OSPF_LSA_HEADER_SIZE; + opaquelen = lsa->size - OSPF_LSA_HEADER_SIZE; zlog_debug("apiserver_lsa_print: opaquelen=%d", opaquelen); for (i = 0; i < opaquelen; i++) { @@ -111,11 +111,16 @@ struct msg *msg_new(uint8_t msgtype, void *msgbody, uint32_t seqnum, struct msg *msg_dup(struct msg *msg) { struct msg *new; + size_t size; assert(msg); + size = ntohs(msg->hdr.msglen); + if (size > OSPF_MAX_LSA_SIZE) + return NULL; + new = msg_new(msg->hdr.msgtype, STREAM_DATA(msg->s), - ntohl(msg->hdr.msgseq), ntohs(msg->hdr.msglen)); + ntohl(msg->hdr.msgseq), size); return new; } @@ -400,7 +405,7 @@ struct msg *msg_read(int fd) } /* Allocate new message */ - msg = msg_new(hdr.msgtype, buf, ntohl(hdr.msgseq), ntohs(hdr.msglen)); + msg = msg_new(hdr.msgtype, buf, ntohl(hdr.msgseq), bodylen); return msg; } @@ -408,29 +413,34 @@ struct msg *msg_read(int fd) int msg_write(int fd, struct msg *msg) { uint8_t buf[OSPF_API_MAX_MSG_SIZE]; - int l; + uint16_t l; int wlen; assert(msg); assert(msg->s); - /* Length of message including header */ - l = sizeof(struct apimsghdr) + ntohs(msg->hdr.msglen); + /* Length of OSPF LSA payload */ + l = ntohs(msg->hdr.msglen); + if (l > OSPF_MAX_LSA_SIZE) { + zlog_warn("%s: wrong LSA size %d", __func__, l); + return -1; + } /* Make contiguous memory buffer for message */ memcpy(buf, &msg->hdr, sizeof(struct apimsghdr)); - memcpy(buf + sizeof(struct apimsghdr), STREAM_DATA(msg->s), - ntohs(msg->hdr.msglen)); + memcpy(buf + sizeof(struct apimsghdr), STREAM_DATA(msg->s), l); + /* Total length of OSPF API Message */ + l += sizeof(struct apimsghdr); wlen = writen(fd, buf, l); if (wlen < 0) { - zlog_warn("msg_write: writen %s", safe_strerror(errno)); + zlog_warn("%s: writen %s", __func__, safe_strerror(errno)); return -1; } else if (wlen == 0) { - zlog_warn("msg_write: Connection closed by peer"); + zlog_warn("%s: Connection closed by peer", __func__); return -1; } else if (wlen != l) { - zlog_warn("msg_write: Cannot write API message"); + zlog_warn("%s: Cannot write API message", __func__); return -1; } return 0; diff --git a/ospfd/ospf_api.h b/ospfd/ospf_api.h index 0fc683a5db..c20284aed5 100644 --- a/ospfd/ospf_api.h +++ b/ospfd/ospf_api.h @@ -276,7 +276,7 @@ struct apimsg { */ /* For debugging only. */ -extern void api_opaque_lsa_print(struct lsa_header *data); +extern void api_opaque_lsa_print(struct ospf_lsa *lsa); /* Messages sent by client */ extern struct msg *new_msg_register_opaque_type(uint32_t seqnum, uint8_t ltype, diff --git a/ospfd/ospf_apiserver.c b/ospfd/ospf_apiserver.c index c01ecdd1d4..cbd03441ef 100644 --- a/ospfd/ospf_apiserver.c +++ b/ospfd/ospf_apiserver.c @@ -1156,6 +1156,7 @@ int ospf_apiserver_handle_register_event(struct ospf_apiserver *apiserv, struct msg_register_event *rmsg; int rc; uint32_t seqnum; + size_t size; rmsg = (struct msg_register_event *)STREAM_DATA(msg->s); @@ -1165,13 +1166,16 @@ int ospf_apiserver_handle_register_event(struct ospf_apiserver *apiserv, /* Free existing filter in apiserv. */ XFREE(MTYPE_OSPF_APISERVER_MSGFILTER, apiserv->filter); /* Alloc new space for filter. */ + size = ntohs(msg->hdr.msglen); + if (size < OSPF_MAX_LSA_SIZE) { - apiserv->filter = - XMALLOC(MTYPE_OSPF_APISERVER_MSGFILTER, ntohs(msg->hdr.msglen)); + apiserv->filter = XMALLOC(MTYPE_OSPF_APISERVER_MSGFILTER, size); - /* copy it over. */ - memcpy(apiserv->filter, &rmsg->filter, ntohs(msg->hdr.msglen)); - rc = OSPF_API_OK; + /* copy it over. */ + memcpy(apiserv->filter, &rmsg->filter, size); + rc = OSPF_API_OK; + } else + rc = OSPF_API_NOMEMORY; /* Send a reply back to client with return code */ rc = ospf_apiserver_send_reply(apiserv, seqnum, rc); diff --git a/ospfd/ospf_dump.c b/ospfd/ospf_dump.c index 8f31f90346..e490070d03 100644 --- a/ospfd/ospf_dump.c +++ b/ospfd/ospf_dump.c @@ -241,7 +241,7 @@ const char *ospf_timer_dump(struct thread *t, char *buf, size_t size) static void ospf_packet_hello_dump(struct stream *s, uint16_t length) { struct ospf_hello *hello; - int i; + int i, len; hello = (struct ospf_hello *)stream_pnt(s); @@ -256,9 +256,9 @@ static void ospf_packet_hello_dump(struct stream *s, uint16_t length) zlog_debug(" DRouter %pI4", &hello->d_router); zlog_debug(" BDRouter %pI4", &hello->bd_router); - length -= OSPF_HEADER_SIZE + OSPF_HELLO_MIN_SIZE; - zlog_debug(" # Neighbors %d", length / 4); - for (i = 0; length > 0; i++, length -= sizeof(struct in_addr)) + len = length - OSPF_HEADER_SIZE - OSPF_HELLO_MIN_SIZE; + zlog_debug(" # Neighbors %d", len / 4); + for (i = 0; len > 0; i++, len -= sizeof(struct in_addr)) zlog_debug(" Neighbor %pI4", &hello->neighbors[i]); } @@ -285,7 +285,8 @@ static void ospf_router_lsa_dump(struct stream *s, uint16_t length) { char buf[BUFSIZ]; struct router_lsa *rl; - int i, len; + struct router_link *rlnk; + int i, len, sum; rl = (struct router_lsa *)stream_pnt(s); @@ -294,16 +295,15 @@ static void ospf_router_lsa_dump(struct stream *s, uint16_t length) ospf_router_lsa_flags_dump(rl->flags, buf, BUFSIZ)); zlog_debug(" # links %d", ntohs(rl->links)); - len = ntohs(rl->header.length) - OSPF_LSA_HEADER_SIZE - 4; - for (i = 0; len > 0; i++) { - zlog_debug(" Link ID %pI4", &rl->link[i].link_id); - zlog_debug(" Link Data %pI4", - &rl->link[i].link_data); - zlog_debug(" Type %d", (uint8_t)rl->link[i].type); - zlog_debug(" TOS %d", (uint8_t)rl->link[i].tos); - zlog_debug(" metric %d", ntohs(rl->link[i].metric)); - - len -= 12; + len = length - OSPF_LSA_HEADER_SIZE - 4; + rlnk = &rl->link[0]; + sum = 0; + for (i = 0; sum < len && rlnk; sum += 12, rlnk = &rl->link[++i]) { + zlog_debug(" Link ID %pI4", &rlnk->link_id); + zlog_debug(" Link Data %pI4", &rlnk->link_data); + zlog_debug(" Type %d", (uint8_t)rlnk->type); + zlog_debug(" TOS %d", (uint8_t)rlnk->tos); + zlog_debug(" metric %d", ntohs(rlnk->metric)); } } @@ -312,10 +312,11 @@ static void ospf_network_lsa_dump(struct stream *s, uint16_t length) struct network_lsa *nl; int i, cnt; + zlog_debug(" Network-LSA"); + nl = (struct network_lsa *)stream_pnt(s); - cnt = (ntohs(nl->header.length) - (OSPF_LSA_HEADER_SIZE + 4)) / 4; + cnt = (length - (OSPF_LSA_HEADER_SIZE + 4)) / 4; - zlog_debug(" Network-LSA"); /* zlog_debug ("LSA total size %d", ntohs (nl->header.length)); zlog_debug ("Network-LSA size %d", @@ -331,55 +332,53 @@ static void ospf_network_lsa_dump(struct stream *s, uint16_t length) static void ospf_summary_lsa_dump(struct stream *s, uint16_t length) { struct summary_lsa *sl; - int size; - int i; sl = (struct summary_lsa *)stream_pnt(s); zlog_debug(" Summary-LSA"); zlog_debug(" Network Mask %pI4", &sl->mask); - - size = ntohs(sl->header.length) - OSPF_LSA_HEADER_SIZE - 4; - for (i = 0; size > 0; size -= 4, i++) - zlog_debug(" TOS=%d metric %d", sl->tos, - GET_METRIC(sl->metric)); + zlog_debug(" TOS=%d metric %d", sl->tos, GET_METRIC(sl->metric)); } static void ospf_as_external_lsa_dump(struct stream *s, uint16_t length) { struct as_external_lsa *al; - int size; + struct as_route *asr; + int size, sum; int i; al = (struct as_external_lsa *)stream_pnt(s); zlog_debug(" %s", ospf_lsa_type_msg[al->header.type].str); zlog_debug(" Network Mask %pI4", &al->mask); - size = ntohs(al->header.length) - OSPF_LSA_HEADER_SIZE - 4; - for (i = 0; size > 0; size -= 12, i++) { + size = length - OSPF_LSA_HEADER_SIZE - 4; + asr = &al->e[0]; + sum = 0; + for (i = 0; sum < size && asr; sum += 12, asr = &al->e[++i]) { zlog_debug(" bit %s TOS=%d metric %d", - IS_EXTERNAL_METRIC(al->e[i].tos) ? "E" : "-", - al->e[i].tos & 0x7f, GET_METRIC(al->e[i].metric)); - zlog_debug(" Forwarding address %pI4", - &al->e[i].fwd_addr); + IS_EXTERNAL_METRIC(asr->tos) ? "E" : "-", + asr->tos & 0x7f, GET_METRIC(asr->metric)); + zlog_debug(" Forwarding address %pI4", &asr->fwd_addr); zlog_debug(" External Route Tag %" ROUTE_TAG_PRI, - al->e[i].route_tag); + asr->route_tag); } } static void ospf_lsa_header_list_dump(struct stream *s, uint16_t length) { struct lsa_header *lsa; + int len; zlog_debug(" # LSA Headers %d", length / OSPF_LSA_HEADER_SIZE); /* LSA Headers. */ - while (length > 0) { + len = length; + while (len > 0) { lsa = (struct lsa_header *)stream_pnt(s); ospf_lsa_header_dump(lsa); stream_forward_getp(s, OSPF_LSA_HEADER_SIZE); - length -= OSPF_LSA_HEADER_SIZE; + len -= OSPF_LSA_HEADER_SIZE; } } @@ -417,6 +416,7 @@ static void ospf_packet_ls_req_dump(struct stream *s, uint16_t length) uint32_t ls_type; struct in_addr ls_id; struct in_addr adv_router; + int sum; sp = stream_get_getp(s); @@ -425,7 +425,8 @@ static void ospf_packet_ls_req_dump(struct stream *s, uint16_t length) zlog_debug("Link State Request"); zlog_debug(" # Requests %d", length / 12); - for (; length > 0; length -= 12) { + sum = 0; + for (; sum < length; sum += 12) { ls_type = stream_getl(s); ls_id.s_addr = stream_get_ipv4(s); adv_router.s_addr = stream_get_ipv4(s); @@ -442,23 +443,23 @@ static void ospf_packet_ls_upd_dump(struct stream *s, uint16_t length) { uint32_t sp; struct lsa_header *lsa; - int lsa_len; + int lsa_len, len; uint32_t count; - length -= OSPF_HEADER_SIZE; + len = length - OSPF_HEADER_SIZE; sp = stream_get_getp(s); count = stream_getl(s); - length -= 4; + len -= 4; zlog_debug("Link State Update"); zlog_debug(" # LSAs %d", count); - while (length > 0 && count > 0) { - if (length < OSPF_HEADER_SIZE || length % 4 != 0) { + while (len > 0 && count > 0) { + if ((uint16_t)len < OSPF_LSA_HEADER_SIZE || len % 4 != 0) { zlog_debug(" Remaining %d bytes; Incorrect length.", - length); + len); break; } @@ -466,34 +467,39 @@ static void ospf_packet_ls_upd_dump(struct stream *s, uint16_t length) lsa_len = ntohs(lsa->length); ospf_lsa_header_dump(lsa); + /* Check that LSA length is valid */ + if (lsa_len > len || lsa_len % 4 != 0) { + zlog_debug(" LSA length %d is incorrect!", lsa_len); + break; + } switch (lsa->type) { case OSPF_ROUTER_LSA: - ospf_router_lsa_dump(s, length); + ospf_router_lsa_dump(s, lsa_len); break; case OSPF_NETWORK_LSA: - ospf_network_lsa_dump(s, length); + ospf_network_lsa_dump(s, lsa_len); break; case OSPF_SUMMARY_LSA: case OSPF_ASBR_SUMMARY_LSA: - ospf_summary_lsa_dump(s, length); + ospf_summary_lsa_dump(s, lsa_len); break; case OSPF_AS_EXTERNAL_LSA: - ospf_as_external_lsa_dump(s, length); + ospf_as_external_lsa_dump(s, lsa_len); break; case OSPF_AS_NSSA_LSA: - ospf_as_external_lsa_dump(s, length); + ospf_as_external_lsa_dump(s, lsa_len); break; case OSPF_OPAQUE_LINK_LSA: case OSPF_OPAQUE_AREA_LSA: case OSPF_OPAQUE_AS_LSA: - ospf_opaque_lsa_dump(s, length); + ospf_opaque_lsa_dump(s, lsa_len); break; default: break; } stream_forward_getp(s, lsa_len); - length -= lsa_len; + len -= lsa_len; count--; } diff --git a/ospfd/ospf_ext.c b/ospfd/ospf_ext.c index 754e2bcbab..2d08eeece2 100644 --- a/ospfd/ospf_ext.c +++ b/ospfd/ospf_ext.c @@ -1715,13 +1715,23 @@ static void ospf_ext_lsa_schedule(struct ext_itf *exti, enum lsa_opcode op) * ------------------------------------ */ +#define check_tlv_size(size, msg) \ + do { \ + if (ntohs(tlvh->length) != size) { \ + vty_out(vty, " Wrong %s TLV size: %d(%d). Abort!\n", \ + msg, ntohs(tlvh->length), size); \ + return size + TLV_HDR_SIZE; \ + } \ + } while (0) + /* Cisco experimental SubTLV */ static uint16_t show_vty_ext_link_rmt_itf_addr(struct vty *vty, struct tlv_header *tlvh) { - struct ext_subtlv_rmt_itf_addr *top; + struct ext_subtlv_rmt_itf_addr *top = + (struct ext_subtlv_rmt_itf_addr *)tlvh; - top = (struct ext_subtlv_rmt_itf_addr *)tlvh; + check_tlv_size(EXT_SUBTLV_RMT_ITF_ADDR_SIZE, "Remote Itf. Address"); vty_out(vty, " Remote Interface Address Sub-TLV: Length %u\n Address: %pI4\n", @@ -1736,6 +1746,8 @@ static uint16_t show_vty_ext_link_adj_sid(struct vty *vty, { struct ext_subtlv_adj_sid *top = (struct ext_subtlv_adj_sid *)tlvh; + check_tlv_size(EXT_SUBTLV_ADJ_SID_SIZE, "Adjacency SID"); + vty_out(vty, " Adj-SID Sub-TLV: Length %u\n\tFlags: 0x%x\n\tMT-ID:0x%x\n\tWeight: 0x%x\n\t%s: %u\n", ntohs(top->header.length), top->flags, top->mtid, top->weight, @@ -1755,6 +1767,8 @@ static uint16_t show_vty_ext_link_lan_adj_sid(struct vty *vty, struct ext_subtlv_lan_adj_sid *top = (struct ext_subtlv_lan_adj_sid *)tlvh; + check_tlv_size(EXT_SUBTLV_LAN_ADJ_SID_SIZE, "Lan-Adjacency SID"); + vty_out(vty, " LAN-Adj-SID Sub-TLV: Length %u\n\tFlags: 0x%x\n\tMT-ID:0x%x\n\tWeight: 0x%x\n\tNeighbor ID: %pI4\n\t%s: %u\n", ntohs(top->header.length), top->flags, top->mtid, top->weight, @@ -1768,8 +1782,15 @@ static uint16_t show_vty_ext_link_lan_adj_sid(struct vty *vty, return TLV_SIZE(tlvh); } -static uint16_t show_vty_unknown_tlv(struct vty *vty, struct tlv_header *tlvh) +static uint16_t show_vty_unknown_tlv(struct vty *vty, struct tlv_header *tlvh, + size_t buf_size) { + if (TLV_SIZE(tlvh) > buf_size) { + vty_out(vty, " TLV size %d exceeds buffer size. Abort!", + TLV_SIZE(tlvh)); + return buf_size; + } + vty_out(vty, " Unknown TLV: [type(0x%x), length(0x%x)]\n", ntohs(tlvh->type), ntohs(tlvh->length)); @@ -1777,13 +1798,22 @@ static uint16_t show_vty_unknown_tlv(struct vty *vty, struct tlv_header *tlvh) } /* Extended Link Sub TLVs */ -static uint16_t show_vty_link_info(struct vty *vty, struct tlv_header *ext) +static uint16_t show_vty_link_info(struct vty *vty, struct tlv_header *ext, + size_t buf_size) { struct ext_tlv_link *top = (struct ext_tlv_link *)ext; struct tlv_header *tlvh; - uint16_t length = ntohs(top->header.length) - 3 * sizeof(uint32_t); + uint16_t length = ntohs(top->header.length); uint16_t sum = 0; + /* Verify that TLV length is valid against remaining buffer size */ + if (length > buf_size) { + vty_out(vty, + " Extended Link TLV size %d exceeds buffer size. Abort!\n", + length); + return buf_size; + } + vty_out(vty, " Extended Link TLV: Length %u\n Link Type: 0x%x\n" " Link ID: %pI4\n", @@ -1791,9 +1821,11 @@ static uint16_t show_vty_link_info(struct vty *vty, struct tlv_header *ext) &top->link_id); vty_out(vty, " Link data: %pI4\n", &top->link_data); + /* Skip Extended TLV and parse sub-TLVs */ + length -= EXT_TLV_LINK_SIZE; tlvh = (struct tlv_header *)((char *)(ext) + TLV_HDR_SIZE + EXT_TLV_LINK_SIZE); - for (; sum < length; tlvh = TLV_HDR_NEXT(tlvh)) { + for (; sum < length && tlvh; tlvh = TLV_HDR_NEXT(tlvh)) { switch (ntohs(tlvh->type)) { case EXT_SUBTLV_ADJ_SID: sum += show_vty_ext_link_adj_sid(vty, tlvh); @@ -1805,7 +1837,7 @@ static uint16_t show_vty_link_info(struct vty *vty, struct tlv_header *ext) sum += show_vty_ext_link_rmt_itf_addr(vty, tlvh); break; default: - sum += show_vty_unknown_tlv(vty, tlvh); + sum += show_vty_unknown_tlv(vty, tlvh, length - sum); break; } } @@ -1821,16 +1853,16 @@ static void ospf_ext_link_show_info(struct vty *vty, struct ospf_lsa *lsa) uint16_t length = 0, sum = 0; /* Initialize TLV browsing */ - length = ntohs(lsah->length) - OSPF_LSA_HEADER_SIZE; + length = lsa->size - OSPF_LSA_HEADER_SIZE; - for (tlvh = TLV_HDR_TOP(lsah); sum < length; + for (tlvh = TLV_HDR_TOP(lsah); sum < length && tlvh; tlvh = TLV_HDR_NEXT(tlvh)) { switch (ntohs(tlvh->type)) { case EXT_TLV_LINK: - sum += show_vty_link_info(vty, tlvh); + sum += show_vty_link_info(vty, tlvh, length - sum); break; default: - sum += show_vty_unknown_tlv(vty, tlvh); + sum += show_vty_unknown_tlv(vty, tlvh, length - sum); break; } } @@ -1843,6 +1875,8 @@ static uint16_t show_vty_ext_pref_pref_sid(struct vty *vty, struct ext_subtlv_prefix_sid *top = (struct ext_subtlv_prefix_sid *)tlvh; + check_tlv_size(EXT_SUBTLV_PREFIX_SID_SIZE, "Prefix SID"); + vty_out(vty, " Prefix SID Sub-TLV: Length %u\n\tAlgorithm: %u\n\tFlags: 0x%x\n\tMT-ID:0x%x\n\t%s: %u\n", ntohs(top->header.length), top->algorithm, top->flags, @@ -1857,28 +1891,39 @@ static uint16_t show_vty_ext_pref_pref_sid(struct vty *vty, } /* Extended Prefix SubTLVs */ -static uint16_t show_vty_pref_info(struct vty *vty, struct tlv_header *ext) +static uint16_t show_vty_pref_info(struct vty *vty, struct tlv_header *ext, + size_t buf_size) { struct ext_tlv_prefix *top = (struct ext_tlv_prefix *)ext; struct tlv_header *tlvh; - uint16_t length = ntohs(top->header.length) - 2 * sizeof(uint32_t); + uint16_t length = ntohs(top->header.length); uint16_t sum = 0; + /* Verify that TLV length is valid against remaining buffer size */ + if (length > buf_size) { + vty_out(vty, + " Extended Link TLV size %d exceeds buffer size. Abort!\n", + length); + return buf_size; + } + vty_out(vty, " Extended Prefix TLV: Length %u\n\tRoute Type: %u\n" "\tAddress Family: 0x%x\n\tFlags: 0x%x\n\tAddress: %pI4/%u\n", ntohs(top->header.length), top->route_type, top->af, top->flags, &top->address, top->pref_length); + /* Skip Extended Prefix TLV and parse sub-TLVs */ + length -= EXT_TLV_PREFIX_SIZE; tlvh = (struct tlv_header *)((char *)(ext) + TLV_HDR_SIZE + EXT_TLV_PREFIX_SIZE); - for (; sum < length; tlvh = TLV_HDR_NEXT(tlvh)) { + for (; sum < length && tlvh; tlvh = TLV_HDR_NEXT(tlvh)) { switch (ntohs(tlvh->type)) { case EXT_SUBTLV_PREFIX_SID: sum += show_vty_ext_pref_pref_sid(vty, tlvh); break; default: - sum += show_vty_unknown_tlv(vty, tlvh); + sum += show_vty_unknown_tlv(vty, tlvh, length - sum); break; } } @@ -1894,16 +1939,16 @@ static void ospf_ext_pref_show_info(struct vty *vty, struct ospf_lsa *lsa) uint16_t length = 0, sum = 0; /* Initialize TLV browsing */ - length = ntohs(lsah->length) - OSPF_LSA_HEADER_SIZE; + length = lsa->size - OSPF_LSA_HEADER_SIZE; - for (tlvh = TLV_HDR_TOP(lsah); sum < length; + for (tlvh = TLV_HDR_TOP(lsah); sum < length && tlvh; tlvh = TLV_HDR_NEXT(tlvh)) { switch (ntohs(tlvh->type)) { case EXT_TLV_PREFIX: - sum += show_vty_pref_info(vty, tlvh); + sum += show_vty_pref_info(vty, tlvh, length - sum); break; default: - sum += show_vty_unknown_tlv(vty, tlvh); + sum += show_vty_unknown_tlv(vty, tlvh, length - sum); break; } } diff --git a/ospfd/ospf_gr_helper.c b/ospfd/ospf_gr_helper.c index d818878cf5..a25057a27f 100644 --- a/ospfd/ospf_gr_helper.c +++ b/ospfd/ospf_gr_helper.c @@ -233,19 +233,17 @@ static int ospf_extract_grace_lsa_fields(struct ospf_lsa *lsa, lsah = (struct lsa_header *)lsa->data; - length = ntohs(lsah->length); - /* Check LSA len */ - if (length <= OSPF_LSA_HEADER_SIZE) { + if (lsa->size <= OSPF_LSA_HEADER_SIZE) { if (IS_DEBUG_OSPF_GR_HELPER) zlog_debug("%s: Malformed packet: Invalid LSA len:%d", __func__, length); return OSPF_GR_FAILURE; } - length -= OSPF_LSA_HEADER_SIZE; + length = lsa->size - OSPF_LSA_HEADER_SIZE; - for (tlvh = TLV_HDR_TOP(lsah); sum < length; + for (tlvh = TLV_HDR_TOP(lsah); sum < length && tlvh; tlvh = TLV_HDR_NEXT(tlvh)) { /* Check TLV len against overall LSA */ @@ -996,18 +994,16 @@ static void show_ospf_grace_lsa_info(struct vty *vty, struct ospf_lsa *lsa) lsah = (struct lsa_header *)lsa->data; - length = ntohs(lsah->length); - - if (length <= OSPF_LSA_HEADER_SIZE) { + if (lsa->size <= OSPF_LSA_HEADER_SIZE) { vty_out(vty, "%% Invalid LSA length: %d\n", length); return; } - length -= OSPF_LSA_HEADER_SIZE; + length = lsa->size - OSPF_LSA_HEADER_SIZE; vty_out(vty, " TLV info:\n"); - for (tlvh = TLV_HDR_TOP(lsah); sum < length; + for (tlvh = TLV_HDR_TOP(lsah); sum < length && tlvh; tlvh = TLV_HDR_NEXT(tlvh)) { /* Check TLV len */ if (sum + TLV_SIZE(tlvh) > length) { diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c index 6e9df77fb8..72dc699bd9 100644 --- a/ospfd/ospf_lsa.c +++ b/ospfd/ospf_lsa.c @@ -175,6 +175,7 @@ struct ospf_lsa *ospf_lsa_new_and_data(size_t size) new = ospf_lsa_new(); new->data = ospf_lsa_data_new(size); + new->size = size; return new; } @@ -3241,22 +3242,22 @@ int ospf_lsa_different(struct ospf_lsa *l1, struct ospf_lsa *l2) if (IS_LSA_MAXAGE(l2) && !IS_LSA_MAXAGE(l1)) return 1; - if (l1->data->length != l2->data->length) + if (l1->size != l2->size) return 1; - if (l1->data->length == 0) + if (l1->size == 0) return 1; if (CHECK_FLAG((l1->flags ^ l2->flags), OSPF_LSA_RECEIVED)) return 1; /* May be a stale LSA in the LSBD */ - assert(ntohs(l1->data->length) > OSPF_LSA_HEADER_SIZE); + assert(l1->size > OSPF_LSA_HEADER_SIZE); p1 = (char *)l1->data; p2 = (char *)l2->data; if (memcmp(p1 + OSPF_LSA_HEADER_SIZE, p2 + OSPF_LSA_HEADER_SIZE, - ntohs(l1->data->length) - OSPF_LSA_HEADER_SIZE) + l1->size - OSPF_LSA_HEADER_SIZE) != 0) return 1; diff --git a/ospfd/ospf_lsa.h b/ospfd/ospf_lsa.h index 3c1f94e628..3808700ccc 100644 --- a/ospfd/ospf_lsa.h +++ b/ospfd/ospf_lsa.h @@ -84,8 +84,9 @@ struct ospf_lsa { #define OSPF_LSA_PREMATURE_AGE 0x40 #define OSPF_LSA_IN_MAXAGE 0x80 - /* LSA data. */ + /* LSA data. and size */ struct lsa_header *data; + size_t size; /* Received time stamp. */ struct timeval tv_recv; @@ -168,7 +169,7 @@ struct router_lsa { uint8_t flags; uint8_t zero; uint16_t links; - struct { + struct router_link { struct in_addr link_id; struct in_addr link_data; uint8_t type; @@ -199,7 +200,7 @@ struct summary_lsa { struct as_external_lsa { struct lsa_header header; struct in_addr mask; - struct { + struct as_route { uint8_t tos; uint8_t metric[3]; struct in_addr fwd_addr; diff --git a/ospfd/ospf_opaque.c b/ospfd/ospf_opaque.c index ae9ab48d4a..42bf914f67 100644 --- a/ospfd/ospf_opaque.c +++ b/ospfd/ospf_opaque.c @@ -1204,9 +1204,10 @@ void show_opaque_info_detail(struct vty *vty, struct ospf_lsa *lsa, void ospf_opaque_lsa_dump(struct stream *s, uint16_t length) { - struct ospf_lsa lsa; + struct ospf_lsa lsa = {}; lsa.data = (struct lsa_header *)stream_pnt(s); + lsa.size = length; show_opaque_info_detail(NULL, &lsa, NULL); return; } diff --git a/ospfd/ospf_opaque.h b/ospfd/ospf_opaque.h index c63b8ebdaf..7d401c3dcc 100644 --- a/ospfd/ospf_opaque.h +++ b/ospfd/ospf_opaque.h @@ -79,6 +79,7 @@ #define VALID_OPAQUE_INFO_LEN(lsahdr) \ ((ntohs((lsahdr)->length) >= sizeof(struct lsa_header)) \ + && ((ntohs((lsahdr)->length) < OSPF_MAX_LSA_SIZE)) \ && ((ntohs((lsahdr)->length) % sizeof(uint32_t)) == 0)) /* diff --git a/ospfd/ospf_ri.c b/ospfd/ospf_ri.c index 4083ea9332..602f98d141 100644 --- a/ospfd/ospf_ri.c +++ b/ospfd/ospf_ri.c @@ -294,8 +294,8 @@ static void set_pce_address(struct in_addr ipv4, struct ospf_pce_info *pce) pce->pce_header.header.type = htons(RI_TLV_PCE); /* Set PCE Address */ pce->pce_address.header.type = htons(RI_PCE_SUBTLV_ADDRESS); - pce->pce_address.header.length = htons(PCE_ADDRESS_LENGTH_IPV4); - pce->pce_address.address.type = htons(PCE_ADDRESS_TYPE_IPV4); + pce->pce_address.header.length = htons(PCE_ADDRESS_IPV4_SIZE); + pce->pce_address.address.type = htons(PCE_ADDRESS_IPV4); pce->pce_address.address.value = ipv4; return; @@ -323,7 +323,7 @@ static void set_pce_domain(uint16_t type, uint32_t domain, sizeof(struct ri_pce_subtlv_domain)); new->header.type = htons(RI_PCE_SUBTLV_DOMAIN); - new->header.length = htons(PCE_ADDRESS_LENGTH_IPV4); + new->header.length = htons(PCE_ADDRESS_IPV4_SIZE); new->type = htons(type); new->value = htonl(domain); @@ -369,7 +369,7 @@ static void set_pce_neighbor(uint16_t type, uint32_t domain, sizeof(struct ri_pce_subtlv_neighbor)); new->header.type = htons(RI_PCE_SUBTLV_NEIGHBOR); - new->header.length = htons(PCE_ADDRESS_LENGTH_IPV4); + new->header.length = htons(PCE_ADDRESS_IPV4_SIZE); new->type = htons(type); new->value = htonl(domain); @@ -447,8 +447,7 @@ static void set_sr_global_label_range(struct sr_block srgb) { /* Set Header */ TLV_TYPE(OspfRI.sr_info.srgb) = htons(RI_SR_TLV_SRGB_LABEL_RANGE); - TLV_LEN(OspfRI.sr_info.srgb) = - htons(SUBTLV_SID_LABEL_SIZE + sizeof(uint32_t)); + TLV_LEN(OspfRI.sr_info.srgb) = htons(RI_SR_TLV_LABEL_RANGE_SIZE); /* Set Range Size */ OspfRI.sr_info.srgb.size = htonl(SET_RANGE_SIZE(srgb.range_size)); /* Set Lower bound label SubTLV */ @@ -471,8 +470,7 @@ static void set_sr_local_label_range(struct sr_block srlb) { /* Set Header */ TLV_TYPE(OspfRI.sr_info.srlb) = htons(RI_SR_TLV_SRLB_LABEL_RANGE); - TLV_LEN(OspfRI.sr_info.srlb) = - htons(SUBTLV_SID_LABEL_SIZE + sizeof(uint32_t)); + TLV_LEN(OspfRI.sr_info.srlb) = htons(RI_SR_TLV_LABEL_RANGE_SIZE); /* Set Range Size */ OspfRI.sr_info.srlb.size = htonl(SET_RANGE_SIZE(srlb.range_size)); /* Set Lower bound label SubTLV */ @@ -1226,10 +1224,25 @@ static int ospf_router_info_lsa_update(struct ospf_lsa *lsa) * Followings are vty session control functions. *------------------------------------------------------------------------*/ +#define check_tlv_size(size, msg) \ + do { \ + if (ntohs(tlvh->length) > size) { \ + if (vty != NULL) \ + vty_out(vty, " Wrong %s TLV size: %d(%d)\n", \ + msg, ntohs(tlvh->length), size); \ + else \ + zlog_debug(" Wrong %s TLV size: %d(%d)", \ + msg, ntohs(tlvh->length), size); \ + return size + TLV_HDR_SIZE; \ + } \ + } while (0) + static uint16_t show_vty_router_cap(struct vty *vty, struct tlv_header *tlvh) { struct ri_tlv_router_cap *top = (struct ri_tlv_router_cap *)tlvh; + check_tlv_size(RI_TLV_CAPABILITIES_SIZE, "Router Capabilities"); + if (vty != NULL) vty_out(vty, " Router Capabilities: 0x%x\n", ntohl(top->value)); @@ -1245,21 +1258,30 @@ static uint16_t show_vty_pce_subtlv_address(struct vty *vty, struct ri_pce_subtlv_address *top = (struct ri_pce_subtlv_address *)tlvh; - if (ntohs(top->address.type) == PCE_ADDRESS_TYPE_IPV4) { + if (ntohs(top->address.type) == PCE_ADDRESS_IPV4) { + check_tlv_size(PCE_ADDRESS_IPV4_SIZE, "PCE Address"); if (vty != NULL) vty_out(vty, " PCE Address: %pI4\n", &top->address.value); else zlog_debug(" PCE Address: %pI4", &top->address.value); - } else { + } else if (ntohs(top->address.type) == PCE_ADDRESS_IPV6) { /* TODO: Add support to IPv6 with inet_ntop() */ + check_tlv_size(PCE_ADDRESS_IPV6_SIZE, "PCE Address"); if (vty != NULL) vty_out(vty, " PCE Address: 0x%x\n", ntohl(top->address.value.s_addr)); else zlog_debug(" PCE Address: 0x%x", ntohl(top->address.value.s_addr)); + } else { + if (vty != NULL) + vty_out(vty, " Wrong PCE Address type: 0x%x\n", + ntohl(top->address.type)); + else + zlog_debug(" Wrong PCE Address type: 0x%x", + ntohl(top->address.type)); } return TLV_SIZE(tlvh); @@ -1271,6 +1293,8 @@ static uint16_t show_vty_pce_subtlv_path_scope(struct vty *vty, struct ri_pce_subtlv_path_scope *top = (struct ri_pce_subtlv_path_scope *)tlvh; + check_tlv_size(RI_PCE_SUBTLV_PATH_SCOPE_SIZE, "PCE Path Scope"); + if (vty != NULL) vty_out(vty, " PCE Path Scope: 0x%x\n", ntohl(top->value)); else @@ -1285,19 +1309,29 @@ static uint16_t show_vty_pce_subtlv_domain(struct vty *vty, struct ri_pce_subtlv_domain *top = (struct ri_pce_subtlv_domain *)tlvh; struct in_addr tmp; + check_tlv_size(RI_PCE_SUBTLV_DOMAIN_SIZE, "PCE Domain"); + if (ntohs(top->type) == PCE_DOMAIN_TYPE_AREA) { tmp.s_addr = top->value; if (vty != NULL) - vty_out(vty, " PCE domain Area: %pI4\n", &tmp); + vty_out(vty, " PCE Domain Area: %pI4\n", &tmp); else - zlog_debug(" PCE domain Area: %pI4", &tmp); - } else { + zlog_debug(" PCE Domain Area: %pI4", &tmp); + } else if (ntohs(top->type) == PCE_DOMAIN_TYPE_AS) { if (vty != NULL) - vty_out(vty, " PCE domain AS: %d\n", + vty_out(vty, " PCE Domain AS: %d\n", ntohl(top->value)); else - zlog_debug(" PCE domain AS: %d", ntohl(top->value)); + zlog_debug(" PCE Domain AS: %d", ntohl(top->value)); + } else { + if (vty != NULL) + vty_out(vty, " Wrong PCE Domain type: %d\n", + ntohl(top->type)); + else + zlog_debug(" Wrong PCE Domain type: %d", + ntohl(top->type)); } + return TLV_SIZE(tlvh); } @@ -1309,21 +1343,30 @@ static uint16_t show_vty_pce_subtlv_neighbor(struct vty *vty, (struct ri_pce_subtlv_neighbor *)tlvh; struct in_addr tmp; + check_tlv_size(RI_PCE_SUBTLV_NEIGHBOR_SIZE, "PCE Neighbor"); + if (ntohs(top->type) == PCE_DOMAIN_TYPE_AREA) { tmp.s_addr = top->value; if (vty != NULL) - vty_out(vty, " PCE neighbor Area: %pI4\n", - &tmp); + vty_out(vty, " PCE Neighbor Area: %pI4\n", &tmp); else - zlog_debug(" PCE neighbor Area: %pI4", &tmp); - } else { + zlog_debug(" PCE Neighbor Area: %pI4", &tmp); + } else if (ntohs(top->type) == PCE_DOMAIN_TYPE_AS) { if (vty != NULL) - vty_out(vty, " PCE neighbor AS: %d\n", + vty_out(vty, " PCE Neighbor AS: %d\n", ntohl(top->value)); else - zlog_debug(" PCE neighbor AS: %d", + zlog_debug(" PCE Neighbor AS: %d", ntohl(top->value)); + } else { + if (vty != NULL) + vty_out(vty, " Wrong PCE Neighbor type: %d\n", + ntohl(top->type)); + else + zlog_debug(" Wrong PCE Neighbor type: %d", + ntohl(top->type)); } + return TLV_SIZE(tlvh); } @@ -1333,6 +1376,8 @@ static uint16_t show_vty_pce_subtlv_cap_flag(struct vty *vty, struct ri_pce_subtlv_cap_flag *top = (struct ri_pce_subtlv_cap_flag *)tlvh; + check_tlv_size(RI_PCE_SUBTLV_CAP_FLAG_SIZE, "PCE Capabilities"); + if (vty != NULL) vty_out(vty, " PCE Capabilities Flag: 0x%x\n", ntohl(top->value)); @@ -1343,8 +1388,21 @@ static uint16_t show_vty_pce_subtlv_cap_flag(struct vty *vty, return TLV_SIZE(tlvh); } -static uint16_t show_vty_unknown_tlv(struct vty *vty, struct tlv_header *tlvh) +static uint16_t show_vty_unknown_tlv(struct vty *vty, struct tlv_header *tlvh, + size_t buf_size) { + if (TLV_SIZE(tlvh) > buf_size) { + if (vty != NULL) + vty_out(vty, + " TLV size %d exceeds buffer size. Abort!", + TLV_SIZE(tlvh)); + else + zlog_debug( + " TLV size %d exceeds buffer size. Abort!", + TLV_SIZE(tlvh)); + return buf_size; + } + if (vty != NULL) vty_out(vty, " Unknown TLV: [type(0x%x), length(0x%x)]\n", ntohs(tlvh->type), ntohs(tlvh->length)); @@ -1356,12 +1414,21 @@ static uint16_t show_vty_unknown_tlv(struct vty *vty, struct tlv_header *tlvh) } static uint16_t show_vty_pce_info(struct vty *vty, struct tlv_header *ri, - uint32_t total) + size_t buf_size) { struct tlv_header *tlvh; + uint16_t length = ntohs(ri->length); uint16_t sum = 0; - for (tlvh = ri; sum < total; tlvh = TLV_HDR_NEXT(tlvh)) { + /* Verify that TLV length is valid against remaining buffer size */ + if (length > buf_size) { + vty_out(vty, + " PCE Info TLV size %d exceeds buffer size. Abort!\n", + length); + return buf_size; + } + + for (tlvh = ri; sum < length; tlvh = TLV_HDR_NEXT(tlvh)) { switch (ntohs(tlvh->type)) { case RI_PCE_SUBTLV_ADDRESS: sum += show_vty_pce_subtlv_address(vty, tlvh); @@ -1379,7 +1446,7 @@ static uint16_t show_vty_pce_info(struct vty *vty, struct tlv_header *ri, sum += show_vty_pce_subtlv_cap_flag(vty, tlvh); break; default: - sum += show_vty_unknown_tlv(vty, tlvh); + sum += show_vty_unknown_tlv(vty, tlvh, length - sum); break; } } @@ -1393,6 +1460,8 @@ static uint16_t show_vty_sr_algorithm(struct vty *vty, struct tlv_header *tlvh) (struct ri_sr_tlv_sr_algorithm *)tlvh; int i; + check_tlv_size(ALGORITHM_COUNT, "Segment Routing Algorithm"); + if (vty != NULL) { vty_out(vty, " Segment Routing Algorithm TLV:\n"); for (i = 0; i < ntohs(algo->header.length); i++) { @@ -1411,9 +1480,7 @@ static uint16_t show_vty_sr_algorithm(struct vty *vty, struct tlv_header *tlvh) break; } } - } - - else { + } else { zlog_debug(" Segment Routing Algorithm TLV:"); for (i = 0; i < ntohs(algo->header.length); i++) switch (algo->value[i]) { @@ -1439,6 +1506,8 @@ static uint16_t show_vty_sr_range(struct vty *vty, struct tlv_header *tlvh) struct ri_sr_tlv_sid_label_range *range = (struct ri_sr_tlv_sid_label_range *)tlvh; + check_tlv_size(RI_SR_TLV_LABEL_RANGE_SIZE, "SR Label Range"); + if (vty != NULL) { vty_out(vty, " Segment Routing %s Range TLV:\n" @@ -1467,6 +1536,8 @@ static uint16_t show_vty_sr_msd(struct vty *vty, struct tlv_header *tlvh) { struct ri_sr_tlv_node_msd *msd = (struct ri_sr_tlv_node_msd *)tlvh; + check_tlv_size(RI_SR_TLV_NODE_MSD_SIZE, "Node Maximum Stack Depth"); + if (vty != NULL) { vty_out(vty, " Segment Routing MSD TLV:\n" @@ -1488,9 +1559,9 @@ static void ospf_router_info_show_info(struct vty *vty, struct ospf_lsa *lsa) uint16_t length = 0, sum = 0; /* Initialize TLV browsing */ - length = ntohs(lsah->length) - OSPF_LSA_HEADER_SIZE; + length = lsa->size - OSPF_LSA_HEADER_SIZE; - for (tlvh = TLV_HDR_TOP(lsah); sum < length; + for (tlvh = TLV_HDR_TOP(lsah); sum < length && tlvh; tlvh = TLV_HDR_NEXT(tlvh)) { switch (ntohs(tlvh->type)) { case RI_TLV_CAPABILITIES: @@ -1513,7 +1584,7 @@ static void ospf_router_info_show_info(struct vty *vty, struct ospf_lsa *lsa) break; default: - sum += show_vty_unknown_tlv(vty, tlvh); + sum += show_vty_unknown_tlv(vty, tlvh, length); break; } } diff --git a/ospfd/ospf_ri.h b/ospfd/ospf_ri.h index 4729677bca..bbad896280 100644 --- a/ospfd/ospf_ri.h +++ b/ospfd/ospf_ri.h @@ -75,7 +75,7 @@ /* RFC4970: Router Information Capabilities TLV */ /* Mandatory */ #define RI_TLV_CAPABILITIES 1 - +#define RI_TLV_CAPABILITIES_SIZE 4 struct ri_tlv_router_cap { struct tlv_header header; /* Value length is 4 bytes. */ uint32_t value; @@ -105,12 +105,12 @@ struct ri_tlv_pce { struct ri_pce_subtlv_address { /* Type = 1; Length is 8 (IPv4) or 20 (IPv6) bytes. */ struct tlv_header header; -#define PCE_ADDRESS_LENGTH_IPV4 8 -#define PCE_ADDRESS_LENGTH_IPV6 20 +#define PCE_ADDRESS_IPV4_SIZE 8 +#define PCE_ADDRESS_IPV6_SIZE 20 struct { uint16_t type; /* Address type: 1 = IPv4, 2 = IPv6 */ -#define PCE_ADDRESS_TYPE_IPV4 1 -#define PCE_ADDRESS_TYPE_IPV6 2 +#define PCE_ADDRESS_IPV4 1 +#define PCE_ADDRESS_IPV6 2 uint16_t reserved; struct in_addr value; /* PCE address */ } address; @@ -118,6 +118,7 @@ struct ri_pce_subtlv_address { /* PCE Path-Scope Sub-TLV */ /* Mandatory */ #define RI_PCE_SUBTLV_PATH_SCOPE 2 +#define RI_PCE_SUBTLV_PATH_SCOPE_SIZE 4 struct ri_pce_subtlv_path_scope { struct tlv_header header; /* Type = 2; Length = 4 bytes. */ /* @@ -128,11 +129,11 @@ struct ri_pce_subtlv_path_scope { }; /* PCE Domain Sub-TLV */ /* Optional */ -#define RI_PCE_SUBTLV_DOMAIN 3 - #define PCE_DOMAIN_TYPE_AREA 1 -#define PCE_DOMAIN_TYPE_AS 2 +#define PCE_DOMAIN_TYPE_AS 2 +#define RI_PCE_SUBTLV_DOMAIN 3 +#define RI_PCE_SUBTLV_DOMAIN_SIZE 8 struct ri_pce_subtlv_domain { struct tlv_header header; /* Type = 3; Length = 8 bytes. */ uint16_t type; /* Domain type: 1 = OSPF Area ID, 2 = AS Number */ @@ -142,6 +143,7 @@ struct ri_pce_subtlv_domain { /* PCE Neighbor Sub-TLV */ /* Mandatory if R or S bit is set */ #define RI_PCE_SUBTLV_NEIGHBOR 4 +#define RI_PCE_SUBTLV_NEIGHBOR_SIZE 8 struct ri_pce_subtlv_neighbor { struct tlv_header header; /* Type = 4; Length = 8 bytes. */ uint16_t type; /* Domain type: 1 = OSPF Area ID, 2 = AS Number */ @@ -151,6 +153,7 @@ struct ri_pce_subtlv_neighbor { /* PCE Capabilities Flags Sub-TLV */ /* Optional */ #define RI_PCE_SUBTLV_CAP_FLAG 5 +#define RI_PCE_SUBTLV_CAP_FLAG_SIZE 4 #define PCE_CAP_GMPLS_LINK 0x0001 #define PCE_CAP_BIDIRECTIONAL 0x0002 diff --git a/ospfd/ospf_sr.c b/ospfd/ospf_sr.c index d003f3bf7c..3ce177618f 100644 --- a/ospfd/ospf_sr.c +++ b/ospfd/ospf_sr.c @@ -954,7 +954,7 @@ static inline void update_adj_sid(struct sr_nhlfe n1, struct sr_nhlfe n2) */ /* Extended Link SubTLVs Getter */ -static struct sr_link *get_ext_link_sid(struct tlv_header *tlvh) +static struct sr_link *get_ext_link_sid(struct tlv_header *tlvh, size_t size) { struct sr_link *srl; @@ -966,13 +966,20 @@ static struct sr_link *get_ext_link_sid(struct tlv_header *tlvh) struct tlv_header *sub_tlvh; uint16_t length = 0, sum = 0, i = 0; + /* Check TLV size */ + if ((ntohs(tlvh->length) > size) + || ntohs(tlvh->length) < EXT_TLV_LINK_SIZE) { + zlog_warn("Wrong Extended Link TLV size. Abort!"); + return NULL; + } + srl = XCALLOC(MTYPE_OSPF_SR_PARAMS, sizeof(struct sr_link)); /* Initialize TLV browsing */ length = ntohs(tlvh->length) - EXT_TLV_LINK_SIZE; sub_tlvh = (struct tlv_header *)((char *)(tlvh) + TLV_HDR_SIZE + EXT_TLV_LINK_SIZE); - for (; sum < length; sub_tlvh = TLV_HDR_NEXT(sub_tlvh)) { + for (; sum < length && sub_tlvh; sub_tlvh = TLV_HDR_NEXT(sub_tlvh)) { switch (ntohs(sub_tlvh->type)) { case EXT_SUBTLV_ADJ_SID: adj_sid = (struct ext_subtlv_adj_sid *)sub_tlvh; @@ -1025,7 +1032,8 @@ static struct sr_link *get_ext_link_sid(struct tlv_header *tlvh) } /* Extended Prefix SubTLVs Getter */ -static struct sr_prefix *get_ext_prefix_sid(struct tlv_header *tlvh) +static struct sr_prefix *get_ext_prefix_sid(struct tlv_header *tlvh, + size_t size) { struct sr_prefix *srp; @@ -1035,13 +1043,20 @@ static struct sr_prefix *get_ext_prefix_sid(struct tlv_header *tlvh) struct tlv_header *sub_tlvh; uint16_t length = 0, sum = 0; + /* Check TLV size */ + if ((ntohs(tlvh->length) > size) + || ntohs(tlvh->length) < EXT_TLV_PREFIX_SIZE) { + zlog_warn("Wrong Extended Link TLV size. Abort!"); + return NULL; + } + srp = XCALLOC(MTYPE_OSPF_SR_PARAMS, sizeof(struct sr_prefix)); /* Initialize TLV browsing */ length = ntohs(tlvh->length) - EXT_TLV_PREFIX_SIZE; sub_tlvh = (struct tlv_header *)((char *)(tlvh) + TLV_HDR_SIZE + EXT_TLV_PREFIX_SIZE); - for (; sum < length; sub_tlvh = TLV_HDR_NEXT(sub_tlvh)) { + for (; sum < length && sub_tlvh; sub_tlvh = TLV_HDR_NEXT(sub_tlvh)) { switch (ntohs(sub_tlvh->type)) { case EXT_SUBTLV_PREFIX_SID: psid = (struct ext_subtlv_prefix_sid *)sub_tlvh; @@ -1353,7 +1368,7 @@ void ospf_sr_ri_lsa_update(struct ospf_lsa *lsa) /* Collect Router Information Sub TLVs */ /* Initialize TLV browsing */ - length = ntohs(lsah->length) - OSPF_LSA_HEADER_SIZE; + length = lsa->size - OSPF_LSA_HEADER_SIZE; srgb.range_size = 0; srgb.lower_bound = 0; @@ -1362,24 +1377,20 @@ void ospf_sr_ri_lsa_update(struct ospf_lsa *lsa) switch (ntohs(tlvh->type)) { case RI_SR_TLV_SR_ALGORITHM: algo = (struct ri_sr_tlv_sr_algorithm *)tlvh; - sum += TLV_SIZE(tlvh); break; case RI_SR_TLV_SRGB_LABEL_RANGE: ri_srgb = (struct ri_sr_tlv_sid_label_range *)tlvh; - sum += TLV_SIZE(tlvh); break; case RI_SR_TLV_SRLB_LABEL_RANGE: ri_srlb = (struct ri_sr_tlv_sid_label_range *)tlvh; - sum += TLV_SIZE(tlvh); break; case RI_SR_TLV_NODE_MSD: msd = ((struct ri_sr_tlv_node_msd *)(tlvh))->value; - sum += TLV_SIZE(tlvh); break; default: - sum += TLV_SIZE(tlvh); break; } + sum += TLV_SIZE(tlvh); } /* Check if Segment Routing Capabilities has been found */ @@ -1519,7 +1530,7 @@ void ospf_sr_ext_link_lsa_update(struct ospf_lsa *lsa) struct lsa_header *lsah = lsa->data; struct sr_link *srl; - uint16_t length, sum; + int length; osr_debug("SR (%s): Process Extended Link LSA 8.0.0.%u from %pI4", __func__, GET_OPAQUE_ID(ntohl(lsah->id.s_addr)), @@ -1546,20 +1557,19 @@ void ospf_sr_ext_link_lsa_update(struct ospf_lsa *lsa) } /* Initialize TLV browsing */ - length = ntohs(lsah->length) - OSPF_LSA_HEADER_SIZE; - sum = 0; - for (tlvh = TLV_HDR_TOP(lsah); (sum < length) && (tlvh != NULL); + length = lsa->size - OSPF_LSA_HEADER_SIZE; + for (tlvh = TLV_HDR_TOP(lsah); length > 0 && tlvh; tlvh = TLV_HDR_NEXT(tlvh)) { if (ntohs(tlvh->type) == EXT_TLV_LINK) { /* Got Extended Link information */ - srl = get_ext_link_sid(tlvh); + srl = get_ext_link_sid(tlvh, length); /* Update SID if not null */ if (srl != NULL) { srl->instance = ntohl(lsah->id.s_addr); update_ext_link_sid(srn, srl, lsa->flags); } } - sum += TLV_SIZE(tlvh); + length -= TLV_SIZE(tlvh); } } @@ -1753,7 +1763,7 @@ void ospf_sr_ext_prefix_lsa_update(struct ospf_lsa *lsa) struct lsa_header *lsah = (struct lsa_header *)lsa->data; struct sr_prefix *srp; - uint16_t length, sum; + int length; osr_debug("SR (%s): Process Extended Prefix LSA 7.0.0.%u from %pI4", __func__, GET_OPAQUE_ID(ntohl(lsah->id.s_addr)), @@ -1780,20 +1790,19 @@ void ospf_sr_ext_prefix_lsa_update(struct ospf_lsa *lsa) } /* Initialize TLV browsing */ - length = ntohs(lsah->length) - OSPF_LSA_HEADER_SIZE; - sum = 0; - for (tlvh = TLV_HDR_TOP(lsah); sum < length; + length = lsa->size - OSPF_LSA_HEADER_SIZE; + for (tlvh = TLV_HDR_TOP(lsah); length > 0 && tlvh; tlvh = TLV_HDR_NEXT(tlvh)) { if (ntohs(tlvh->type) == EXT_TLV_LINK) { /* Got Extended Link information */ - srp = get_ext_prefix_sid(tlvh); + srp = get_ext_prefix_sid(tlvh, length); /* Update SID if not null */ if (srp != NULL) { srp->instance = ntohl(lsah->id.s_addr); update_ext_prefix_sid(srn, srp); } } - sum += TLV_SIZE(tlvh); + length -= TLV_SIZE(tlvh); } } diff --git a/ospfd/ospf_sr.h b/ospfd/ospf_sr.h index ce13457484..ea54e3b310 100644 --- a/ospfd/ospf_sr.h +++ b/ospfd/ospf_sr.h @@ -61,7 +61,7 @@ /* SID/Label Sub TLV - section 2.1 */ #define SUBTLV_SID_LABEL 1 -#define SUBTLV_SID_LABEL_SIZE 8 +#define SUBTLV_SID_LABEL_SIZE 4 struct subtlv_sid_label { /* Length is 3 (20 rightmost bits MPLS label) or 4 (32 bits SID) */ struct tlv_header header; @@ -88,6 +88,7 @@ struct ri_sr_tlv_sr_algorithm { /* RI SID/Label Range TLV used for SRGB & SRLB - section 3.2 & 3.3 */ #define RI_SR_TLV_SRGB_LABEL_RANGE 9 #define RI_SR_TLV_SRLB_LABEL_RANGE 14 +#define RI_SR_TLV_LABEL_RANGE_SIZE 12 struct ri_sr_tlv_sid_label_range { struct tlv_header header; /* Only 24 upper most bits are significant */ @@ -99,6 +100,7 @@ struct ri_sr_tlv_sid_label_range { /* RI Node/MSD TLV as per RFC 8476 */ #define RI_SR_TLV_NODE_MSD 12 +#define RI_SR_TLV_NODE_MSD_SIZE 4 struct ri_sr_tlv_node_msd { struct tlv_header header; uint8_t subtype; /* always = 1 */ diff --git a/ospfd/ospf_te.c b/ospfd/ospf_te.c index 1929e3dea4..333fa6a3a1 100644 --- a/ospfd/ospf_te.c +++ b/ospfd/ospf_te.c @@ -1882,7 +1882,7 @@ static int ospf_te_parse_router_lsa(struct ls_ted *ted, struct ospf_lsa *lsa) struct ls_edge *edge; struct ls_subnet *subnet; struct listnode *node; - int len; + int len, links; /* Sanity Check */ if (!ted || !lsa || !lsa->data) @@ -1932,8 +1932,9 @@ static int ospf_te_parse_router_lsa(struct ls_ted *ted, struct ospf_lsa *lsa) subnet->status = ORPHAN; /* Then, process Link Information */ - len = ntohs(rl->header.length) - 4; - for (int i = 0; i < ntohs(rl->links) && len > 0; len -= 12, i++) { + len = lsa->size - OSPF_LSA_HEADER_SIZE - OSPF_ROUTER_LSA_MIN_SIZE; + links = ntohs(rl->links); + for (int i = 0; i < links && len > 0; len -= 12, i++) { struct prefix p; uint32_t metric; @@ -2152,20 +2153,20 @@ static int ospf_te_parse_te(struct ls_ted *ted, struct ospf_lsa *lsa) /* Initialize TLV browsing */ tlvh = TLV_HDR_TOP(lsa->data); + len = lsa->size - OSPF_LSA_HEADER_SIZE; - uint32_t total_len = TLV_BODY_SIZE(lsa->data) - OSPF_LSA_HEADER_SIZE; + /* Check if TE Router-ID TLV is present */ + if (ntohs(tlvh->type) == TE_TLV_ROUTER_ADDR) { + /* if TE Router-ID is alone, we are done ... */ + if (len == TE_LINK_SUBTLV_DEF_SIZE) + return 0; - /* If TE Router-ID is only TLV we are done */ - if (ntohs(tlvh->type) == TE_TLV_ROUTER_ADDR - && total_len == sizeof(struct te_tlv_router_addr)) - return 0; - - /* Skip TE Router-ID if present */ - if (ntohs(tlvh->type) == TE_TLV_ROUTER_ADDR) + /* ... otherwise, skip it */ + len -= TE_LINK_SUBTLV_DEF_SIZE + TLV_HDR_SIZE; tlvh = TLV_HDR_NEXT(tlvh); + } - /* Check if we have a TE Link TLV */ - len = TLV_BODY_SIZE(tlvh); + /* Check if we have a valid TE Link TLV */ if ((len == 0) || (ntohs(tlvh->type) != TE_TLV_LINK)) return 0; @@ -2467,8 +2468,9 @@ static int ospf_te_parse_ri(struct ls_ted *ted, struct ospf_lsa *lsa) &lsa->data->id, &node->router_id); /* Initialize TLV browsing */ - len = ntohs(lsah->length) - OSPF_LSA_HEADER_SIZE; - for (tlvh = TLV_HDR_TOP(lsah); sum < len; tlvh = TLV_HDR_NEXT(tlvh)) { + len = lsa->size - OSPF_LSA_HEADER_SIZE; + for (tlvh = TLV_HDR_TOP(lsah); sum < len && tlvh; + tlvh = TLV_HDR_NEXT(tlvh)) { struct ri_sr_tlv_sr_algorithm *algo; struct ri_sr_tlv_sid_label_range *range; struct ri_sr_tlv_node_msd *msd; @@ -3152,11 +3154,25 @@ static void ospf_te_init_ted(struct ls_ted *ted, struct ospf *ospf) /*------------------------------------------------------------------------* * Followings are vty session control functions. *------------------------------------------------------------------------*/ +#define check_tlv_size(size, msg) \ + do { \ + if (ntohs(tlvh->length) > size) { \ + if (vty != NULL) \ + vty_out(vty, " Wrong %s TLV size: %d(%d)\n", \ + msg, ntohs(tlvh->length), size); \ + else \ + zlog_debug(" Wrong %s TLV size: %d(%d)", \ + msg, ntohs(tlvh->length), size); \ + return size + TLV_HDR_SIZE; \ + } \ + } while (0) static uint16_t show_vty_router_addr(struct vty *vty, struct tlv_header *tlvh) { struct te_tlv_router_addr *top = (struct te_tlv_router_addr *)tlvh; + check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Router Address"); + if (vty != NULL) vty_out(vty, " Router-Address: %pI4\n", &top->value); else @@ -3165,10 +3181,23 @@ static uint16_t show_vty_router_addr(struct vty *vty, struct tlv_header *tlvh) return TLV_SIZE(tlvh); } -static uint16_t show_vty_link_header(struct vty *vty, struct tlv_header *tlvh) +static uint16_t show_vty_link_header(struct vty *vty, struct tlv_header *tlvh, + size_t buf_size) { struct te_tlv_link *top = (struct te_tlv_link *)tlvh; + if (TLV_SIZE(tlvh) > buf_size) { + if (vty != NULL) + vty_out(vty, + " TLV size %d exceeds buffer size. Abort!", + TLV_SIZE(tlvh)); + else + zlog_debug( + " TLV size %d exceeds buffer size. Abort!", + TLV_SIZE(tlvh)); + return buf_size; + } + if (vty != NULL) vty_out(vty, " Link: %u octets of data\n", ntohs(top->header.length)); @@ -3185,6 +3214,8 @@ static uint16_t show_vty_link_subtlv_link_type(struct vty *vty, struct te_link_subtlv_link_type *top; const char *cp = "Unknown"; + check_tlv_size(TE_LINK_SUBTLV_TYPE_SIZE, "Link Type"); + top = (struct te_link_subtlv_link_type *)tlvh; switch (top->link_type.value) { case LINK_TYPE_SUBTLV_VALUE_PTP: @@ -3211,6 +3242,8 @@ static uint16_t show_vty_link_subtlv_link_id(struct vty *vty, { struct te_link_subtlv_link_id *top; + check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Link ID"); + top = (struct te_link_subtlv_link_id *)tlvh; if (vty != NULL) vty_out(vty, " Link-ID: %pI4\n", &top->value); @@ -3221,11 +3254,24 @@ static uint16_t show_vty_link_subtlv_link_id(struct vty *vty, } static uint16_t show_vty_link_subtlv_lclif_ipaddr(struct vty *vty, - struct tlv_header *tlvh) + struct tlv_header *tlvh, + size_t buf_size) { struct te_link_subtlv_lclif_ipaddr *top; int i, n; + if (TLV_SIZE(tlvh) > buf_size) { + if (vty != NULL) + vty_out(vty, + " TLV size %d exceeds buffer size. Abort!", + TLV_SIZE(tlvh)); + else + zlog_debug( + " TLV size %d exceeds buffer size. Abort!", + TLV_SIZE(tlvh)); + return buf_size; + } + top = (struct te_link_subtlv_lclif_ipaddr *)tlvh; n = ntohs(tlvh->length) / sizeof(top->value[0]); @@ -3244,11 +3290,24 @@ static uint16_t show_vty_link_subtlv_lclif_ipaddr(struct vty *vty, } static uint16_t show_vty_link_subtlv_rmtif_ipaddr(struct vty *vty, - struct tlv_header *tlvh) + struct tlv_header *tlvh, + size_t buf_size) { struct te_link_subtlv_rmtif_ipaddr *top; int i, n; + if (TLV_SIZE(tlvh) > buf_size) { + if (vty != NULL) + vty_out(vty, + " TLV size %d exceeds buffer size. Abort!", + TLV_SIZE(tlvh)); + else + zlog_debug( + " TLV size %d exceeds buffer size. Abort!", + TLV_SIZE(tlvh)); + return buf_size; + } + top = (struct te_link_subtlv_rmtif_ipaddr *)tlvh; n = ntohs(tlvh->length) / sizeof(top->value[0]); if (vty != NULL) @@ -3270,6 +3329,8 @@ static uint16_t show_vty_link_subtlv_te_metric(struct vty *vty, { struct te_link_subtlv_te_metric *top; + check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "TE Metric"); + top = (struct te_link_subtlv_te_metric *)tlvh; if (vty != NULL) vty_out(vty, " Traffic Engineering Metric: %u\n", @@ -3287,6 +3348,8 @@ static uint16_t show_vty_link_subtlv_max_bw(struct vty *vty, struct te_link_subtlv_max_bw *top; float fval; + check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Maximum Bandwidth"); + top = (struct te_link_subtlv_max_bw *)tlvh; fval = ntohf(top->value); @@ -3304,6 +3367,8 @@ static uint16_t show_vty_link_subtlv_max_rsv_bw(struct vty *vty, struct te_link_subtlv_max_rsv_bw *top; float fval; + check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Maximum Reservable Bandwidth"); + top = (struct te_link_subtlv_max_rsv_bw *)tlvh; fval = ntohf(top->value); @@ -3324,6 +3389,8 @@ static uint16_t show_vty_link_subtlv_unrsv_bw(struct vty *vty, float fval1, fval2; int i; + check_tlv_size(TE_LINK_SUBTLV_UNRSV_SIZE, "Unreserved Bandwidth"); + top = (struct te_link_subtlv_unrsv_bw *)tlvh; if (vty != NULL) vty_out(vty, @@ -3353,6 +3420,8 @@ static uint16_t show_vty_link_subtlv_rsc_clsclr(struct vty *vty, { struct te_link_subtlv_rsc_clsclr *top; + check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Resource class/color"); + top = (struct te_link_subtlv_rsc_clsclr *)tlvh; if (vty != NULL) vty_out(vty, " Resource class/color: 0x%x\n", @@ -3369,6 +3438,8 @@ static uint16_t show_vty_link_subtlv_lrrid(struct vty *vty, { struct te_link_subtlv_lrrid *top; + check_tlv_size(TE_LINK_SUBTLV_LRRID_SIZE, "Local/Remote Router ID"); + top = (struct te_link_subtlv_lrrid *)tlvh; if (vty != NULL) { @@ -3391,6 +3462,8 @@ static uint16_t show_vty_link_subtlv_llri(struct vty *vty, { struct te_link_subtlv_llri *top; + check_tlv_size(TE_LINK_SUBTLV_LLRI_SIZE, "Link Local/Remote ID"); + top = (struct te_link_subtlv_llri *)tlvh; if (vty != NULL) { @@ -3413,6 +3486,8 @@ static uint16_t show_vty_link_subtlv_rip(struct vty *vty, { struct te_link_subtlv_rip *top; + check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Remote ASBR Address"); + top = (struct te_link_subtlv_rip *)tlvh; if (vty != NULL) @@ -3430,6 +3505,8 @@ static uint16_t show_vty_link_subtlv_ras(struct vty *vty, { struct te_link_subtlv_ras *top; + check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Remote AS number"); + top = (struct te_link_subtlv_ras *)tlvh; if (vty != NULL) @@ -3449,6 +3526,8 @@ static uint16_t show_vty_link_subtlv_av_delay(struct vty *vty, uint32_t delay; uint32_t anomalous; + check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Average Link Delay"); + top = (struct te_link_subtlv_av_delay *)tlvh; delay = (uint32_t)ntohl(top->value) & TE_EXT_MASK; anomalous = (uint32_t)ntohl(top->value) & TE_EXT_ANORMAL; @@ -3470,6 +3549,8 @@ static uint16_t show_vty_link_subtlv_mm_delay(struct vty *vty, uint32_t low, high; uint32_t anomalous; + check_tlv_size(TE_LINK_SUBTLV_MM_DELAY_SIZE, "Min/Max Link Delay"); + top = (struct te_link_subtlv_mm_delay *)tlvh; low = (uint32_t)ntohl(top->low) & TE_EXT_MASK; anomalous = (uint32_t)ntohl(top->low) & TE_EXT_ANORMAL; @@ -3491,6 +3572,8 @@ static uint16_t show_vty_link_subtlv_delay_var(struct vty *vty, struct te_link_subtlv_delay_var *top; uint32_t jitter; + check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Link Delay Variation"); + top = (struct te_link_subtlv_delay_var *)tlvh; jitter = (uint32_t)ntohl(top->value) & TE_EXT_MASK; @@ -3510,6 +3593,8 @@ static uint16_t show_vty_link_subtlv_pkt_loss(struct vty *vty, uint32_t anomalous; float fval; + check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Link Loss"); + top = (struct te_link_subtlv_pkt_loss *)tlvh; loss = (uint32_t)ntohl(top->value) & TE_EXT_MASK; fval = (float)(loss * LOSS_PRECISION); @@ -3531,6 +3616,8 @@ static uint16_t show_vty_link_subtlv_res_bw(struct vty *vty, struct te_link_subtlv_res_bw *top; float fval; + check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Residual Bandwidth"); + top = (struct te_link_subtlv_res_bw *)tlvh; fval = ntohf(top->value); @@ -3552,6 +3639,8 @@ static uint16_t show_vty_link_subtlv_ava_bw(struct vty *vty, struct te_link_subtlv_ava_bw *top; float fval; + check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Available Bandwidth"); + top = (struct te_link_subtlv_ava_bw *)tlvh; fval = ntohf(top->value); @@ -3573,6 +3662,8 @@ static uint16_t show_vty_link_subtlv_use_bw(struct vty *vty, struct te_link_subtlv_use_bw *top; float fval; + check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Utilized Bandwidth"); + top = (struct te_link_subtlv_use_bw *)tlvh; fval = ntohf(top->value); @@ -3588,8 +3679,21 @@ static uint16_t show_vty_link_subtlv_use_bw(struct vty *vty, return TLV_SIZE(tlvh); } -static uint16_t show_vty_unknown_tlv(struct vty *vty, struct tlv_header *tlvh) +static uint16_t show_vty_unknown_tlv(struct vty *vty, struct tlv_header *tlvh, + size_t buf_size) { + if (TLV_SIZE(tlvh) > buf_size) { + if (vty != NULL) + vty_out(vty, + " TLV size %d exceeds buffer size. Abort!", + TLV_SIZE(tlvh)); + else + zlog_debug( + " TLV size %d exceeds buffer size. Abort!", + TLV_SIZE(tlvh)); + return buf_size; + } + if (vty != NULL) vty_out(vty, " Unknown TLV: [type(0x%x), length(0x%x)]\n", ntohs(tlvh->type), ntohs(tlvh->length)); @@ -3607,8 +3711,7 @@ static uint16_t ospf_mpls_te_show_link_subtlv(struct vty *vty, struct tlv_header *tlvh; uint16_t sum = subtotal; - for (tlvh = tlvh0; sum < total; - tlvh = TLV_HDR_NEXT(tlvh)) { + for (tlvh = tlvh0; sum < total; tlvh = TLV_HDR_NEXT(tlvh)) { switch (ntohs(tlvh->type)) { case TE_LINK_SUBTLV_LINK_TYPE: sum += show_vty_link_subtlv_link_type(vty, tlvh); @@ -3617,10 +3720,12 @@ static uint16_t ospf_mpls_te_show_link_subtlv(struct vty *vty, sum += show_vty_link_subtlv_link_id(vty, tlvh); break; case TE_LINK_SUBTLV_LCLIF_IPADDR: - sum += show_vty_link_subtlv_lclif_ipaddr(vty, tlvh); + sum += show_vty_link_subtlv_lclif_ipaddr(vty, tlvh, + total - sum); break; case TE_LINK_SUBTLV_RMTIF_IPADDR: - sum += show_vty_link_subtlv_rmtif_ipaddr(vty, tlvh); + sum += show_vty_link_subtlv_rmtif_ipaddr(vty, tlvh, + total - sum); break; case TE_LINK_SUBTLV_TE_METRIC: sum += show_vty_link_subtlv_te_metric(vty, tlvh); @@ -3671,7 +3776,7 @@ static uint16_t ospf_mpls_te_show_link_subtlv(struct vty *vty, sum += show_vty_link_subtlv_use_bw(vty, tlvh); break; default: - sum += show_vty_unknown_tlv(vty, tlvh); + sum += show_vty_unknown_tlv(vty, tlvh, total - sum); break; } } @@ -3687,9 +3792,9 @@ static void ospf_mpls_te_show_info(struct vty *vty, struct ospf_lsa *lsa) uint16_t subtotal, uint16_t total) = NULL; sum = 0; - total = ntohs(lsah->length) - OSPF_LSA_HEADER_SIZE; + total = lsa->size - OSPF_LSA_HEADER_SIZE; - for (tlvh = TLV_HDR_TOP(lsah); sum < total; + for (tlvh = TLV_HDR_TOP(lsah); sum < total && tlvh; tlvh = (next ? next : TLV_HDR_NEXT(tlvh))) { if (subfunc != NULL) { sum = (*subfunc)(vty, tlvh, sum, total); @@ -3704,12 +3809,12 @@ static void ospf_mpls_te_show_info(struct vty *vty, struct ospf_lsa *lsa) sum += show_vty_router_addr(vty, tlvh); break; case TE_TLV_LINK: - sum += show_vty_link_header(vty, tlvh); + sum += show_vty_link_header(vty, tlvh, total - sum); subfunc = ospf_mpls_te_show_link_subtlv; next = TLV_DATA(tlvh); break; default: - sum += show_vty_unknown_tlv(vty, tlvh); + sum += show_vty_unknown_tlv(vty, tlvh, total - sum); break; } } @@ -4081,10 +4186,12 @@ static void show_mpls_te_link_sub(struct vty *vty, struct interface *ifp) show_vty_link_subtlv_link_id(vty, &lp->link_id.header); if (TLV_TYPE(lp->lclif_ipaddr) != 0) show_vty_link_subtlv_lclif_ipaddr( - vty, &lp->lclif_ipaddr.header); + vty, &lp->lclif_ipaddr.header, + lp->lclif_ipaddr.header.length); if (TLV_TYPE(lp->rmtif_ipaddr) != 0) show_vty_link_subtlv_rmtif_ipaddr( - vty, &lp->rmtif_ipaddr.header); + vty, &lp->rmtif_ipaddr.header, + lp->rmtif_ipaddr.header.length); if (TLV_TYPE(lp->rip) != 0) show_vty_link_subtlv_rip(vty, &lp->rip.header); if (TLV_TYPE(lp->ras) != 0) diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index 50943c4ccf..04b6bdd961 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -6400,6 +6400,7 @@ static int show_network_lsa_detail(struct vty *vty, struct ospf_lsa *lsa, if (lsa != NULL) { struct network_lsa *nl = (struct network_lsa *)lsa->data; + struct in_addr *addr; show_ip_ospf_database_header(vty, lsa, json); @@ -6410,24 +6411,25 @@ static int show_network_lsa_detail(struct vty *vty, struct ospf_lsa *lsa, json_object_int_add(json, "networkMask", ip_masklen(nl->mask)); - length = ntohs(lsa->data->length) - OSPF_LSA_HEADER_SIZE - 4; - - for (i = 0; length > 0; i++, length -= 4) + length = lsa->size - OSPF_LSA_HEADER_SIZE - 4; + addr = &nl->routers[0]; + for (i = 0; length > 0 && addr; + length -= 4, addr = &nl->routers[++i]) if (!json) { vty_out(vty, " Attached Router: %pI4\n", - &nl->routers[i]); + addr); vty_out(vty, "\n"); } else { json_router = json_object_new_object(); json_object_string_add( json_router, "attachedRouterId", - inet_ntop(AF_INET, &nl->routers[i], - buf, sizeof(buf))); - json_object_object_add( - json_attached_rt, - inet_ntop(AF_INET, &(nl->routers[i]), - buf, sizeof(buf)), - json_router); + inet_ntop(AF_INET, addr, buf, + sizeof(buf))); + json_object_object_add(json_attached_rt, + inet_ntop(AF_INET, addr, + buf, + sizeof(buf)), + json_router); } } diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c index cc1404e5e9..7505f24aef 100644 --- a/ospfd/ospfd.c +++ b/ospfd/ospfd.c @@ -2182,6 +2182,16 @@ static void ospf_set_redist_vrf_bitmaps(struct ospf *ospf, bool set) vrf_bitmap_unset(zclient->redist[AFI_IP][type], ospf->vrf_id); } + + red_list = ospf->redist[DEFAULT_ROUTE]; + if (red_list) { + if (set) + vrf_bitmap_set(zclient->default_information[AFI_IP], + ospf->vrf_id); + else + vrf_bitmap_unset(zclient->default_information[AFI_IP], + ospf->vrf_id); + } } /* Enable OSPF VRF instance */ diff --git a/pathd/path_cli.c b/pathd/path_cli.c index 7a28449e4e..172737c9d4 100644 --- a/pathd/path_cli.c +++ b/pathd/path_cli.c @@ -351,8 +351,6 @@ static int segment_list_has_src_dst( nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, "ipv6_adjacency"); node_src_id = adj_src_ipv6_str; - } else { - return CMD_ERR_NO_MATCH; } /* addresses */ snprintf(xpath, XPATH_MAXLEN, "./segment[index='%s']/nai/local-address", @@ -421,8 +419,6 @@ int segment_list_has_prefix( sizeof(buf_prefix)); pre_ipaddr.ipa_type = IPADDR_V6; pre_ipaddr.ip._v6_addr = prefix_cli.u.prefix6; - } else { - return CMD_ERR_NO_MATCH; } snprintf(xpath, XPATH_MAXLEN, "./segment[index='%s']/nai/local-address", index_str); @@ -524,7 +520,7 @@ DEFPY(srte_segment_list_segment, srte_segment_list_segment_cmd, if (status != CMD_SUCCESS) return status; } else { - segment_list_has_prefix( + status = segment_list_has_prefix( vty, xpath, index, index_str, prefix_ipv4, prefix_ipv4_str, prefix_ipv6, prefix_ipv6_str, has_algo, algo, algo_str, has_iface_id, iface_id, iface_id_str); @@ -821,9 +817,8 @@ DEFPY(srte_candidate_no_bandwidth, return nb_cli_apply_changes(vty, NULL); } -DEFPY(srte_candidate_affinity_filter, - srte_candidate_affinity_filter_cmd, - "affinity {exclude-any|include-any|include-all}$type BITPATTERN$value", +DEFPY(srte_candidate_affinity_filter, srte_candidate_affinity_filter_cmd, + "affinity <exclude-any|include-any|include-all>$type BITPATTERN$value", "Affinity constraint\n" "Exclude any matching link\n" "Include any matching link\n" @@ -846,9 +841,8 @@ DEFPY(srte_candidate_affinity_filter, return nb_cli_apply_changes(vty, NULL); } -DEFPY(srte_candidate_no_affinity_filter, - srte_candidate_no_affinity_filter_cmd, - "no affinity {exclude-any|include-any|include-all}$type [BITPATTERN$value]", +DEFPY(srte_candidate_no_affinity_filter, srte_candidate_no_affinity_filter_cmd, + "no affinity <exclude-any|include-any|include-all>$type [BITPATTERN$value]", NO_STR "Affinity constraint\n" "Exclude any matching link\n" diff --git a/pathd/path_pcep_pcc.c b/pathd/path_pcep_pcc.c index 9af2148819..779c400b86 100644 --- a/pathd/path_pcep_pcc.c +++ b/pathd/path_pcep_pcc.c @@ -1273,7 +1273,8 @@ void handle_pcep_comp_reply(struct ctrl_state *ctrl_state, * pathd API is thread safe, we could get a new path */ if (pcc_state->caps.is_stateful) { PCEP_DEBUG("%s Delegating undefined dynamic path %s to PCE %s", - pcc_state->tag, path->name, pcc_state->originator); + pcc_state->tag, req->path->name, + pcc_state->originator); path = pcep_copy_path(req->path); path->is_delegated = true; send_report(pcc_state, path); diff --git a/pathd/pathd.c b/pathd/pathd.c index 2462b08306..9dc3a41638 100644 --- a/pathd/pathd.c +++ b/pathd/pathd.c @@ -195,14 +195,16 @@ int srte_segment_entry_set_nai(struct srte_segment_entry *segment, struct ipaddr *remote_ip, uint32_t remote_iface, uint8_t algo, uint8_t pref_len) { + int32_t status = 0; struct prefix pre = {0}; - segment->nai_type = type; - memcpy(&segment->nai_local_addr, local_ip, sizeof(struct ipaddr)); if (!segment || !local_ip || !remote_ip) return 1; + segment->nai_type = type; + memcpy(&segment->nai_local_addr, local_ip, sizeof(struct ipaddr)); + switch (type) { case SRTE_SEGMENT_NAI_TYPE_IPV4_NODE: case SRTE_SEGMENT_NAI_TYPE_IPV6_NODE: diff --git a/pbrd/pbr_nht.c b/pbrd/pbr_nht.c index e127999b0b..301550deb7 100644 --- a/pbrd/pbr_nht.c +++ b/pbrd/pbr_nht.c @@ -721,7 +721,7 @@ pbr_nht_individual_nexthop_gw_update(struct pbr_nexthop_cache *pnhc, * So let's search and do the right thing on the * interface event. */ - if (!pnhi->nhr && pnhi->ifp) { + if (!pnhi->nhr) { switch (pnhc->nexthop.type) { case NEXTHOP_TYPE_BLACKHOLE: case NEXTHOP_TYPE_IPV4: @@ -738,20 +738,18 @@ pbr_nht_individual_nexthop_gw_update(struct pbr_nexthop_cache *pnhc, goto done; } - if (pnhi->nhr) { - switch (pnhi->nhr->prefix.family) { - case AF_INET: - if (pnhc->nexthop.gate.ipv4.s_addr - != pnhi->nhr->prefix.u.prefix4.s_addr) - goto done; /* Unrelated change */ - break; - case AF_INET6: - if (memcmp(&pnhc->nexthop.gate.ipv6, - &pnhi->nhr->prefix.u.prefix6, 16) - != 0) - goto done; /* Unrelated change */ - break; - } + switch (pnhi->nhr->prefix.family) { + case AF_INET: + if (pnhc->nexthop.gate.ipv4.s_addr + != pnhi->nhr->prefix.u.prefix4.s_addr) + goto done; /* Unrelated change */ + break; + case AF_INET6: + if (memcmp(&pnhc->nexthop.gate.ipv6, + &pnhi->nhr->prefix.u.prefix6, 16) + != 0) + goto done; /* Unrelated change */ + break; } pnhi->nhr_matched = true; diff --git a/pimd/pim_bsm.c b/pimd/pim_bsm.c index 3fbe3317ba..ad5257630b 100644 --- a/pimd/pim_bsm.c +++ b/pimd/pim_bsm.c @@ -1320,7 +1320,7 @@ int pim_bsm_process(struct interface *ifp, struct ip *ip_hdr, uint8_t *buf, } } } else if (if_lookup_exact_address(&ip_hdr->ip_dst, AF_INET, - pim->vrf_id)) { + pim->vrf->vrf_id)) { /* Unicast BSM received - if ucast bsm not enabled on * the interface, drop it */ diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 548c866e4d..f6072b1771 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -810,7 +810,7 @@ static void igmp_show_interface_join(struct pim_instance *pim, struct vty *vty, if (uj) { json = json_object_new_object(); json_object_string_add(json, "vrf", - vrf_id_to_name(pim->vrf_id)); + vrf_id_to_name(pim->vrf->vrf_id)); } else { vty_out(vty, "Interface Address Source Group Socket Uptime \n"); @@ -2971,7 +2971,7 @@ static int pim_print_pnc_cache_walkcb(struct hash_bucket *bucket, void *arg) for (nh_node = pnc->nexthop; nh_node; nh_node = nh_node->next) { first_ifindex = nh_node->ifindex; - ifp = if_lookup_by_index(first_ifindex, pim->vrf_id); + ifp = if_lookup_by_index(first_ifindex, pim->vrf->vrf_id); vty_out(vty, "%-15s ", inet_ntop(AF_INET, &pnc->rpf.rpf_addr.u.prefix4, diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index 834399053b..353f133001 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -1050,7 +1050,7 @@ int pim_if_find_vifindex_by_ifindex(struct pim_instance *pim, ifindex_t ifindex) struct pim_interface *pim_ifp; struct interface *ifp; - ifp = if_lookup_by_index(ifindex, pim->vrf_id); + ifp = if_lookup_by_index(ifindex, pim->vrf->vrf_id); if (!ifp || !ifp->info) return -1; pim_ifp = ifp->info; @@ -1477,13 +1477,13 @@ void pim_if_create_pimreg(struct pim_instance *pim) char pimreg_name[INTERFACE_NAMSIZ]; if (!pim->regiface) { - if (pim->vrf_id == VRF_DEFAULT) + if (pim->vrf->vrf_id == VRF_DEFAULT) strlcpy(pimreg_name, "pimreg", sizeof(pimreg_name)); else snprintf(pimreg_name, sizeof(pimreg_name), "pimreg%u", pim->vrf->data.l.table_id); - pim->regiface = if_create_name(pimreg_name, pim->vrf_id); + pim->regiface = if_create_name(pimreg_name, pim->vrf->vrf_id); pim->regiface->ifindex = PIM_OIF_PIM_REGISTER_VIF; pim_if_new(pim->regiface, false, false, true, @@ -1566,6 +1566,16 @@ int pim_ifp_create(struct interface *ifp) if (pim_ifp) pim_ifp->pim = pim; pim_if_addr_add_all(ifp); + + /* + * Due to ordering issues based upon when + * a command is entered we should ensure that + * the pim reg is created for this vrf if we + * have configuration for it already. + * + * this is a no-op if it's already been done. + */ + pim_if_create_pimreg(pim); } /* diff --git a/pimd/pim_igmp_mtrace.c b/pimd/pim_igmp_mtrace.c index d36a275f85..73af44fc46 100644 --- a/pimd/pim_igmp_mtrace.c +++ b/pimd/pim_igmp_mtrace.c @@ -597,7 +597,7 @@ int igmp_mtrace_recv_qry_req(struct igmp_sock *igmp, struct ip *ip_hdr, */ if (!IPV4_CLASS_DE(ntohl(ip_hdr->ip_dst.s_addr))) if (!if_lookup_exact_address(&ip_hdr->ip_dst, AF_INET, - pim->vrf_id)) + pim->vrf->vrf_id)) return mtrace_forward_packet(pim, ip_hdr); if (igmp_msg_len < (int)sizeof(struct igmp_mtrace)) { diff --git a/pimd/pim_instance.c b/pimd/pim_instance.c index 019048abf1..47358f38e1 100644 --- a/pimd/pim_instance.c +++ b/pimd/pim_instance.c @@ -92,7 +92,6 @@ static struct pim_instance *pim_instance_init(struct vrf *vrf) pim->ecmp_enable = false; pim->ecmp_rebalance_enable = false; - pim->vrf_id = vrf->vrf_id; pim->vrf = vrf; pim->spt.switchover = PIM_SPT_IMMEDIATE; @@ -175,8 +174,17 @@ static int pim_vrf_delete(struct vrf *vrf) static int pim_vrf_enable(struct vrf *vrf) { struct pim_instance *pim = (struct pim_instance *)vrf->info; + struct interface *ifp; - zlog_debug("%s: for %s", __func__, vrf->name); + zlog_debug("%s: for %s %u", __func__, vrf->name, vrf->vrf_id); + + FOR_ALL_INTERFACES (vrf, ifp) { + if (!ifp->info) + continue; + + pim_if_create_pimreg(pim); + break; + } pim_mroute_socket_enable(pim); diff --git a/pimd/pim_instance.h b/pimd/pim_instance.h index 2b76da21b2..72c726690c 100644 --- a/pimd/pim_instance.h +++ b/pimd/pim_instance.h @@ -127,7 +127,7 @@ struct pim_router { /* Per VRF PIM DB */ struct pim_instance { - vrf_id_t vrf_id; + // vrf_id_t vrf_id; struct vrf *vrf; struct { diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index afd38face3..ab6d8c17df 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -56,7 +56,7 @@ static int pim_mroute_set(struct pim_instance *pim, int enable) /* * We need to create the VRF table for the pim mroute_socket */ - if (pim->vrf_id != VRF_DEFAULT) { + if (pim->vrf->vrf_id != VRF_DEFAULT) { frr_with_privs(&pimd_privs) { data = pim->vrf->data.l.table_id; @@ -609,7 +609,7 @@ static int pim_mroute_msg(struct pim_instance *pim, const char *buf, * the source * of the IP packet. */ - ifp = if_lookup_by_index(ifindex, pim->vrf_id); + ifp = if_lookup_by_index(ifindex, pim->vrf->vrf_id); if (!ifp || !ifp->info) return 0; diff --git a/pimd/pim_msdp_socket.c b/pimd/pim_msdp_socket.c index 9c3cdb2711..78a8265a1c 100644 --- a/pimd/pim_msdp_socket.c +++ b/pimd/pim_msdp_socket.c @@ -156,9 +156,9 @@ int pim_msdp_sock_listen(struct pim_instance *pim) sockopt_reuseaddr(sock); sockopt_reuseport(sock); - if (pim->vrf_id != VRF_DEFAULT) { + if (pim->vrf->vrf_id != VRF_DEFAULT) { struct interface *ifp = - if_lookup_by_name(pim->vrf->name, pim->vrf_id); + if_lookup_by_name(pim->vrf->name, pim->vrf->vrf_id); if (!ifp) { flog_err(EC_LIB_INTERFACE, "%s: Unable to lookup vrf interface: %s", @@ -243,9 +243,9 @@ int pim_msdp_sock_connect(struct pim_msdp_peer *mp) return -1; } - if (mp->pim->vrf_id != VRF_DEFAULT) { - struct interface *ifp = - if_lookup_by_name(mp->pim->vrf->name, mp->pim->vrf_id); + if (mp->pim->vrf->vrf_id != VRF_DEFAULT) { + struct interface *ifp = if_lookup_by_name(mp->pim->vrf->name, + mp->pim->vrf->vrf_id); if (!ifp) { flog_err(EC_LIB_INTERFACE, "%s: Unable to lookup vrf interface: %s", diff --git a/pimd/pim_nb_config.c b/pimd/pim_nb_config.c index 003a9947e4..11e8da3b87 100644 --- a/pimd/pim_nb_config.c +++ b/pimd/pim_nb_config.c @@ -220,7 +220,7 @@ static int pim_cmd_spt_switchover(struct pim_instance *pim, static int pim_ssm_cmd_worker(struct pim_instance *pim, const char *plist, char *errmsg, size_t errmsg_len) { - int result = pim_ssm_range_set(pim, pim->vrf_id, plist); + int result = pim_ssm_range_set(pim, pim->vrf->vrf_id, plist); int ret = NB_ERR; if (result == PIM_SSM_ERR_NONE) @@ -2398,7 +2398,7 @@ int lib_interface_pim_address_family_mroute_destroy( pim = pim_iifp->pim; oifname = yang_dnode_get_string(args->dnode, "./oif"); - oif = if_lookup_by_name(oifname, pim->vrf_id); + oif = if_lookup_by_name(oifname, pim->vrf->vrf_id); if (!oif) { snprintf(args->errmsg, args->errmsg_len, @@ -2457,7 +2457,7 @@ int lib_interface_pim_address_family_mroute_oif_modify( pim = pim_iifp->pim; oifname = yang_dnode_get_string(args->dnode, NULL); - oif = if_lookup_by_name(oifname, pim->vrf_id); + oif = if_lookup_by_name(oifname, pim->vrf->vrf_id); if (oif && (iif->ifindex == oif->ifindex)) { strlcpy(args->errmsg, @@ -2476,7 +2476,7 @@ int lib_interface_pim_address_family_mroute_oif_modify( pim = pim_iifp->pim; oifname = yang_dnode_get_string(args->dnode, NULL); - oif = if_lookup_by_name(oifname, pim->vrf_id); + oif = if_lookup_by_name(oifname, pim->vrf->vrf_id); if (!oif) { snprintf(args->errmsg, args->errmsg_len, "No such interface name %s", diff --git a/pimd/pim_nht.c b/pimd/pim_nht.c index 68e0a45690..23ba3498ae 100644 --- a/pimd/pim_nht.c +++ b/pimd/pim_nht.c @@ -54,7 +54,7 @@ void pim_sendmsg_zebra_rnh(struct pim_instance *pim, struct zclient *zclient, int ret; p = &(pnc->rpf.rpf_addr); - ret = zclient_send_rnh(zclient, command, p, false, pim->vrf_id); + ret = zclient_send_rnh(zclient, command, p, false, pim->vrf->vrf_id); if (ret == ZCLIENT_SEND_FAILURE) zlog_warn("sendmsg_nexthop: zclient_send_message() failed"); @@ -266,7 +266,7 @@ bool pim_nexthop_match(struct pim_instance *pim, struct in_addr addr, while (i < num_ifindex) { first_ifindex = nexthop_tab[i].ifindex; - ifp = if_lookup_by_index(first_ifindex, pim->vrf_id); + ifp = if_lookup_by_index(first_ifindex, pim->vrf->vrf_id); if (!ifp) { if (PIM_DEBUG_ZEBRA) { char addr_str[INET_ADDRSTRLEN]; @@ -344,7 +344,7 @@ bool pim_nexthop_match_nht_cache(struct pim_instance *pim, struct in_addr addr, for (nh_node = pnc->nexthop; nh_node; nh_node = nh_node->next) { first_ifindex = nh_node->ifindex; - ifp = if_lookup_by_index(first_ifindex, pim->vrf_id); + ifp = if_lookup_by_index(first_ifindex, pim->vrf->vrf_id); if (!ifp) { if (PIM_DEBUG_PIM_NHT) { char addr_str[INET_ADDRSTRLEN]; @@ -590,7 +590,8 @@ static int pim_ecmp_nexthop_search(struct pim_instance *pim, */ for (nh_node = pnc->nexthop, i = 0; nh_node; nh_node = nh_node->next, i++) { - ifps[i] = if_lookup_by_index(nh_node->ifindex, pim->vrf_id); + ifps[i] = + if_lookup_by_index(nh_node->ifindex, pim->vrf->vrf_id); if (ifps[i]) { nbrs[i] = pim_neighbor_find(ifps[i], nh_node->gate.ipv4); @@ -774,7 +775,7 @@ int pim_parse_nexthop_update(ZAPI_CALLBACK_ARGS) break; case NEXTHOP_TYPE_IPV6_IFINDEX: ifp1 = if_lookup_by_index(nexthop->ifindex, - pim->vrf_id); + pim->vrf->vrf_id); if (!ifp1) nbr = NULL; @@ -793,7 +794,8 @@ int pim_parse_nexthop_update(ZAPI_CALLBACK_ARGS) break; } - ifp = if_lookup_by_index(nexthop->ifindex, pim->vrf_id); + ifp = if_lookup_by_index(nexthop->ifindex, + pim->vrf->vrf_id); if (!ifp) { if (PIM_DEBUG_PIM_NHT) { char buf[NEXTHOP_STRLEN]; @@ -940,7 +942,7 @@ int pim_ecmp_nexthop_lookup(struct pim_instance *pim, */ for (i = 0; i < num_ifindex; i++) { ifps[i] = if_lookup_by_index(nexthop_tab[i].ifindex, - pim->vrf_id); + pim->vrf->vrf_id); if (ifps[i]) { nbrs[i] = pim_neighbor_find( ifps[i], nexthop_tab[i].nexthop_addr.u.prefix4); @@ -1076,7 +1078,8 @@ int pim_ecmp_fib_lookup_if_vif_index(struct pim_instance *pim, if (PIM_DEBUG_PIM_NHT) zlog_debug( "%s: found nexthop ifindex=%d (interface %s(%s)) for address %s", - __func__, ifindex, ifindex2ifname(ifindex, pim->vrf_id), + __func__, ifindex, + ifindex2ifname(ifindex, pim->vrf->vrf_id), pim->vrf->name, addr_str); vif_index = pim_if_find_vifindex_by_ifindex(pim, ifindex); diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c index 4ba08a19d8..e7ac0d4e5b 100644 --- a/pimd/pim_pim.c +++ b/pimd/pim_pim.c @@ -369,7 +369,7 @@ static int pim_sock_read(struct thread *t) * the right ifindex, so just use it. We know * it's the right interface because we bind to it */ - ifp = if_lookup_by_index(ifindex, pim_ifp->pim->vrf_id); + ifp = if_lookup_by_index(ifindex, pim_ifp->pim->vrf->vrf_id); if (!ifp || !ifp->info) { if (PIM_DEBUG_PIM_PACKETS) zlog_debug( diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c index feaeea929d..a31fec036f 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -1159,7 +1159,7 @@ int pim_rp_config_write(struct pim_instance *pim, struct vty *vty, bool pim_rp_check_is_my_ip_address(struct pim_instance *pim, struct in_addr dest_addr) { - if (if_lookup_exact_address(&dest_addr, AF_INET, pim->vrf_id)) + if (if_lookup_exact_address(&dest_addr, AF_INET, pim->vrf->vrf_id)) return true; return false; @@ -1323,7 +1323,7 @@ void pim_resolve_rp_nh(struct pim_instance *pim, struct pim_neighbor *nbr) continue; struct interface *ifp1 = if_lookup_by_index( - nh_node->ifindex, pim->vrf_id); + nh_node->ifindex, pim->vrf->vrf_id); if (nbr->interface != ifp1) continue; diff --git a/pimd/pim_rpf.c b/pimd/pim_rpf.c index 043ccdb848..98944e8fed 100644 --- a/pimd/pim_rpf.c +++ b/pimd/pim_rpf.c @@ -112,7 +112,7 @@ bool pim_nexthop_lookup(struct pim_instance *pim, struct pim_nexthop *nexthop, while (!found && (i < num_ifindex)) { first_ifindex = nexthop_tab[i].ifindex; - ifp = if_lookup_by_index(first_ifindex, pim->vrf_id); + ifp = if_lookup_by_index(first_ifindex, pim->vrf->vrf_id); if (!ifp) { if (PIM_DEBUG_ZEBRA) { char addr_str[INET_ADDRSTRLEN]; diff --git a/pimd/pim_ssm.c b/pimd/pim_ssm.c index 8d3e04f5da..6c5883aebf 100644 --- a/pimd/pim_ssm.c +++ b/pimd/pim_ssm.c @@ -112,7 +112,7 @@ int pim_ssm_range_set(struct pim_instance *pim, vrf_id_t vrf_id, struct pim_ssm *ssm; int change = 0; - if (vrf_id != pim->vrf_id) + if (vrf_id != pim->vrf->vrf_id) return PIM_SSM_ERR_NO_VRF; ssm = pim->ssm_info; diff --git a/pimd/pim_ssmpingd.c b/pimd/pim_ssmpingd.c index 03e77de161..abd95e648e 100644 --- a/pimd/pim_ssmpingd.c +++ b/pimd/pim_ssmpingd.c @@ -267,7 +267,7 @@ static int ssmpingd_read_msg(struct ssmpingd_sock *ss) return -1; } - ifp = if_lookup_by_index(ifindex, ss->pim->vrf_id); + ifp = if_lookup_by_index(ifindex, ss->pim->vrf->vrf_id); if (buf[0] != PIM_SSMPINGD_REQUEST) { char source_str[INET_ADDRSTRLEN]; diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c index 929d35101e..c049ef4029 100644 --- a/pimd/pim_vty.c +++ b/pimd/pim_vty.c @@ -171,7 +171,7 @@ int pim_global_config_write_worker(struct pim_instance *pim, struct vty *vty) struct pim_ssm *ssm = pim->ssm_info; char spaces[10]; - if (pim->vrf_id == VRF_DEFAULT) + if (pim->vrf->vrf_id == VRF_DEFAULT) snprintf(spaces, sizeof(spaces), "%s", ""); else snprintf(spaces, sizeof(spaces), "%s", " "); @@ -186,7 +186,7 @@ int pim_global_config_write_worker(struct pim_instance *pim, struct vty *vty) writes += pim_rp_config_write(pim, vty, spaces); - if (pim->vrf_id == VRF_DEFAULT) { + if (pim->vrf->vrf_id == VRF_DEFAULT) { if (router->register_suppress_time != PIM_REGISTER_SUPPRESSION_TIME_DEFAULT) { vty_out(vty, "%sip pim register-suppress-time %d\n", diff --git a/pimd/pim_vxlan.c b/pimd/pim_vxlan.c index 6a12c7fb13..5d5ea1bfe6 100644 --- a/pimd/pim_vxlan.c +++ b/pimd/pim_vxlan.c @@ -1076,7 +1076,7 @@ void pim_vxlan_add_vif(struct interface *ifp) struct pim_interface *pim_ifp = ifp->info; struct pim_instance *pim = pim_ifp->pim; - if (pim->vrf_id != VRF_DEFAULT) + if (pim->vrf->vrf_id != VRF_DEFAULT) return; if (if_is_loopback_or_vrf(ifp)) @@ -1095,7 +1095,7 @@ void pim_vxlan_del_vif(struct interface *ifp) struct pim_interface *pim_ifp = ifp->info; struct pim_instance *pim = pim_ifp->pim; - if (pim->vrf_id != VRF_DEFAULT) + if (pim->vrf->vrf_id != VRF_DEFAULT) return; if (pim->vxlan.default_iif == ifp) diff --git a/pimd/pim_zlookup.c b/pimd/pim_zlookup.c index 72505a6993..9ccf1fedd4 100644 --- a/pimd/pim_zlookup.c +++ b/pimd/pim_zlookup.c @@ -544,7 +544,8 @@ int pim_zlookup_sg_statistics(struct channel_oil *c_oil) return -1; stream_reset(s); - zclient_create_header(s, ZEBRA_IPMR_ROUTE_STATS, c_oil->pim->vrf_id); + zclient_create_header(s, ZEBRA_IPMR_ROUTE_STATS, + c_oil->pim->vrf->vrf_id); stream_put_in_addr(s, &c_oil->oil.mfcc_origin); stream_put_in_addr(s, &c_oil->oil.mfcc_mcastgrp); stream_putl(s, ifp->ifindex); diff --git a/tests/isisd/test_isis_spf.c b/tests/isisd/test_isis_spf.c index 915f849aec..b89a5a008e 100644 --- a/tests/isisd/test_isis_spf.c +++ b/tests/isisd/test_isis_spf.c @@ -51,8 +51,6 @@ enum test_type { #define F_LEVEL1_ONLY 0x08 #define F_LEVEL2_ONLY 0x10 -static struct isis *isis; - static void test_run_spf(struct vty *vty, const struct isis_topology *topology, const struct isis_test_node *root, struct isis_area *area, struct lspdb_head *lspdb, @@ -257,8 +255,8 @@ static int test_run(struct vty *vty, const struct isis_topology *topology, uint8_t fail_id[ISIS_SYS_ID_LEN] = {}; /* Init topology. */ - memcpy(isis->sysid, root->sysid, sizeof(isis->sysid)); area = isis_area_create("1", NULL); + memcpy(area->isis->sysid, root->sysid, sizeof(area->isis->sysid)); area->is_type = IS_LEVEL_1_AND_2; area->srdb.enabled = true; if (test_topology_load(topology, area, area->lspdb) != 0) { @@ -470,7 +468,6 @@ static void vty_do_exit(int isexit) { printf("\nend.\n"); - isis_finish(isis); cmd_terminate(); vty_terminate(); yang_terminate(); @@ -555,7 +552,6 @@ int main(int argc, char **argv) /* IS-IS inits. */ yang_module_load("frr-isisd"); - isis = isis_new(VRF_DEFAULT_NAME); SET_FLAG(im->options, F_ISIS_UNIT_TEST); debug_spf_events |= DEBUG_SPF_EVENTS; debug_lfa |= DEBUG_LFA; diff --git a/tests/topotests/isis_topo1_vrf/r1/r1_route.json b/tests/topotests/isis_topo1_vrf/r1/r1_route.json index f0a3593a4c..8359baadaf 100644 --- a/tests/topotests/isis_topo1_vrf/r1/r1_route.json +++ b/tests/topotests/isis_topo1_vrf/r1/r1_route.json @@ -2,7 +2,7 @@ "10.0.10.0/24": [ { "distance": 115, - "metric": 20, + "metric": 10, "nexthops": [ { "active": true, diff --git a/tests/topotests/isis_topo1_vrf/r1/r1_route6.json b/tests/topotests/isis_topo1_vrf/r1/r1_route6.json index 888b9e2c42..74961262b4 100644 --- a/tests/topotests/isis_topo1_vrf/r1/r1_route6.json +++ b/tests/topotests/isis_topo1_vrf/r1/r1_route6.json @@ -18,7 +18,7 @@ "2001:db8:2:1::/64": [ { "distance": 115, - "metric": 20, + "metric": 10, "nexthops": [ { "active": true, diff --git a/tests/topotests/isis_topo1_vrf/r1/r1_topology.json b/tests/topotests/isis_topo1_vrf/r1/r1_topology.json index 1a6fe6d5c6..666fa52b19 100644 --- a/tests/topotests/isis_topo1_vrf/r1/r1_topology.json +++ b/tests/topotests/isis_topo1_vrf/r1/r1_topology.json @@ -33,7 +33,7 @@ }, { "interface": "r1-eth0", - "metric": "20", + "metric": "10", "next-hop": "r3", "parent": "r3(4)", "type": "IP TE", @@ -41,7 +41,7 @@ }, { "interface": "r1-eth0", - "metric": "20", + "metric": "10", "next-hop": "r3", "parent": "r3(4)", "type": "IP TE", @@ -67,8 +67,8 @@ "vertex": "r3" }, { + "metric": "10", "interface": "r1-eth0", - "metric": "20", "next-hop": "r3", "parent": "r3(4)", "type": "IP6 internal", diff --git a/tests/topotests/isis_topo1_vrf/r2/r2_route.json b/tests/topotests/isis_topo1_vrf/r2/r2_route.json index a26cdfad8e..e2eee112b3 100644 --- a/tests/topotests/isis_topo1_vrf/r2/r2_route.json +++ b/tests/topotests/isis_topo1_vrf/r2/r2_route.json @@ -2,7 +2,7 @@ "10.0.11.0/24": [ { "distance": 115, - "metric": 20, + "metric": 10, "nexthops": [ { "active": true, diff --git a/tests/topotests/isis_topo1_vrf/r2/r2_route6.json b/tests/topotests/isis_topo1_vrf/r2/r2_route6.json index b01789b8d9..21b953d0f7 100644 --- a/tests/topotests/isis_topo1_vrf/r2/r2_route6.json +++ b/tests/topotests/isis_topo1_vrf/r2/r2_route6.json @@ -18,7 +18,7 @@ "2001:db8:2:2::/64": [ { "distance": 115, - "metric": 20, + "metric": 10, "nexthops": [ { "active": true, diff --git a/tests/topotests/isis_topo1_vrf/r2/r2_topology.json b/tests/topotests/isis_topo1_vrf/r2/r2_topology.json index a77f7977f9..c26ad1ee37 100644 --- a/tests/topotests/isis_topo1_vrf/r2/r2_topology.json +++ b/tests/topotests/isis_topo1_vrf/r2/r2_topology.json @@ -33,7 +33,7 @@ }, { "interface": "r2-eth0", - "metric": "20", + "metric": "10", "next-hop": "r4", "parent": "r4(4)", "type": "IP TE", @@ -41,7 +41,7 @@ }, { "interface": "r2-eth0", - "metric": "20", + "metric": "10", "next-hop": "r4", "parent": "r4(4)", "type": "IP TE", @@ -67,8 +67,8 @@ "vertex": "r4" }, { + "metric": "10", "interface": "r2-eth0", - "metric": "20", "next-hop": "r4", "parent": "r4(4)", "type": "IP6 internal", diff --git a/tests/topotests/isis_topo1_vrf/r3/r3_route.json b/tests/topotests/isis_topo1_vrf/r3/r3_route.json index 9717df5c1a..33ad90cda1 100644 --- a/tests/topotests/isis_topo1_vrf/r3/r3_route.json +++ b/tests/topotests/isis_topo1_vrf/r3/r3_route.json @@ -2,7 +2,7 @@ "10.0.10.0/24": [ { "distance": 115, - "metric": 20, + "metric": 10, "nexthops": [ { "afi": "ipv4", @@ -32,7 +32,7 @@ "10.0.11.0/24": [ { "distance": 115, - "metric": 20, + "metric": 10, "nexthops": [ { "active": true, @@ -67,7 +67,7 @@ "10.0.21.0/24": [ { "distance": 115, - "metric": 30, + "metric": 20, "nexthops": [ { "active": true, diff --git a/tests/topotests/isis_topo1_vrf/r3/r3_route6.json b/tests/topotests/isis_topo1_vrf/r3/r3_route6.json index 31a1e4620f..519fe4968a 100644 --- a/tests/topotests/isis_topo1_vrf/r3/r3_route6.json +++ b/tests/topotests/isis_topo1_vrf/r3/r3_route6.json @@ -18,7 +18,7 @@ "2001:db8:1:2::/64": [ { "distance": 115, - "metric": 30, + "metric": 20, "nexthops": [ { "active": true, @@ -52,7 +52,7 @@ "2001:db8:2:2::/64": [ { "distance": 115, - "metric": 20, + "metric": 10, "nexthops": [ { "active": true, diff --git a/tests/topotests/isis_topo1_vrf/r3/r3_topology.json b/tests/topotests/isis_topo1_vrf/r3/r3_topology.json index 1e5d331965..34892d4a3a 100644 --- a/tests/topotests/isis_topo1_vrf/r3/r3_topology.json +++ b/tests/topotests/isis_topo1_vrf/r3/r3_topology.json @@ -21,7 +21,7 @@ }, { "interface": "r3-eth1", - "metric": "20", + "metric": "10", "next-hop": "r5", "parent": "r5(4)", "type": "IP TE", @@ -29,7 +29,7 @@ }, { "interface": "r3-eth1", - "metric": "20", + "metric": "10", "next-hop": "r5", "parent": "r5(4)", "type": "IP TE", @@ -37,7 +37,7 @@ }, { "interface": "r3-eth1", - "metric": "30", + "metric": "20", "next-hop": "r5", "parent": "r4(4)", "type": "IP TE", @@ -63,16 +63,16 @@ "vertex": "r5" }, { + "metric": "10", "interface": "r3-eth1", - "metric": "20", "next-hop": "r5", "parent": "r5(4)", "type": "IP6 internal", "vertex": "2001:db8:2:2::/64" }, { + "metric": "20", "interface": "r3-eth1", - "metric": "30", "next-hop": "r5", "parent": "r4(4)", "type": "IP6 internal", @@ -101,7 +101,7 @@ }, { "interface": "r3-eth0", - "metric": "20", + "metric": "10", "next-hop": "r3", "parent": "r3(4)", "type": "IP TE", diff --git a/tests/topotests/isis_topo1_vrf/r4/r4_route.json b/tests/topotests/isis_topo1_vrf/r4/r4_route.json index 6cb79b0301..6fb3bd99d1 100644 --- a/tests/topotests/isis_topo1_vrf/r4/r4_route.json +++ b/tests/topotests/isis_topo1_vrf/r4/r4_route.json @@ -1,7 +1,7 @@ { "10.0.10.0/24": [ { - "metric": 20, + "metric": 10, "nexthops": [ { "active": true, diff --git a/tests/topotests/isis_topo1_vrf/r4/r4_route6.json b/tests/topotests/isis_topo1_vrf/r4/r4_route6.json index 88a91749c2..702a83fb72 100644 --- a/tests/topotests/isis_topo1_vrf/r4/r4_route6.json +++ b/tests/topotests/isis_topo1_vrf/r4/r4_route6.json @@ -2,7 +2,7 @@ "2001:db8:1:1::/64": [ { "distance": 115, - "metric": 30, + "metric": 20, "nexthops": [ { "active": true, @@ -36,7 +36,7 @@ "2001:db8:2:1::/64": [ { "distance": 115, - "metric": 20, + "metric": 10, "nexthops": [ { "active": true, diff --git a/tests/topotests/isis_topo1_vrf/r4/r4_topology.json b/tests/topotests/isis_topo1_vrf/r4/r4_topology.json index 34f5ac9ca4..d40008aa30 100644 --- a/tests/topotests/isis_topo1_vrf/r4/r4_topology.json +++ b/tests/topotests/isis_topo1_vrf/r4/r4_topology.json @@ -21,7 +21,7 @@ }, { "interface": "r4-eth1", - "metric": "20", + "metric": "10", "next-hop": "r5", "parent": "r5(4)", "type": "IP TE", @@ -29,7 +29,7 @@ }, { "interface": "r4-eth1", - "metric": "20", + "metric": "10", "next-hop": "r5", "parent": "r5(4)", "type": "IP TE", @@ -37,7 +37,7 @@ }, { "interface": "r4-eth1", - "metric": "30", + "metric": "20", "next-hop": "r5", "parent": "r3(4)", "type": "IP TE", @@ -63,16 +63,16 @@ "vertex": "r5" }, { + "metric": "10", "interface": "r4-eth1", - "metric": "20", "next-hop": "r5", "parent": "r5(4)", "type": "IP6 internal", "vertex": "2001:db8:2:1::/64" }, { + "metric": "20", "interface": "r4-eth1", - "metric": "30", "next-hop": "r5", "parent": "r3(4)", "type": "IP6 internal", @@ -101,7 +101,7 @@ }, { "interface": "r4-eth0", - "metric": "20", + "metric": "10", "next-hop": "r2", "parent": "r2(4)", "type": "IP TE", diff --git a/tests/topotests/isis_topo1_vrf/r5/r5_route.json b/tests/topotests/isis_topo1_vrf/r5/r5_route.json index 5efa36bce6..a254b6fdd5 100644 --- a/tests/topotests/isis_topo1_vrf/r5/r5_route.json +++ b/tests/topotests/isis_topo1_vrf/r5/r5_route.json @@ -2,7 +2,7 @@ "10.0.10.0/24": [ { "distance": 115, - "metric": 20, + "metric": 10, "nexthops": [ { "afi": "ipv4", diff --git a/tests/topotests/isis_topo1_vrf/r5/r5_route6.json b/tests/topotests/isis_topo1_vrf/r5/r5_route6.json index 5e8f6364af..06fc78f703 100644 --- a/tests/topotests/isis_topo1_vrf/r5/r5_route6.json +++ b/tests/topotests/isis_topo1_vrf/r5/r5_route6.json @@ -2,7 +2,7 @@ "2001:db8:1:1::/64": [ { "distance": 115, - "metric": 20, + "metric": 10, "nexthops": [ { "active": true, @@ -20,7 +20,7 @@ "2001:db8:1:2::/64": [ { "distance": 115, - "metric": 20, + "metric": 10, "nexthops": [ { "active": true, diff --git a/tests/topotests/isis_topo1_vrf/r5/r5_topology.json b/tests/topotests/isis_topo1_vrf/r5/r5_topology.json index ace56536e9..2a088cae30 100644 --- a/tests/topotests/isis_topo1_vrf/r5/r5_topology.json +++ b/tests/topotests/isis_topo1_vrf/r5/r5_topology.json @@ -35,7 +35,7 @@ }, { "interface": "r5-eth0", - "metric": "20", + "metric": "10", "next-hop": "r3", "parent": "r3(4)", "type": "IP TE", @@ -43,7 +43,7 @@ }, { "interface": "r5-eth0", - "metric": "20", + "metric": "10", "next-hop": "r3", "parent": "r3(4)", "type": "IP TE", @@ -51,7 +51,7 @@ }, { "interface": "r5-eth1", - "metric": "20", + "metric": "10", "next-hop": "r4", "parent": "r4(4)", "type": "IP TE", @@ -59,7 +59,7 @@ }, { "interface": "r5-eth1", - "metric": "20", + "metric": "10", "next-hop": "r4", "parent": "r4(4)", "type": "IP TE", @@ -99,16 +99,16 @@ "vertex": "r4" }, { + "metric": "10", "interface": "r5-eth0", - "metric": "20", "next-hop": "r3", "parent": "r3(4)", "type": "IP6 internal", "vertex": "2001:db8:1:1::/64" }, { + "metric": "10", "interface": "r5-eth1", - "metric": "20", "next-hop": "r4", "parent": "r4(4)", "type": "IP6 internal", diff --git a/tests/topotests/multicast_pim_sm_topo2/test_multicast_pim_sm_topo2.py b/tests/topotests/multicast_pim_sm_topo2/test_multicast_pim_sm_topo2.py index 7e409c2a05..f1f130826f 100755 --- a/tests/topotests/multicast_pim_sm_topo2/test_multicast_pim_sm_topo2.py +++ b/tests/topotests/multicast_pim_sm_topo2/test_multicast_pim_sm_topo2.py @@ -1676,7 +1676,8 @@ def test_verify_mroute_when_5_different_receiver_joining_same_sources_p0(request source = topo["routers"]["i3"]["links"]["r2"]["ipv4"].split("/")[0] input_dict_all = [ - {"dut": "l1", "src_address": source, "iif": "l1-r2-eth4", "oil": "l1-i1-eth1"}, + {"dut": "l1", "src_address": source, "iif": ["l1-r2-eth4", "l1-c1-eth0"], + "oil": ["l1-i1-eth1", "l1-i6-eth2"]}, {"dut": "f1", "src_address": source, "iif": "f1-r2-eth3", "oil": "f1-i8-eth2"}, ] for data in input_dict_all: diff --git a/yang/frr-bgp-common-structure.yang b/yang/frr-bgp-common-structure.yang index 232c78899e..2ad22a1435 100644 --- a/yang/frr-bgp-common-structure.yang +++ b/yang/frr-bgp-common-structure.yang @@ -124,7 +124,7 @@ submodule frr-bgp-common-structure { set to 'false' it will prepend local-as to updates."; } - leaf no-replace-as { + leaf replace-as { type boolean; default "false"; description diff --git a/zebra/connected.c b/zebra/connected.c index 883334d509..d110ccf6dd 100644 --- a/zebra/connected.c +++ b/zebra/connected.c @@ -277,7 +277,7 @@ void connected_up(struct interface *ifp, struct connected *ifc) * resolve to the same network and mask */ for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) { - struct prefix cp; + struct prefix cp = {0}; PREFIX_COPY(&cp, CONNECTED_PREFIX(c)); apply_mask(&cp); |
