summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_nb.c12
-rw-r--r--bgpd/bgp_nb.h6
-rw-r--r--bgpd/bgp_nb_config.c27
-rw-r--r--bgpd/bgp_vty.c4
-rw-r--r--bgpd/bgp_zebra.c6
-rw-r--r--bgpd/bgpd.c2
-rw-r--r--doc/developer/grpc.rst282
-rw-r--r--doc/user/pathd.rst2
-rw-r--r--isisd/isis_main.c3
-rw-r--r--isisd/isis_nb_config.c2
-rw-r--r--isisd/isis_redist.c32
-rw-r--r--isisd/isis_redist.h2
-rw-r--r--isisd/isis_snmp.c93
-rw-r--r--isisd/isis_zebra.c24
-rw-r--r--isisd/isis_zebra.h5
-rw-r--r--isisd/isisd.c93
-rw-r--r--lib/northbound.c4
-rw-r--r--ospf6d/ospf6_asbr.c14
-rw-r--r--ospf6d/ospf6_top.c10
-rw-r--r--ospfd/ospf_api.c38
-rw-r--r--ospfd/ospf_api.h2
-rw-r--r--ospfd/ospf_apiserver.c14
-rw-r--r--ospfd/ospf_dump.c102
-rw-r--r--ospfd/ospf_ext.c83
-rw-r--r--ospfd/ospf_gr_helper.c16
-rw-r--r--ospfd/ospf_lsa.c9
-rw-r--r--ospfd/ospf_lsa.h7
-rw-r--r--ospfd/ospf_opaque.c3
-rw-r--r--ospfd/ospf_opaque.h1
-rw-r--r--ospfd/ospf_ri.c133
-rw-r--r--ospfd/ospf_ri.h19
-rw-r--r--ospfd/ospf_sr.c53
-rw-r--r--ospfd/ospf_sr.h4
-rw-r--r--ospfd/ospf_te.c167
-rw-r--r--ospfd/ospf_vty.c24
-rw-r--r--ospfd/ospfd.c10
-rw-r--r--pathd/path_cli.c16
-rw-r--r--pathd/path_pcep_pcc.c3
-rw-r--r--pathd/pathd.c6
-rw-r--r--pbrd/pbr_nht.c28
-rw-r--r--pimd/pim_bsm.c2
-rw-r--r--pimd/pim_cmd.c4
-rw-r--r--pimd/pim_iface.c16
-rw-r--r--pimd/pim_igmp_mtrace.c2
-rw-r--r--pimd/pim_instance.c12
-rw-r--r--pimd/pim_instance.h2
-rw-r--r--pimd/pim_mroute.c4
-rw-r--r--pimd/pim_msdp_socket.c10
-rw-r--r--pimd/pim_nb_config.c8
-rw-r--r--pimd/pim_nht.c19
-rw-r--r--pimd/pim_pim.c2
-rw-r--r--pimd/pim_rp.c4
-rw-r--r--pimd/pim_rpf.c2
-rw-r--r--pimd/pim_ssm.c2
-rw-r--r--pimd/pim_ssmpingd.c2
-rw-r--r--pimd/pim_vty.c4
-rw-r--r--pimd/pim_vxlan.c4
-rw-r--r--pimd/pim_zlookup.c3
-rw-r--r--tests/isisd/test_isis_spf.c6
-rw-r--r--tests/topotests/isis_topo1_vrf/r1/r1_route.json2
-rw-r--r--tests/topotests/isis_topo1_vrf/r1/r1_route6.json2
-rw-r--r--tests/topotests/isis_topo1_vrf/r1/r1_topology.json6
-rw-r--r--tests/topotests/isis_topo1_vrf/r2/r2_route.json2
-rw-r--r--tests/topotests/isis_topo1_vrf/r2/r2_route6.json2
-rw-r--r--tests/topotests/isis_topo1_vrf/r2/r2_topology.json6
-rw-r--r--tests/topotests/isis_topo1_vrf/r3/r3_route.json6
-rw-r--r--tests/topotests/isis_topo1_vrf/r3/r3_route6.json4
-rw-r--r--tests/topotests/isis_topo1_vrf/r3/r3_topology.json12
-rw-r--r--tests/topotests/isis_topo1_vrf/r4/r4_route.json2
-rw-r--r--tests/topotests/isis_topo1_vrf/r4/r4_route6.json4
-rw-r--r--tests/topotests/isis_topo1_vrf/r4/r4_topology.json12
-rw-r--r--tests/topotests/isis_topo1_vrf/r5/r5_route.json2
-rw-r--r--tests/topotests/isis_topo1_vrf/r5/r5_route6.json4
-rw-r--r--tests/topotests/isis_topo1_vrf/r5/r5_topology.json12
-rwxr-xr-xtests/topotests/multicast_pim_sm_topo2/test_multicast_pim_sm_topo2.py3
-rw-r--r--yang/frr-bgp-common-structure.yang2
-rw-r--r--zebra/connected.c2
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);