diff --git a/patches/vpp/0001-linux-cp-add-support-for-xfrm-netlink-notifcation.patch b/patches/vpp/0001-linux-cp-add-support-for-xfrm-netlink-notifcation.patch index 712901e..ed1a779 100644 --- a/patches/vpp/0001-linux-cp-add-support-for-xfrm-netlink-notifcation.patch +++ b/patches/vpp/0001-linux-cp-add-support-for-xfrm-netlink-notifcation.patch @@ -1,7 +1,7 @@ From a3ebed1641deca92e4eae2b32d34dbe5fc5e9f57 Mon Sep 17 00:00:00 2001 From: Aakash Date: Mon, 1 Aug 2022 04:59:02 -0400 -Subject: [PATCH 01/13] linux-cp: add support for xfrm netlink notifcation +Subject: [PATCH 01/17] linux-cp: add support for xfrm netlink notifcation This patch contains changes to add support for handlng xfrm notifications in linux-cp plugin. diff --git a/patches/vpp/0002-linux-cp-update-code-to-support-api-proto-changes.patch b/patches/vpp/0002-linux-cp-update-code-to-support-api-proto-changes.patch index bf690de..f7c0ce5 100644 --- a/patches/vpp/0002-linux-cp-update-code-to-support-api-proto-changes.patch +++ b/patches/vpp/0002-linux-cp-update-code-to-support-api-proto-changes.patch @@ -1,7 +1,7 @@ From b2bce6dc411175928d52e207d8890403af1f4792 Mon Sep 17 00:00:00 2001 From: Kommula Shiva Shankar Date: Tue, 6 Feb 2024 23:23:14 +0530 -Subject: [PATCH 02/13] linux-cp: update code to support api proto changes +Subject: [PATCH 02/17] linux-cp: update code to support api proto changes Type: fix diff --git a/patches/vpp/0003-linux-cp-add-ipsec-interface-support-for-xfrm.patch b/patches/vpp/0003-linux-cp-add-ipsec-interface-support-for-xfrm.patch index dba0557..2d553f3 100644 --- a/patches/vpp/0003-linux-cp-add-ipsec-interface-support-for-xfrm.patch +++ b/patches/vpp/0003-linux-cp-add-ipsec-interface-support-for-xfrm.patch @@ -1,7 +1,7 @@ From 2a1f214e452225b78150a0fa8fa0938a9d55e118 Mon Sep 17 00:00:00 2001 From: Bheemappa Agasimundin Date: Tue, 5 Dec 2023 18:25:33 +0000 -Subject: [PATCH 03/13] linux-cp: add ipsec interface support for xfrm +Subject: [PATCH 03/17] linux-cp: add ipsec interface support for xfrm This patch adds ipsec interface support for strongswan based SA configuration. diff --git a/patches/vpp/0004-linux-cp-initialize-sw_if_index-variable.patch b/patches/vpp/0004-linux-cp-initialize-sw_if_index-variable.patch index d4c6939..3defb70 100644 --- a/patches/vpp/0004-linux-cp-initialize-sw_if_index-variable.patch +++ b/patches/vpp/0004-linux-cp-initialize-sw_if_index-variable.patch @@ -1,7 +1,7 @@ From 8ffe977acdba505759bd6645871ab976c7fbce87 Mon Sep 17 00:00:00 2001 From: Kommula Shiva Shankar Date: Wed, 7 Feb 2024 11:58:17 +0530 -Subject: [PATCH 04/13] linux-cp: initialize sw_if_index variable +Subject: [PATCH 04/17] linux-cp: initialize sw_if_index variable Type: fix diff --git a/patches/vpp/0005-linux-cp-add-readme-for-xfrm-implementation.patch b/patches/vpp/0005-linux-cp-add-readme-for-xfrm-implementation.patch index 1196088..7f1bd71 100644 --- a/patches/vpp/0005-linux-cp-add-readme-for-xfrm-implementation.patch +++ b/patches/vpp/0005-linux-cp-add-readme-for-xfrm-implementation.patch @@ -1,7 +1,7 @@ From 57f0bafafe203da5f7fa04efbc2e850e391f3589 Mon Sep 17 00:00:00 2001 From: Bheemappa Agasimundin Date: Sun, 24 Mar 2024 08:36:48 +0000 -Subject: [PATCH 05/13] linux-cp: add readme for xfrm implementation +Subject: [PATCH 05/17] linux-cp: add readme for xfrm implementation This patch adds REAMDE for XFRM changes design and startup.conf configuration details. diff --git a/patches/vpp/0006-linux-cp-fix-esn-and-anti-replay-issue.patch b/patches/vpp/0006-linux-cp-fix-esn-and-anti-replay-issue.patch index 24820fd..9b1105f 100644 --- a/patches/vpp/0006-linux-cp-fix-esn-and-anti-replay-issue.patch +++ b/patches/vpp/0006-linux-cp-fix-esn-and-anti-replay-issue.patch @@ -1,7 +1,7 @@ From 3aee268143607b829b9e006ff3d72dfb67bd919b Mon Sep 17 00:00:00 2001 From: Bheemappa Agasimundin Date: Tue, 27 Aug 2024 17:29:30 +0000 -Subject: [PATCH 06/13] linux-cp: fix esn and anti-replay issue +Subject: [PATCH 06/17] linux-cp: fix esn and anti-replay issue This patch enables anti-replay when ESN is enabled on a Security Association (SA) configured via strongSwan. diff --git a/patches/vpp/0007-linux-cp-fix-ipsec-policy-incorrect-protocol-type.patch b/patches/vpp/0007-linux-cp-fix-ipsec-policy-incorrect-protocol-type.patch index d47054f..6fba7e4 100644 --- a/patches/vpp/0007-linux-cp-fix-ipsec-policy-incorrect-protocol-type.patch +++ b/patches/vpp/0007-linux-cp-fix-ipsec-policy-incorrect-protocol-type.patch @@ -1,7 +1,7 @@ From 48d57e9543244fb29b8e9bdce4d5775950332e9d Mon Sep 17 00:00:00 2001 From: Bheemappa Agasimundin Date: Tue, 1 Oct 2024 15:06:41 +0000 -Subject: [PATCH 07/13] linux-cp: fix ipsec policy incorrect protocol type +Subject: [PATCH 07/17] linux-cp: fix ipsec policy incorrect protocol type This patch changes protocol type 0 to IPSEC_POLICY_PROTOCOL_ANY to allow any transport protocol for protect/bypass. diff --git a/patches/vpp/0008-linux-cp-Added-build-dependency-for-XFRM.patch b/patches/vpp/0008-linux-cp-Added-build-dependency-for-XFRM.patch index 9edf824..7ec298f 100644 --- a/patches/vpp/0008-linux-cp-Added-build-dependency-for-XFRM.patch +++ b/patches/vpp/0008-linux-cp-Added-build-dependency-for-XFRM.patch @@ -1,7 +1,7 @@ From 28a3d6f27e0237f07d71a305191a814e07550128 Mon Sep 17 00:00:00 2001 From: zdc Date: Wed, 12 Feb 2025 12:29:57 +0200 -Subject: [PATCH 08/13] linux-cp: Added build dependency for XFRM +Subject: [PATCH 08/17] linux-cp: Added build dependency for XFRM Added `libnl-xfrm-3-200` to build dependencies to make build `linux-cp` with XFRM possible. diff --git a/patches/vpp/0009-linux-cp-Added-routing-for-prefixes-with-no-paths-av.patch b/patches/vpp/0009-linux-cp-Added-routing-for-prefixes-with-no-paths-av.patch index 11c8ced..5eacb23 100644 --- a/patches/vpp/0009-linux-cp-Added-routing-for-prefixes-with-no-paths-av.patch +++ b/patches/vpp/0009-linux-cp-Added-routing-for-prefixes-with-no-paths-av.patch @@ -1,7 +1,7 @@ From c784244ca4092210ea74fcff1ec7c1a7d633e2ff Mon Sep 17 00:00:00 2001 From: zsdc Date: Tue, 23 Jul 2024 20:06:41 +0300 -Subject: [PATCH 09/13] linux-cp: Added routing for prefixes with no paths +Subject: [PATCH 09/17] linux-cp: Added routing for prefixes with no paths available A new CLI and configuration file option is available: diff --git a/patches/vpp/0010-Resync-ip-fib-with-Linux-state.patch b/patches/vpp/0010-Resync-ip-fib-with-Linux-state.patch index f584e2e..5bbccb0 100644 --- a/patches/vpp/0010-Resync-ip-fib-with-Linux-state.patch +++ b/patches/vpp/0010-Resync-ip-fib-with-Linux-state.patch @@ -1,7 +1,7 @@ From d66645af550b6916e11f3923c1fbaf511094e1b8 Mon Sep 17 00:00:00 2001 From: Denys Haryachyy Date: Wed, 24 Jul 2024 08:35:25 +0000 -Subject: [PATCH 10/13] Resync ip fib with Linux state. +Subject: [PATCH 10/17] Resync ip fib with Linux state. A new CLI and API file option is available: diff --git a/patches/vpp/0011-LCP-Improved-lcp-resync-CLI-and-API-to-wait-until-Ne.patch b/patches/vpp/0011-LCP-Improved-lcp-resync-CLI-and-API-to-wait-until-Ne.patch index a57399e..6ca00e3 100644 --- a/patches/vpp/0011-LCP-Improved-lcp-resync-CLI-and-API-to-wait-until-Ne.patch +++ b/patches/vpp/0011-LCP-Improved-lcp-resync-CLI-and-API-to-wait-until-Ne.patch @@ -1,7 +1,7 @@ From 9653065d5de59ab76e10f67117896f7ed6478585 Mon Sep 17 00:00:00 2001 From: Denys Haryachyy Date: Wed, 29 Jan 2025 11:57:01 +0200 -Subject: [PATCH 11/13] LCP: Improved lcp resync CLI and API to wait until +Subject: [PATCH 11/17] LCP: Improved lcp resync CLI and API to wait until Netlink sync is finished. (cherry picked from commit b19375e7e42023a5cdca84f259036574ccd9da77) diff --git a/patches/vpp/0012-build-Fixed-compatibility-with-build-on-Debian-12.patch b/patches/vpp/0012-build-Fixed-compatibility-with-build-on-Debian-12.patch index 70fd0b2..49c6b1b 100644 --- a/patches/vpp/0012-build-Fixed-compatibility-with-build-on-Debian-12.patch +++ b/patches/vpp/0012-build-Fixed-compatibility-with-build-on-Debian-12.patch @@ -1,7 +1,7 @@ From e34ad0e3b7ae9f4e630687e39278e5dd43a43c31 Mon Sep 17 00:00:00 2001 From: zdc Date: Tue, 11 Feb 2025 20:33:46 +0200 -Subject: [PATCH 12/13] build: Fixed compatibility with build on Debian 12 +Subject: [PATCH 12/17] build: Fixed compatibility with build on Debian 12 (cherry picked from commit ca7d5bcd381edb68e9d4ae6ffa915bda4d2c1adf) --- diff --git a/patches/vpp/0013-linux-cp-Added-build-dependency-libunwind8-for-XFRM.patch b/patches/vpp/0013-linux-cp-Added-build-dependency-libunwind8-for-XFRM.patch index 1bcf3ea..7a2e5e0 100644 --- a/patches/vpp/0013-linux-cp-Added-build-dependency-libunwind8-for-XFRM.patch +++ b/patches/vpp/0013-linux-cp-Added-build-dependency-libunwind8-for-XFRM.patch @@ -1,7 +1,7 @@ From 44830bdae2c4cefe94dd3c8ceee471b7dadeef8b Mon Sep 17 00:00:00 2001 From: Viacheslav Hletenko Date: Thu, 13 Feb 2025 11:37:36 +0000 -Subject: [PATCH 13/13] linux-cp: Added build dependency libunwind8 for XFRM +Subject: [PATCH 13/17] linux-cp: Added build dependency libunwind8 for XFRM Added `libunwind8` to build dependencies required by `linux-cp` for XFRM diff --git a/patches/vpp/0014-Revert-linux-cp-Added-routing-for-prefixes-with-no-p.patch b/patches/vpp/0014-Revert-linux-cp-Added-routing-for-prefixes-with-no-p.patch new file mode 100644 index 0000000..6417c41 --- /dev/null +++ b/patches/vpp/0014-Revert-linux-cp-Added-routing-for-prefixes-with-no-p.patch @@ -0,0 +1,170 @@ +From 0696c16075caa700a0c9313400c67582da42de99 Mon Sep 17 00:00:00 2001 +From: Denys Haryachyy +Date: Thu, 6 Mar 2025 16:27:51 +0200 +Subject: [PATCH 14/17] Revert "linux-cp: Added routing for prefixes with no + paths available" + +This reverts commit c784244ca4092210ea74fcff1ec7c1a7d633e2ff. +--- + src/plugins/linux-cp/lcp.c | 16 ---------------- + src/plugins/linux-cp/lcp.h | 7 ------- + src/plugins/linux-cp/lcp_cli.c | 14 +------------- + src/plugins/linux-cp/lcp_interface.c | 4 ---- + src/plugins/linux-cp/lcp_router.c | 21 ++++----------------- + 5 files changed, 5 insertions(+), 57 deletions(-) + +diff --git a/src/plugins/linux-cp/lcp.c b/src/plugins/linux-cp/lcp.c +index 6e8c38b8c..34e8550a1 100644 +--- a/src/plugins/linux-cp/lcp.c ++++ b/src/plugins/linux-cp/lcp.c +@@ -183,22 +183,6 @@ lcp_get_default_num_queues (u8 is_tx) + return lcpm->num_rx_queues ?: vlib_num_workers (); + } + +-void +-lcp_set_route_no_paths (u8 is_del) +-{ +- lcp_main_t *lcpm = &lcp_main; +- +- lcpm->route_no_paths = (is_del != 0); +-} +- +-u8 +-lcp_get_route_no_paths (void) +-{ +- lcp_main_t *lcpm = &lcp_main; +- +- return lcpm->route_no_paths; +-} +- + /* + * fd.io coding-style-patch-verification: ON + * +diff --git a/src/plugins/linux-cp/lcp.h b/src/plugins/linux-cp/lcp.h +index 5349bb492..e89b149f6 100644 +--- a/src/plugins/linux-cp/lcp.h ++++ b/src/plugins/linux-cp/lcp.h +@@ -33,7 +33,6 @@ typedef struct lcp_main_s + u8 test_mode; /* Set when Unit testing */ + u8 netlink_processing_active; /* Set while a batch of Netlink messages are + being processed */ +- u8 route_no_paths; /* Add routes with no paths as local */ + } lcp_main_t; + + extern lcp_main_t lcp_main; +@@ -70,12 +69,6 @@ u8 lcp_get_netlink_processing_active (void); + void lcp_set_default_num_queues (u16 num_queues, u8 is_tx); + u16 lcp_get_default_num_queues (u8 is_tx); + +-/** +- * Get/Set whether to install routes with no paths as local +- */ +-void lcp_set_route_no_paths (u8 is_del); +-u8 lcp_get_route_no_paths (void); +- + #endif + + /* +diff --git a/src/plugins/linux-cp/lcp_cli.c b/src/plugins/linux-cp/lcp_cli.c +index c7f0658ee..0dcf600b3 100644 +--- a/src/plugins/linux-cp/lcp_cli.c ++++ b/src/plugins/linux-cp/lcp_cli.c +@@ -192,17 +192,6 @@ lcp_param_command_fn (vlib_main_t *vm, unformat_input_t *input, + return clib_error_return (0, "unknown input `%U'", + format_unformat_error, line_input); + } +- else if (unformat (line_input, "route-no-paths")) +- { +- if (unformat (line_input, "on") || unformat (line_input, "enable")) +- lcp_set_route_no_paths (1 /* is_del */); +- else if (unformat (line_input, "off") || +- unformat (line_input, "disable")) +- lcp_set_route_no_paths (0 /* is_del */); +- else +- return clib_error_return (0, "unknown input `%U'", +- format_unformat_error, line_input); +- } + else + return clib_error_return (0, "unknown input `%U'", + format_unformat_error, line_input); +@@ -215,8 +204,7 @@ lcp_param_command_fn (vlib_main_t *vm, unformat_input_t *input, + VLIB_CLI_COMMAND (lcp_param_command, static) = { + .path = "lcp param", + .short_help = "lcp param [del-static-on-link-down (on|enable|off|disable)] " +- "[del-dynamic-on-link-down (on|enable|off|disable)] " +- "[route-no-paths (on|enable|off|disable)]", ++ "[del-dynamic-on-link-down (on|enable|off|disable)]", + .function = lcp_param_command_fn, + }; + +diff --git a/src/plugins/linux-cp/lcp_interface.c b/src/plugins/linux-cp/lcp_interface.c +index 6f2b2e5c9..61665ad41 100644 +--- a/src/plugins/linux-cp/lcp_interface.c ++++ b/src/plugins/linux-cp/lcp_interface.c +@@ -138,8 +138,6 @@ lcp_itf_pair_show (u32 phy_sw_if_index) + lcp_get_del_static_on_link_down () ? "on" : "off"); + vlib_cli_output (vm, "lcp del-dynamic-on-link-down %s\n", + lcp_get_del_dynamic_on_link_down () ? "on" : "off"); +- vlib_cli_output (vm, "lcp route-no-paths %s\n", +- lcp_get_route_no_paths () ? "on" : "off"); + + if (phy_sw_if_index == ~0) + { +@@ -590,8 +588,6 @@ lcp_itf_pair_config (vlib_main_t *vm, unformat_input_t *input) + lcp_set_default_num_queues (tmp, 0 /* is_tx */); + else if (unformat (input, "num-tx-queues %d", &tmp)) + lcp_set_default_num_queues (tmp, 1 /* is_tx */); +- else if (unformat (input, "route-no-paths")) +- lcp_set_route_no_paths (1 /* is_del */); + else + return clib_error_return (0, "interfaces not found"); + } +diff --git a/src/plugins/linux-cp/lcp_router.c b/src/plugins/linux-cp/lcp_router.c +index 0879d00bc..0efd53e64 100644 +--- a/src/plugins/linux-cp/lcp_router.c ++++ b/src/plugins/linux-cp/lcp_router.c +@@ -1167,7 +1167,7 @@ lcp_router_route_path_add_special (struct rtnl_route *rr, + { + fib_route_path_t *path; + +- if (rtnl_route_get_type (rr) < RTN_BLACKHOLE && !(lcp_get_route_no_paths ())) ++ if (rtnl_route_get_type (rr) < RTN_BLACKHOLE) + return; + + /* if it already has a path, it does not need us to add one */ +@@ -1176,21 +1176,8 @@ lcp_router_route_path_add_special (struct rtnl_route *rr, + + vec_add2 (ctx->paths, path, 1); + +- /* If there are no paths, and `lcp param route-no-paths` is enabled +- * we need to add an extra local path. This allows punting traffic +- * with destinations available only via kernel */ +- if (lcp_get_route_no_paths ()) +- { +- path->frp_flags = FIB_ROUTE_PATH_LOCAL | ctx->type_flags; +- } else { +- path->frp_flags = FIB_ROUTE_PATH_FLAG_NONE | ctx->type_flags; +- } +- +- /* Do not add interface to routes from kernel */ +- if (rtnl_route_get_protocol (rr) != RTPROT_KERNEL) { +- path->frp_sw_if_index = ~0; +- } +- ++ path->frp_flags = FIB_ROUTE_PATH_FLAG_NONE | ctx->type_flags; ++ path->frp_sw_if_index = ~0; + path->frp_proto = fib_proto_to_dpo (ctx->route_proto); + path->frp_preference = ctx->preference; + +@@ -1348,7 +1335,7 @@ lcp_router_route_add (struct rtnl_route *rr, int is_replace) + + nlt = lcp_router_table_add_or_lock (table_id, pfx.fp_proto); + /* Skip any kernel routes and IPv6 LL or multicast routes */ +- if ((rproto == RTPROT_KERNEL && !(lcp_get_route_no_paths ())) || ++ if (rproto == RTPROT_KERNEL || + (FIB_PROTOCOL_IP6 == pfx.fp_proto && + (ip6_address_is_multicast (&pfx.fp_addr.ip6) || + ip6_address_is_link_local_unicast (&pfx.fp_addr.ip6)))) +-- +2.39.5 + diff --git a/patches/vpp/0015-linux-cp-Added-routing-for-prefixes-with-no-paths-av.patch b/patches/vpp/0015-linux-cp-Added-routing-for-prefixes-with-no-paths-av.patch new file mode 100644 index 0000000..4bdc606 --- /dev/null +++ b/patches/vpp/0015-linux-cp-Added-routing-for-prefixes-with-no-paths-av.patch @@ -0,0 +1,284 @@ +From 5583626fe1a9d11cffb8f759c996e341b7e54a7b Mon Sep 17 00:00:00 2001 +From: zsdc +Date: Tue, 23 Jul 2024 20:06:41 +0300 +Subject: [PATCH 15/17] linux-cp: Added routing for prefixes with no paths + available + +A new CLI and configuration file option is available: + +``` +lcp param route-no-paths (on|enable|off|disable) +``` + +``` +linux-cp { + route-no-paths +} +``` + +If it is enabled, routes with no paths in VPP will be installed as local. +This allows punting traffic with destinations available only via a kernel +routing table, but not via VPP. + +(cherry picked from commit 35bf59ac3fc96f1af7591dafa1fae642a34558e5) + +linux-cp: Added routing for prefixes with no paths available + +A new CLI and configuration file option is available: + +``` +lcp param route-no-paths (on|enable|off|disable) +``` + +``` +linux-cp { + route-no-paths +} +``` + +If it is enabled, routes with no paths in VPP will be installed as local. +This allows punting traffic with destinations available only via a kernel +routing table, but not via VPP. + +(cherry picked from commit 35bf59ac3fc96f1af7591dafa1fae642a34558e5) +--- + src/plugins/linux-cp/lcp.c | 16 ++++++ + src/plugins/linux-cp/lcp.h | 7 +++ + src/plugins/linux-cp/lcp_cli.c | 14 ++++- + src/plugins/linux-cp/lcp_interface.c | 4 ++ + src/plugins/linux-cp/lcp_router.c | 78 +++++++++++++++++++++++++--- + 5 files changed, 112 insertions(+), 7 deletions(-) + +diff --git a/src/plugins/linux-cp/lcp.c b/src/plugins/linux-cp/lcp.c +index 34e8550a1..6e8c38b8c 100644 +--- a/src/plugins/linux-cp/lcp.c ++++ b/src/plugins/linux-cp/lcp.c +@@ -183,6 +183,22 @@ lcp_get_default_num_queues (u8 is_tx) + return lcpm->num_rx_queues ?: vlib_num_workers (); + } + ++void ++lcp_set_route_no_paths (u8 is_del) ++{ ++ lcp_main_t *lcpm = &lcp_main; ++ ++ lcpm->route_no_paths = (is_del != 0); ++} ++ ++u8 ++lcp_get_route_no_paths (void) ++{ ++ lcp_main_t *lcpm = &lcp_main; ++ ++ return lcpm->route_no_paths; ++} ++ + /* + * fd.io coding-style-patch-verification: ON + * +diff --git a/src/plugins/linux-cp/lcp.h b/src/plugins/linux-cp/lcp.h +index e89b149f6..5349bb492 100644 +--- a/src/plugins/linux-cp/lcp.h ++++ b/src/plugins/linux-cp/lcp.h +@@ -33,6 +33,7 @@ typedef struct lcp_main_s + u8 test_mode; /* Set when Unit testing */ + u8 netlink_processing_active; /* Set while a batch of Netlink messages are + being processed */ ++ u8 route_no_paths; /* Add routes with no paths as local */ + } lcp_main_t; + + extern lcp_main_t lcp_main; +@@ -69,6 +70,12 @@ u8 lcp_get_netlink_processing_active (void); + void lcp_set_default_num_queues (u16 num_queues, u8 is_tx); + u16 lcp_get_default_num_queues (u8 is_tx); + ++/** ++ * Get/Set whether to install routes with no paths as local ++ */ ++void lcp_set_route_no_paths (u8 is_del); ++u8 lcp_get_route_no_paths (void); ++ + #endif + + /* +diff --git a/src/plugins/linux-cp/lcp_cli.c b/src/plugins/linux-cp/lcp_cli.c +index 0dcf600b3..c7f0658ee 100644 +--- a/src/plugins/linux-cp/lcp_cli.c ++++ b/src/plugins/linux-cp/lcp_cli.c +@@ -192,6 +192,17 @@ lcp_param_command_fn (vlib_main_t *vm, unformat_input_t *input, + return clib_error_return (0, "unknown input `%U'", + format_unformat_error, line_input); + } ++ else if (unformat (line_input, "route-no-paths")) ++ { ++ if (unformat (line_input, "on") || unformat (line_input, "enable")) ++ lcp_set_route_no_paths (1 /* is_del */); ++ else if (unformat (line_input, "off") || ++ unformat (line_input, "disable")) ++ lcp_set_route_no_paths (0 /* is_del */); ++ else ++ return clib_error_return (0, "unknown input `%U'", ++ format_unformat_error, line_input); ++ } + else + return clib_error_return (0, "unknown input `%U'", + format_unformat_error, line_input); +@@ -204,7 +215,8 @@ lcp_param_command_fn (vlib_main_t *vm, unformat_input_t *input, + VLIB_CLI_COMMAND (lcp_param_command, static) = { + .path = "lcp param", + .short_help = "lcp param [del-static-on-link-down (on|enable|off|disable)] " +- "[del-dynamic-on-link-down (on|enable|off|disable)]", ++ "[del-dynamic-on-link-down (on|enable|off|disable)] " ++ "[route-no-paths (on|enable|off|disable)]", + .function = lcp_param_command_fn, + }; + +diff --git a/src/plugins/linux-cp/lcp_interface.c b/src/plugins/linux-cp/lcp_interface.c +index 61665ad41..6f2b2e5c9 100644 +--- a/src/plugins/linux-cp/lcp_interface.c ++++ b/src/plugins/linux-cp/lcp_interface.c +@@ -138,6 +138,8 @@ lcp_itf_pair_show (u32 phy_sw_if_index) + lcp_get_del_static_on_link_down () ? "on" : "off"); + vlib_cli_output (vm, "lcp del-dynamic-on-link-down %s\n", + lcp_get_del_dynamic_on_link_down () ? "on" : "off"); ++ vlib_cli_output (vm, "lcp route-no-paths %s\n", ++ lcp_get_route_no_paths () ? "on" : "off"); + + if (phy_sw_if_index == ~0) + { +@@ -588,6 +590,8 @@ lcp_itf_pair_config (vlib_main_t *vm, unformat_input_t *input) + lcp_set_default_num_queues (tmp, 0 /* is_tx */); + else if (unformat (input, "num-tx-queues %d", &tmp)) + lcp_set_default_num_queues (tmp, 1 /* is_tx */); ++ else if (unformat (input, "route-no-paths")) ++ lcp_set_route_no_paths (1 /* is_del */); + else + return clib_error_return (0, "interfaces not found"); + } +diff --git a/src/plugins/linux-cp/lcp_router.c b/src/plugins/linux-cp/lcp_router.c +index 0efd53e64..6848f3d1c 100644 +--- a/src/plugins/linux-cp/lcp_router.c ++++ b/src/plugins/linux-cp/lcp_router.c +@@ -1157,6 +1157,33 @@ lcp_router_route_path_parse (struct rtnl_nexthop *rnh, void *arg) + } + } + ++/* ++ * Check if there is a need to punt the route. ++ * ++ * This function determines if a route should be punted to the local interface. ++ * A route is punted if it is of a type that requires special handling (e.g., ++ * RTN_LOCAL, RTN_BROADCAST, RTN_ANYCAST, etc.) and if it has no associated ++ * paths. ++ */ ++static bool ++check_if_punted (struct rtnl_route *rr, lcp_router_route_path_parse_t *ctx) ++{ ++ // If the configuration does not allow routes with no paths, return false ++ if (!lcp_get_route_no_paths ()) ++ return false; ++ ++ // If there are any paths associated with the route, return false ++ if (vec_len (ctx->paths) > 0) ++ return false; ++ ++ // If the route type is blackhole or higher, return false ++ if (rtnl_route_get_type (rr) >= RTN_BLACKHOLE) ++ return false; ++ ++ // Otherwise, the route should be punted ++ return true; ++} ++ + /* + * blackhole, unreachable, prohibit will not have a next hop in an + * RTM_NEWROUTE. Add a path for them. +@@ -1167,7 +1194,7 @@ lcp_router_route_path_add_special (struct rtnl_route *rr, + { + fib_route_path_t *path; + +- if (rtnl_route_get_type (rr) < RTN_BLACKHOLE) ++ if (rtnl_route_get_type (rr) < RTN_BLACKHOLE && !(lcp_get_route_no_paths ())) + return; + + /* if it already has a path, it does not need us to add one */ +@@ -1176,8 +1203,21 @@ lcp_router_route_path_add_special (struct rtnl_route *rr, + + vec_add2 (ctx->paths, path, 1); + +- path->frp_flags = FIB_ROUTE_PATH_FLAG_NONE | ctx->type_flags; +- path->frp_sw_if_index = ~0; ++ /* If there are no paths, and `lcp param route-no-paths` is enabled ++ * we need to add an extra local path. This allows punting traffic ++ * with destinations available only via kernel */ ++ if (lcp_get_route_no_paths ()) ++ { ++ path->frp_flags = FIB_ROUTE_PATH_LOCAL | ctx->type_flags; ++ } else { ++ path->frp_flags = FIB_ROUTE_PATH_FLAG_NONE | ctx->type_flags; ++ } ++ ++ /* Do not add interface to routes from kernel */ ++ if (rtnl_route_get_protocol (rr) != RTPROT_KERNEL) { ++ path->frp_sw_if_index = ~0; ++ } ++ + path->frp_proto = fib_proto_to_dpo (ctx->route_proto); + path->frp_preference = ctx->preference; + +@@ -1264,7 +1304,17 @@ lcp_router_route_del (struct rtnl_route *rr) + }; + + rtnl_route_foreach_nexthop (rr, lcp_router_route_path_parse, &np); +- lcp_router_route_path_add_special (rr, &np); ++ ++ if (check_if_punted (rr, &np)) ++ { ++ fib_table_entry_special_remove (nlt->nlt_fib_index, &pfx, ++ lcp_router_proto_fib_source (rproto)); ++ return; ++ } ++ else ++ { ++ lcp_router_route_path_add_special (rr, &np); ++ } + + if (0 != vec_len (np.paths)) + { +@@ -1335,7 +1385,7 @@ lcp_router_route_add (struct rtnl_route *rr, int is_replace) + + nlt = lcp_router_table_add_or_lock (table_id, pfx.fp_proto); + /* Skip any kernel routes and IPv6 LL or multicast routes */ +- if (rproto == RTPROT_KERNEL || ++ if ((rproto == RTPROT_KERNEL && !(lcp_get_route_no_paths ())) || + (FIB_PROTOCOL_IP6 == pfx.fp_proto && + (ip6_address_is_multicast (&pfx.fp_addr.ip6) || + ip6_address_is_link_local_unicast (&pfx.fp_addr.ip6)))) +@@ -1357,7 +1407,23 @@ lcp_router_route_add (struct rtnl_route *rr, int is_replace) + }; + + rtnl_route_foreach_nexthop (rr, lcp_router_route_path_parse, &np); +- lcp_router_route_path_add_special (rr, &np); ++ ++ if (check_if_punted (rr, &np)) ++ { ++ fib_source_t fib_src = lcp_router_proto_fib_source (rproto); ++ if (is_replace) ++ { ++ fib_table_entry_special_remove (nlt->nlt_fib_index, &pfx, fib_src); ++ } ++ ++ fib_table_entry_special_add (nlt->nlt_fib_index, &pfx, fib_src, ++ FIB_ENTRY_FLAG_LOCAL); ++ return; ++ } ++ else ++ { ++ lcp_router_route_path_add_special (rr, &np); ++ } + + if (0 != vec_len (np.paths)) + { +-- +2.39.5 + diff --git a/patches/vpp/0016-Revert-linux-cp-Added-routing-for-prefixes-with-no-p.patch b/patches/vpp/0016-Revert-linux-cp-Added-routing-for-prefixes-with-no-p.patch new file mode 100644 index 0000000..842893a --- /dev/null +++ b/patches/vpp/0016-Revert-linux-cp-Added-routing-for-prefixes-with-no-p.patch @@ -0,0 +1,248 @@ +From 350e148db0fb9708fb234e68e2eaa8500a0248d1 Mon Sep 17 00:00:00 2001 +From: Denys Haryachyy +Date: Tue, 18 Mar 2025 21:32:51 +0200 +Subject: [PATCH 16/17] Revert "linux-cp: Added routing for prefixes with no + paths available" + +This reverts commit 5583626fe1a9d11cffb8f759c996e341b7e54a7b. +--- + src/plugins/linux-cp/lcp.c | 16 ------ + src/plugins/linux-cp/lcp.h | 7 --- + src/plugins/linux-cp/lcp_cli.c | 14 +---- + src/plugins/linux-cp/lcp_interface.c | 4 -- + src/plugins/linux-cp/lcp_router.c | 78 +++------------------------- + 5 files changed, 7 insertions(+), 112 deletions(-) + +diff --git a/src/plugins/linux-cp/lcp.c b/src/plugins/linux-cp/lcp.c +index 6e8c38b8c..34e8550a1 100644 +--- a/src/plugins/linux-cp/lcp.c ++++ b/src/plugins/linux-cp/lcp.c +@@ -183,22 +183,6 @@ lcp_get_default_num_queues (u8 is_tx) + return lcpm->num_rx_queues ?: vlib_num_workers (); + } + +-void +-lcp_set_route_no_paths (u8 is_del) +-{ +- lcp_main_t *lcpm = &lcp_main; +- +- lcpm->route_no_paths = (is_del != 0); +-} +- +-u8 +-lcp_get_route_no_paths (void) +-{ +- lcp_main_t *lcpm = &lcp_main; +- +- return lcpm->route_no_paths; +-} +- + /* + * fd.io coding-style-patch-verification: ON + * +diff --git a/src/plugins/linux-cp/lcp.h b/src/plugins/linux-cp/lcp.h +index 5349bb492..e89b149f6 100644 +--- a/src/plugins/linux-cp/lcp.h ++++ b/src/plugins/linux-cp/lcp.h +@@ -33,7 +33,6 @@ typedef struct lcp_main_s + u8 test_mode; /* Set when Unit testing */ + u8 netlink_processing_active; /* Set while a batch of Netlink messages are + being processed */ +- u8 route_no_paths; /* Add routes with no paths as local */ + } lcp_main_t; + + extern lcp_main_t lcp_main; +@@ -70,12 +69,6 @@ u8 lcp_get_netlink_processing_active (void); + void lcp_set_default_num_queues (u16 num_queues, u8 is_tx); + u16 lcp_get_default_num_queues (u8 is_tx); + +-/** +- * Get/Set whether to install routes with no paths as local +- */ +-void lcp_set_route_no_paths (u8 is_del); +-u8 lcp_get_route_no_paths (void); +- + #endif + + /* +diff --git a/src/plugins/linux-cp/lcp_cli.c b/src/plugins/linux-cp/lcp_cli.c +index c7f0658ee..0dcf600b3 100644 +--- a/src/plugins/linux-cp/lcp_cli.c ++++ b/src/plugins/linux-cp/lcp_cli.c +@@ -192,17 +192,6 @@ lcp_param_command_fn (vlib_main_t *vm, unformat_input_t *input, + return clib_error_return (0, "unknown input `%U'", + format_unformat_error, line_input); + } +- else if (unformat (line_input, "route-no-paths")) +- { +- if (unformat (line_input, "on") || unformat (line_input, "enable")) +- lcp_set_route_no_paths (1 /* is_del */); +- else if (unformat (line_input, "off") || +- unformat (line_input, "disable")) +- lcp_set_route_no_paths (0 /* is_del */); +- else +- return clib_error_return (0, "unknown input `%U'", +- format_unformat_error, line_input); +- } + else + return clib_error_return (0, "unknown input `%U'", + format_unformat_error, line_input); +@@ -215,8 +204,7 @@ lcp_param_command_fn (vlib_main_t *vm, unformat_input_t *input, + VLIB_CLI_COMMAND (lcp_param_command, static) = { + .path = "lcp param", + .short_help = "lcp param [del-static-on-link-down (on|enable|off|disable)] " +- "[del-dynamic-on-link-down (on|enable|off|disable)] " +- "[route-no-paths (on|enable|off|disable)]", ++ "[del-dynamic-on-link-down (on|enable|off|disable)]", + .function = lcp_param_command_fn, + }; + +diff --git a/src/plugins/linux-cp/lcp_interface.c b/src/plugins/linux-cp/lcp_interface.c +index 6f2b2e5c9..61665ad41 100644 +--- a/src/plugins/linux-cp/lcp_interface.c ++++ b/src/plugins/linux-cp/lcp_interface.c +@@ -138,8 +138,6 @@ lcp_itf_pair_show (u32 phy_sw_if_index) + lcp_get_del_static_on_link_down () ? "on" : "off"); + vlib_cli_output (vm, "lcp del-dynamic-on-link-down %s\n", + lcp_get_del_dynamic_on_link_down () ? "on" : "off"); +- vlib_cli_output (vm, "lcp route-no-paths %s\n", +- lcp_get_route_no_paths () ? "on" : "off"); + + if (phy_sw_if_index == ~0) + { +@@ -590,8 +588,6 @@ lcp_itf_pair_config (vlib_main_t *vm, unformat_input_t *input) + lcp_set_default_num_queues (tmp, 0 /* is_tx */); + else if (unformat (input, "num-tx-queues %d", &tmp)) + lcp_set_default_num_queues (tmp, 1 /* is_tx */); +- else if (unformat (input, "route-no-paths")) +- lcp_set_route_no_paths (1 /* is_del */); + else + return clib_error_return (0, "interfaces not found"); + } +diff --git a/src/plugins/linux-cp/lcp_router.c b/src/plugins/linux-cp/lcp_router.c +index 6848f3d1c..0efd53e64 100644 +--- a/src/plugins/linux-cp/lcp_router.c ++++ b/src/plugins/linux-cp/lcp_router.c +@@ -1157,33 +1157,6 @@ lcp_router_route_path_parse (struct rtnl_nexthop *rnh, void *arg) + } + } + +-/* +- * Check if there is a need to punt the route. +- * +- * This function determines if a route should be punted to the local interface. +- * A route is punted if it is of a type that requires special handling (e.g., +- * RTN_LOCAL, RTN_BROADCAST, RTN_ANYCAST, etc.) and if it has no associated +- * paths. +- */ +-static bool +-check_if_punted (struct rtnl_route *rr, lcp_router_route_path_parse_t *ctx) +-{ +- // If the configuration does not allow routes with no paths, return false +- if (!lcp_get_route_no_paths ()) +- return false; +- +- // If there are any paths associated with the route, return false +- if (vec_len (ctx->paths) > 0) +- return false; +- +- // If the route type is blackhole or higher, return false +- if (rtnl_route_get_type (rr) >= RTN_BLACKHOLE) +- return false; +- +- // Otherwise, the route should be punted +- return true; +-} +- + /* + * blackhole, unreachable, prohibit will not have a next hop in an + * RTM_NEWROUTE. Add a path for them. +@@ -1194,7 +1167,7 @@ lcp_router_route_path_add_special (struct rtnl_route *rr, + { + fib_route_path_t *path; + +- if (rtnl_route_get_type (rr) < RTN_BLACKHOLE && !(lcp_get_route_no_paths ())) ++ if (rtnl_route_get_type (rr) < RTN_BLACKHOLE) + return; + + /* if it already has a path, it does not need us to add one */ +@@ -1203,21 +1176,8 @@ lcp_router_route_path_add_special (struct rtnl_route *rr, + + vec_add2 (ctx->paths, path, 1); + +- /* If there are no paths, and `lcp param route-no-paths` is enabled +- * we need to add an extra local path. This allows punting traffic +- * with destinations available only via kernel */ +- if (lcp_get_route_no_paths ()) +- { +- path->frp_flags = FIB_ROUTE_PATH_LOCAL | ctx->type_flags; +- } else { +- path->frp_flags = FIB_ROUTE_PATH_FLAG_NONE | ctx->type_flags; +- } +- +- /* Do not add interface to routes from kernel */ +- if (rtnl_route_get_protocol (rr) != RTPROT_KERNEL) { +- path->frp_sw_if_index = ~0; +- } +- ++ path->frp_flags = FIB_ROUTE_PATH_FLAG_NONE | ctx->type_flags; ++ path->frp_sw_if_index = ~0; + path->frp_proto = fib_proto_to_dpo (ctx->route_proto); + path->frp_preference = ctx->preference; + +@@ -1304,17 +1264,7 @@ lcp_router_route_del (struct rtnl_route *rr) + }; + + rtnl_route_foreach_nexthop (rr, lcp_router_route_path_parse, &np); +- +- if (check_if_punted (rr, &np)) +- { +- fib_table_entry_special_remove (nlt->nlt_fib_index, &pfx, +- lcp_router_proto_fib_source (rproto)); +- return; +- } +- else +- { +- lcp_router_route_path_add_special (rr, &np); +- } ++ lcp_router_route_path_add_special (rr, &np); + + if (0 != vec_len (np.paths)) + { +@@ -1385,7 +1335,7 @@ lcp_router_route_add (struct rtnl_route *rr, int is_replace) + + nlt = lcp_router_table_add_or_lock (table_id, pfx.fp_proto); + /* Skip any kernel routes and IPv6 LL or multicast routes */ +- if ((rproto == RTPROT_KERNEL && !(lcp_get_route_no_paths ())) || ++ if (rproto == RTPROT_KERNEL || + (FIB_PROTOCOL_IP6 == pfx.fp_proto && + (ip6_address_is_multicast (&pfx.fp_addr.ip6) || + ip6_address_is_link_local_unicast (&pfx.fp_addr.ip6)))) +@@ -1407,23 +1357,7 @@ lcp_router_route_add (struct rtnl_route *rr, int is_replace) + }; + + rtnl_route_foreach_nexthop (rr, lcp_router_route_path_parse, &np); +- +- if (check_if_punted (rr, &np)) +- { +- fib_source_t fib_src = lcp_router_proto_fib_source (rproto); +- if (is_replace) +- { +- fib_table_entry_special_remove (nlt->nlt_fib_index, &pfx, fib_src); +- } +- +- fib_table_entry_special_add (nlt->nlt_fib_index, &pfx, fib_src, +- FIB_ENTRY_FLAG_LOCAL); +- return; +- } +- else +- { +- lcp_router_route_path_add_special (rr, &np); +- } ++ lcp_router_route_path_add_special (rr, &np); + + if (0 != vec_len (np.paths)) + { +-- +2.39.5 + diff --git a/patches/vpp/0017-linux-cp-Added-routing-for-prefixes-with-no-paths-av.patch b/patches/vpp/0017-linux-cp-Added-routing-for-prefixes-with-no-paths-av.patch new file mode 100644 index 0000000..f673d36 --- /dev/null +++ b/patches/vpp/0017-linux-cp-Added-routing-for-prefixes-with-no-paths-av.patch @@ -0,0 +1,364 @@ +From 322efbd2c42c6c5007e601de6c752a6197385370 Mon Sep 17 00:00:00 2001 +From: zsdc +Date: Tue, 23 Jul 2024 20:06:41 +0300 +Subject: [PATCH 17/17] linux-cp: Added routing for prefixes with no paths + available + +Fixed GRE crashes in IPv4 and IPv6 FIB. + +A new CLI and configuration file option is available: + +``` +lcp param route-no-paths (on|enable|off|disable) +``` + +``` +linux-cp { + route-no-paths +} +``` + +If it is enabled, routes with no paths in VPP will be installed as local. +This allows punting traffic with destinations available only via a kernel +routing table, but not via VPP. + +(cherry picked from commit 35bf59ac3fc96f1af7591dafa1fae642a34558e5) + +linux-cp: Added routing for prefixes with no paths available + +A new CLI and configuration file option is available: + +``` +lcp param route-no-paths (on|enable|off|disable) +``` + +``` +linux-cp { + route-no-paths +} +``` + +If it is enabled, routes with no paths in VPP will be installed as local. +This allows punting traffic with destinations available only via a kernel +routing table, but not via VPP. + +(cherry picked from commit 35bf59ac3fc96f1af7591dafa1fae642a34558e5) +--- + src/plugins/linux-cp/lcp.c | 16 ++++ + src/plugins/linux-cp/lcp.h | 7 ++ + src/plugins/linux-cp/lcp_cli.c | 14 +++- + src/plugins/linux-cp/lcp_interface.c | 4 + + src/plugins/linux-cp/lcp_router.c | 108 +++++++++++++++++++++++---- + src/vnet/fib/fib_urpf_list.h | 12 +++ + src/vnet/ip/ip4_forward.c | 10 +++ + 7 files changed, 154 insertions(+), 17 deletions(-) + +diff --git a/src/plugins/linux-cp/lcp.c b/src/plugins/linux-cp/lcp.c +index 34e8550a1..6e8c38b8c 100644 +--- a/src/plugins/linux-cp/lcp.c ++++ b/src/plugins/linux-cp/lcp.c +@@ -183,6 +183,22 @@ lcp_get_default_num_queues (u8 is_tx) + return lcpm->num_rx_queues ?: vlib_num_workers (); + } + ++void ++lcp_set_route_no_paths (u8 is_del) ++{ ++ lcp_main_t *lcpm = &lcp_main; ++ ++ lcpm->route_no_paths = (is_del != 0); ++} ++ ++u8 ++lcp_get_route_no_paths (void) ++{ ++ lcp_main_t *lcpm = &lcp_main; ++ ++ return lcpm->route_no_paths; ++} ++ + /* + * fd.io coding-style-patch-verification: ON + * +diff --git a/src/plugins/linux-cp/lcp.h b/src/plugins/linux-cp/lcp.h +index e89b149f6..5349bb492 100644 +--- a/src/plugins/linux-cp/lcp.h ++++ b/src/plugins/linux-cp/lcp.h +@@ -33,6 +33,7 @@ typedef struct lcp_main_s + u8 test_mode; /* Set when Unit testing */ + u8 netlink_processing_active; /* Set while a batch of Netlink messages are + being processed */ ++ u8 route_no_paths; /* Add routes with no paths as local */ + } lcp_main_t; + + extern lcp_main_t lcp_main; +@@ -69,6 +70,12 @@ u8 lcp_get_netlink_processing_active (void); + void lcp_set_default_num_queues (u16 num_queues, u8 is_tx); + u16 lcp_get_default_num_queues (u8 is_tx); + ++/** ++ * Get/Set whether to install routes with no paths as local ++ */ ++void lcp_set_route_no_paths (u8 is_del); ++u8 lcp_get_route_no_paths (void); ++ + #endif + + /* +diff --git a/src/plugins/linux-cp/lcp_cli.c b/src/plugins/linux-cp/lcp_cli.c +index 0dcf600b3..c7f0658ee 100644 +--- a/src/plugins/linux-cp/lcp_cli.c ++++ b/src/plugins/linux-cp/lcp_cli.c +@@ -192,6 +192,17 @@ lcp_param_command_fn (vlib_main_t *vm, unformat_input_t *input, + return clib_error_return (0, "unknown input `%U'", + format_unformat_error, line_input); + } ++ else if (unformat (line_input, "route-no-paths")) ++ { ++ if (unformat (line_input, "on") || unformat (line_input, "enable")) ++ lcp_set_route_no_paths (1 /* is_del */); ++ else if (unformat (line_input, "off") || ++ unformat (line_input, "disable")) ++ lcp_set_route_no_paths (0 /* is_del */); ++ else ++ return clib_error_return (0, "unknown input `%U'", ++ format_unformat_error, line_input); ++ } + else + return clib_error_return (0, "unknown input `%U'", + format_unformat_error, line_input); +@@ -204,7 +215,8 @@ lcp_param_command_fn (vlib_main_t *vm, unformat_input_t *input, + VLIB_CLI_COMMAND (lcp_param_command, static) = { + .path = "lcp param", + .short_help = "lcp param [del-static-on-link-down (on|enable|off|disable)] " +- "[del-dynamic-on-link-down (on|enable|off|disable)]", ++ "[del-dynamic-on-link-down (on|enable|off|disable)] " ++ "[route-no-paths (on|enable|off|disable)]", + .function = lcp_param_command_fn, + }; + +diff --git a/src/plugins/linux-cp/lcp_interface.c b/src/plugins/linux-cp/lcp_interface.c +index 61665ad41..6f2b2e5c9 100644 +--- a/src/plugins/linux-cp/lcp_interface.c ++++ b/src/plugins/linux-cp/lcp_interface.c +@@ -138,6 +138,8 @@ lcp_itf_pair_show (u32 phy_sw_if_index) + lcp_get_del_static_on_link_down () ? "on" : "off"); + vlib_cli_output (vm, "lcp del-dynamic-on-link-down %s\n", + lcp_get_del_dynamic_on_link_down () ? "on" : "off"); ++ vlib_cli_output (vm, "lcp route-no-paths %s\n", ++ lcp_get_route_no_paths () ? "on" : "off"); + + if (phy_sw_if_index == ~0) + { +@@ -588,6 +590,8 @@ lcp_itf_pair_config (vlib_main_t *vm, unformat_input_t *input) + lcp_set_default_num_queues (tmp, 0 /* is_tx */); + else if (unformat (input, "num-tx-queues %d", &tmp)) + lcp_set_default_num_queues (tmp, 1 /* is_tx */); ++ else if (unformat (input, "route-no-paths")) ++ lcp_set_route_no_paths (1 /* is_del */); + else + return clib_error_return (0, "interfaces not found"); + } +diff --git a/src/plugins/linux-cp/lcp_router.c b/src/plugins/linux-cp/lcp_router.c +index 0efd53e64..0e2800624 100644 +--- a/src/plugins/linux-cp/lcp_router.c ++++ b/src/plugins/linux-cp/lcp_router.c +@@ -1157,6 +1157,42 @@ lcp_router_route_path_parse (struct rtnl_nexthop *rnh, void *arg) + } + } + ++/* ++ * Check if there is a need to punt the route. ++ * ++ * This function determines if a route should be punted to the local interface. ++ * A route is punted if it is of a type that requires special handling (e.g., ++ * RTN_LOCAL, RTN_BROADCAST, RTN_ANYCAST, etc.) and if it has no associated ++ * paths. ++ */ ++static bool ++check_if_punted (struct rtnl_route *rr, lcp_router_route_path_parse_t *ctx, ++ fib_prefix_t *pfx) ++{ ++ // If the configuration does not allow routes with no paths, return false ++ if (!lcp_get_route_no_paths ()) ++ return false; ++ ++ // If there are any paths associated with the route, return false ++ if (vec_len (ctx->paths) > 0) ++ return false; ++ ++ // If the route type is blackhole or higher, return false ++ if (rtnl_route_get_type (rr) >= RTN_BLACKHOLE) ++ return false; ++ ++ // If the route is IPv6 and either multicast or link-local unicast, return false ++ if (FIB_PROTOCOL_IP6 == pfx->fp_proto && ++ (ip6_address_is_multicast (&pfx->fp_addr.ip6) || ++ ip6_address_is_link_local_unicast (&pfx->fp_addr.ip6))) ++ return false; ++ ++ LCP_ROUTER_DBG ("Punting route"); ++ ++ // Otherwise, the route should be punted ++ return true; ++} ++ + /* + * blackhole, unreachable, prohibit will not have a next hop in an + * RTM_NEWROUTE. Add a path for them. +@@ -1167,7 +1203,7 @@ lcp_router_route_path_add_special (struct rtnl_route *rr, + { + fib_route_path_t *path; + +- if (rtnl_route_get_type (rr) < RTN_BLACKHOLE) ++ if (rtnl_route_get_type (rr) < RTN_BLACKHOLE && !(lcp_get_route_no_paths ())) + return; + + /* if it already has a path, it does not need us to add one */ +@@ -1176,8 +1212,21 @@ lcp_router_route_path_add_special (struct rtnl_route *rr, + + vec_add2 (ctx->paths, path, 1); + +- path->frp_flags = FIB_ROUTE_PATH_FLAG_NONE | ctx->type_flags; +- path->frp_sw_if_index = ~0; ++ /* If there are no paths, and `lcp param route-no-paths` is enabled ++ * we need to add an extra local path. This allows punting traffic ++ * with destinations available only via kernel */ ++ if (lcp_get_route_no_paths ()) ++ { ++ path->frp_flags = FIB_ROUTE_PATH_LOCAL | ctx->type_flags; ++ } else { ++ path->frp_flags = FIB_ROUTE_PATH_FLAG_NONE | ctx->type_flags; ++ } ++ ++ /* Do not add interface to routes from kernel */ ++ if (rtnl_route_get_protocol (rr) != RTPROT_KERNEL) { ++ path->frp_sw_if_index = ~0; ++ } ++ + path->frp_proto = fib_proto_to_dpo (ctx->route_proto); + path->frp_preference = ctx->preference; + +@@ -1264,7 +1313,17 @@ lcp_router_route_del (struct rtnl_route *rr) + }; + + rtnl_route_foreach_nexthop (rr, lcp_router_route_path_parse, &np); +- lcp_router_route_path_add_special (rr, &np); ++ ++ if (check_if_punted (rr, &np, &pfx)) ++ { ++ fib_table_entry_special_remove (nlt->nlt_fib_index, &pfx, ++ lcp_router_proto_fib_source (rproto)); ++ return; ++ } ++ else ++ { ++ lcp_router_route_path_add_special (rr, &np); ++ } + + if (0 != vec_len (np.paths)) + { +@@ -1334,17 +1393,7 @@ lcp_router_route_add (struct rtnl_route *rr, int is_replace) + entry_flags = lcp_router_route_mk_entry_flags (rtype, table_id, rproto); + + nlt = lcp_router_table_add_or_lock (table_id, pfx.fp_proto); +- /* Skip any kernel routes and IPv6 LL or multicast routes */ +- if (rproto == RTPROT_KERNEL || +- (FIB_PROTOCOL_IP6 == pfx.fp_proto && +- (ip6_address_is_multicast (&pfx.fp_addr.ip6) || +- ip6_address_is_link_local_unicast (&pfx.fp_addr.ip6)))) +- { +- LCP_ROUTER_DBG ("route skip: %d:%U %U", rtnl_route_get_table (rr), +- format_fib_prefix, &pfx, format_fib_entry_flags, +- entry_flags); +- return; +- } ++ + LCP_ROUTER_DBG ("route %s: %d:%U %U", is_replace ? "replace" : "add", + rtnl_route_get_table (rr), format_fib_prefix, &pfx, + format_fib_entry_flags, entry_flags); +@@ -1357,7 +1406,34 @@ lcp_router_route_add (struct rtnl_route *rr, int is_replace) + }; + + rtnl_route_foreach_nexthop (rr, lcp_router_route_path_parse, &np); +- lcp_router_route_path_add_special (rr, &np); ++ ++ if (check_if_punted (rr, &np, &pfx)) ++ { ++ fib_source_t fib_src = lcp_router_proto_fib_source (rproto); ++ if (is_replace) ++ { ++ fib_table_entry_special_remove (nlt->nlt_fib_index, &pfx, fib_src); ++ } ++ ++ fib_table_entry_special_add (nlt->nlt_fib_index, &pfx, fib_src, ++ FIB_ENTRY_FLAG_LOCAL); ++ return; ++ } ++ else ++ { ++ /* Skip any kernel routes and IPv6 LL or multicast routes */ ++ if ((rproto == RTPROT_KERNEL) || ++ (FIB_PROTOCOL_IP6 == pfx.fp_proto && ++ (ip6_address_is_multicast (&pfx.fp_addr.ip6) || ++ ip6_address_is_link_local_unicast (&pfx.fp_addr.ip6)))) ++ { ++ LCP_ROUTER_DBG ("route skip: %d:%U %U", rtnl_route_get_table (rr), ++ format_fib_prefix, &pfx, format_fib_entry_flags, ++ entry_flags); ++ return; ++ } ++ lcp_router_route_path_add_special (rr, &np); ++ } + + if (0 != vec_len (np.paths)) + { +diff --git a/src/vnet/fib/fib_urpf_list.h b/src/vnet/fib/fib_urpf_list.h +index a3116bb93..be1a9a822 100644 +--- a/src/vnet/fib/fib_urpf_list.h ++++ b/src/vnet/fib/fib_urpf_list.h +@@ -138,8 +138,20 @@ fib_urpf_check_size (index_t ui) + { + fib_urpf_list_t *urpf; + ++ // Check if the provided uRPF list index is invalid ++ if (PREDICT_FALSE(INDEX_INVALID == ui)) ++ return (0); ++ + urpf = fib_urpf_list_get(ui); + ++ // Check if the uRPF list is NULL ++ if (PREDICT_FALSE(NULL == urpf)) ++ return (0); ++ ++ // Check if the interface list in the uRPF list is NULL ++ if (PREDICT_FALSE(NULL == urpf->furpf_itfs)) ++ return (0); ++ + return (vec_len(urpf->furpf_itfs)); + } + +diff --git a/src/vnet/ip/ip4_forward.c b/src/vnet/ip/ip4_forward.c +index ff74b52eb..80688a097 100644 +--- a/src/vnet/ip/ip4_forward.c ++++ b/src/vnet/ip/ip4_forward.c +@@ -1522,6 +1522,16 @@ ip4_local_check_src (vlib_buffer_t *b, ip4_header_t *ip0, + vnet_buffer (b)->sw_if_index[VLIB_TX] != ~0 ? + vnet_buffer (b)->sw_if_index[VLIB_TX] : vnet_buffer (b)->ip.fib_index; + ++ if (pool_is_free_index (ip4_fibs, vnet_buffer (b)->ip.fib_index)) ++ { ++ *error0 = IP4_ERROR_SRC_LOOKUP_MISS; ++ last_check->src.as_u32 = ip0->src_address.as_u32; ++ last_check->error = *error0; ++ last_check->first = 0; ++ last_check->fib_index = vnet_buffer (b)->ip.fib_index; ++ return; ++ } ++ + vnet_buffer (b)->ip.rx_sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX]; + if (is_receive_dpo) + { +-- +2.39.5 +