From: Neale Ranns Date: Fri, 13 Oct 2017 12:15:07 +0000 (-0700) Subject: Source Lookup progammable via API X-Git-Tag: v18.04-rc0~465 X-Git-Url: https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commitdiff_plain;h=054c03ac9c20a5e38121590b83f01fd91f82acf0 Source Lookup progammable via API Change-Id: I5d5d4f22b6369d504455a644f73076d772fbcfb4 Signed-off-by: Neale Ranns --- diff --git a/src/vnet/dpo/lookup_dpo.h b/src/vnet/dpo/lookup_dpo.h index 7dfd0385a9d..4ebd6050fc6 100644 --- a/src/vnet/dpo/lookup_dpo.h +++ b/src/vnet/dpo/lookup_dpo.h @@ -42,8 +42,8 @@ typedef enum lookup_table_t_ { } __attribute__ ((packed)) lookup_table_t; #define LOOKUP_TABLES { \ - [LOOKUP_INPUT_SRC_ADDR] = "table-input-interface", \ - [LOOKUP_INPUT_DST_ADDR] = "table-configured", \ + [LOOKUP_TABLE_FROM_INPUT_INTERFACE] = "table-input-interface", \ + [LOOKUP_TABLE_FROM_CONFIG] = "table-configured", \ } /** diff --git a/src/vnet/fib/fib_api.h b/src/vnet/fib/fib_api.h index c369e8f8588..e5b94e14124 100644 --- a/src/vnet/fib/fib_api.h +++ b/src/vnet/fib/fib_api.h @@ -41,6 +41,7 @@ add_del_route_t_handler (u8 is_multipath, u8 is_interface_rx, u8 is_rpf_id, u8 is_l2_bridged, + u8 is_source_lookup, u32 fib_index, const fib_prefix_t * prefix, dpo_proto_t next_hop_proto, diff --git a/src/vnet/fib/fib_path.c b/src/vnet/fib/fib_path.c index 889d17def9c..7b713a4b5c5 100644 --- a/src/vnet/fib/fib_path.c +++ b/src/vnet/fib/fib_path.c @@ -1054,6 +1054,8 @@ fib_path_route_flags_to_cfg_flags (const fib_route_path_t *rpath) cfg_flags |= FIB_PATH_CFG_FLAG_EXCLUSIVE; if (rpath->frp_flags & FIB_ROUTE_PATH_DROP) cfg_flags |= FIB_PATH_CFG_FLAG_DROP; + if (rpath->frp_flags & FIB_ROUTE_PATH_SOURCE_LOOKUP) + cfg_flags |= FIB_PATH_CFG_FLAG_DEAG_SRC; return (cfg_flags); } @@ -1695,16 +1697,20 @@ fib_path_resolve (fib_node_index_t path_index) * Resolve via a lookup DPO. * FIXME. control plane should add routes with a table ID */ + lookup_input_t input; lookup_cast_t cast; - + cast = (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_RPF_ID ? LOOKUP_MULTICAST : LOOKUP_UNICAST); + input = (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_DEAG_SRC ? + LOOKUP_INPUT_SRC_ADDR : + LOOKUP_INPUT_DST_ADDR); lookup_dpo_add_or_lock_w_fib_index(path->deag.fp_tbl_id, path->fp_nh_proto, cast, - LOOKUP_INPUT_DST_ADDR, + input, LOOKUP_TABLE_FROM_CONFIG, &path->fp_dpo); break; diff --git a/src/vnet/fib/fib_path.h b/src/vnet/fib/fib_path.h index f986e437a3b..3a0544c1c42 100644 --- a/src/vnet/fib/fib_path.h +++ b/src/vnet/fib/fib_path.h @@ -79,14 +79,13 @@ typedef enum fib_path_cfg_attribute_t_ { */ FIB_PATH_CFG_ATTRIBUTE_LOCAL, /** - * The path is L2. i.e. the parameters therein are to be interpreted as - * pertaining to L2 config. + * The deag path does a source lookup */ - FIB_PATH_CFG_ATTRIBUTE_L2, + FIB_PATH_CFG_ATTRIBUTE_DEAG_SRC, /** * Marker. Add new types before this one, then update it. */ - FIB_PATH_CFG_ATTRIBUTE_LAST = FIB_PATH_CFG_ATTRIBUTE_LOCAL, + FIB_PATH_CFG_ATTRIBUTE_LAST = FIB_PATH_CFG_ATTRIBUTE_DEAG_SRC, } __attribute__ ((packed)) fib_path_cfg_attribute_t; /** @@ -103,7 +102,7 @@ typedef enum fib_path_cfg_attribute_t_ { [FIB_PATH_CFG_ATTRIBUTE_ATTACHED] = "attached", \ [FIB_PATH_CFG_ATTRIBUTE_INTF_RX] = "interface-rx", \ [FIB_PATH_CFG_ATTRIBUTE_RPF_ID] = "rpf-id", \ - [FIB_PATH_CFG_ATTRIBUTE_L2] = "l2", \ + [FIB_PATH_CFG_ATTRIBUTE_DEAG_SRC] = "deag-src", \ } #define FOR_EACH_FIB_PATH_CFG_ATTRIBUTE(_item) \ @@ -124,7 +123,7 @@ typedef enum fib_path_cfg_flags_t_ { FIB_PATH_CFG_FLAG_ATTACHED = (1 << FIB_PATH_CFG_ATTRIBUTE_ATTACHED), FIB_PATH_CFG_FLAG_INTF_RX = (1 << FIB_PATH_CFG_ATTRIBUTE_INTF_RX), FIB_PATH_CFG_FLAG_RPF_ID = (1 << FIB_PATH_CFG_ATTRIBUTE_RPF_ID), - FIB_PATH_CFG_FLAG_L2 = (1 << FIB_PATH_CFG_ATTRIBUTE_L2), + FIB_PATH_CFG_FLAG_DEAG_SRC = (1 << FIB_PATH_CFG_ATTRIBUTE_DEAG_SRC), } __attribute__ ((packed)) fib_path_cfg_flags_t; diff --git a/src/vnet/fib/fib_test.c b/src/vnet/fib/fib_test.c index 03c9ee75f48..da517b0ceea 100644 --- a/src/vnet/fib/fib_test.c +++ b/src/vnet/fib/fib_test.c @@ -3543,6 +3543,49 @@ fib_test_v4 (void) "4.4.4.4/32 is deag in %d %U", lkd->lkd_fib_index, format_dpo_id, dpo, 0); + FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input), + "4.4.4.4/32 is source deag in %d %U", + lkd->lkd_input, + format_dpo_id, dpo, 0); + + fib_table_entry_delete(fib_index, + &pfx_4_4_4_4_s_32, + FIB_SOURCE_API); + FIB_TEST(FIB_NODE_INDEX_INVALID == + fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32), + "4.4.4.4/32 removed"); + vec_free(r_paths); + + /* + * A route deag route in a source lookup table + */ + fib_table_entry_path_add(fib_index, + &pfx_4_4_4_4_s_32, + FIB_SOURCE_API, + FIB_ENTRY_FLAG_NONE, + DPO_PROTO_IP4, + &zero_addr, + ~0, + fib_index, + 1, + NULL, + FIB_ROUTE_PATH_SOURCE_LOOKUP); + + fei = fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32); + FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.4.4.4/32 present"); + + dpo = fib_entry_contribute_ip_forwarding(fei); + dpo = load_balance_get_bucket(dpo->dpoi_index, 0); + lkd = lookup_dpo_get(dpo->dpoi_index); + + FIB_TEST((fib_index == lkd->lkd_fib_index), + "4.4.4.4/32 is deag in %d %U", + lkd->lkd_fib_index, + format_dpo_id, dpo, 0); + FIB_TEST((LOOKUP_INPUT_SRC_ADDR == lkd->lkd_input), + "4.4.4.4/32 is source deag in %d %U", + lkd->lkd_input, + format_dpo_id, dpo, 0); fib_table_entry_delete(fib_index, &pfx_4_4_4_4_s_32, diff --git a/src/vnet/fib/fib_types.h b/src/vnet/fib/fib_types.h index b5d4ec95911..7eadbb9bb70 100644 --- a/src/vnet/fib/fib_types.h +++ b/src/vnet/fib/fib_types.h @@ -303,6 +303,10 @@ typedef enum fib_route_path_flags_t_ * A local path with a RPF-ID => multicast traffic */ FIB_ROUTE_PATH_RPF_ID = (1 << 7), + /** + * A deag path using the packet's source not destination address. + */ + FIB_ROUTE_PATH_SOURCE_LOOKUP = (1 << 8), } fib_route_path_flags_t; /** diff --git a/src/vnet/ip/ip.api b/src/vnet/ip/ip.api index df9ce6e615a..f5341667892 100644 --- a/src/vnet/ip/ip.api +++ b/src/vnet/ip/ip.api @@ -370,6 +370,9 @@ autoreply define sw_interface_ip6_set_link_local_address @param is_local - @param is_classify - @param is_multipath - Set to 1 if this is a multipath route, else 0 + @param is_source_lookup - The the path is a deaggregate path (i.e. a lookup + in another table) is the lookup on the packet's + source address or destination. @param not_last - Is last or not last msg in group of multiple add/del msgs @param next_hop_weight - @param dst_address_length - @@ -398,6 +401,7 @@ autoreply define ip_add_del_route u8 is_resolve_host; u8 is_resolve_attached; u8 is_l2_bridged; + u8 is_source_lookup; /* Is last/not-last message in group of multiple add/del messages. */ u8 not_last; u8 next_hop_weight; diff --git a/src/vnet/ip/ip_api.c b/src/vnet/ip/ip_api.c index f3712d3fd29..8a3ceb2a4e9 100644 --- a/src/vnet/ip/ip_api.c +++ b/src/vnet/ip/ip_api.c @@ -830,6 +830,7 @@ add_del_route_t_handler (u8 is_multipath, u8 is_interface_rx, u8 is_rpf_id, u8 is_l2_bridged, + u8 is_source_lookup, u32 fib_index, const fib_prefix_t * prefix, dpo_proto_t next_hop_proto, @@ -877,6 +878,8 @@ add_del_route_t_handler (u8 is_multipath, path_flags |= FIB_ROUTE_PATH_INTF_RX; if (is_rpf_id) path_flags |= FIB_ROUTE_PATH_RPF_ID; + if (is_source_lookup) + path_flags |= FIB_ROUTE_PATH_SOURCE_LOOKUP; if (is_multicast) entry_flags |= FIB_ENTRY_FLAG_MULTICAST; @@ -1076,6 +1079,7 @@ ip4_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp) mp->is_resolve_host, mp->is_resolve_attached, 0, 0, mp->is_l2_bridged, + mp->is_source_lookup, fib_index, &pfx, DPO_PROTO_IP4, &nh, ntohl (mp->next_hop_sw_if_index), @@ -1136,6 +1140,7 @@ ip6_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp) mp->is_resolve_host, mp->is_resolve_attached, 0, 0, mp->is_l2_bridged, + mp->is_source_lookup, fib_index, &pfx, DPO_PROTO_IP6, &nh, ntohl (mp->next_hop_sw_if_index), next_hop_fib_index, diff --git a/src/vnet/mpls/mpls_api.c b/src/vnet/mpls/mpls_api.c index e41466e6cf5..c47e94dd34a 100644 --- a/src/vnet/mpls/mpls_api.c +++ b/src/vnet/mpls/mpls_api.c @@ -219,11 +219,21 @@ mpls_route_add_del_t_handler (vnet_main_t * vnm, label_stack[ii] = ntohl (mp->mr_next_hop_out_label_stack[ii]); } - return (add_del_route_t_handler (mp->mr_is_multipath, mp->mr_is_add, 0, // mp->is_drop, + /* *INDENT-OFF* */ + return (add_del_route_t_handler (mp->mr_is_multipath, mp->mr_is_add, + 0, // mp->is_drop, 0, // mp->is_unreach, 0, // mp->is_prohibit, 0, // mp->is_local, - mp->mr_is_multicast, mp->mr_is_classify, mp->mr_classify_table_index, mp->mr_is_resolve_host, mp->mr_is_resolve_attached, mp->mr_is_interface_rx, mp->mr_is_rpf_id, 0, // l2_bridged + mp->mr_is_multicast, + mp->mr_is_classify, + mp->mr_classify_table_index, + mp->mr_is_resolve_host, + mp->mr_is_resolve_attached, + mp->mr_is_interface_rx, + mp->mr_is_rpf_id, + 0, // l2_bridged + 0, // is source_lookup fib_index, &pfx, mp->mr_next_hop_proto, &nh, ntohl (mp->mr_next_hop_sw_if_index), @@ -232,6 +242,7 @@ mpls_route_add_del_t_handler (vnet_main_t * vnm, mp->mr_next_hop_preference, ntohl (mp->mr_next_hop_via_label), label_stack)); + /* *INDENT-ON* */ } void diff --git a/test/test_ip4.py b/test/test_ip4.py index 5bd50ce3ea4..42fd1164a5f 100644 --- a/test/test_ip4.py +++ b/test/test_ip4.py @@ -7,7 +7,7 @@ from framework import VppTestCase, VppTestRunner from vpp_sub_interface import VppSubInterface, VppDot1QSubint, VppDot1ADSubint from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpMRoute, \ VppMRoutePath, MRouteItfFlags, MRouteEntryFlags, VppMplsIpBind, \ - VppMplsTable + VppMplsTable, VppIpTable from scapy.packet import Raw from scapy.layers.l2 import Ether, Dot1Q, ARP @@ -1119,5 +1119,113 @@ class TestIPPunt(VppTestCase): is_add=0) +class TestIPDeag(VppTestCase): + """ IPv4 Deaggregate Routes """ + + def setUp(self): + super(TestIPDeag, self).setUp() + + self.create_pg_interfaces(range(3)) + + for i in self.pg_interfaces: + i.admin_up() + i.config_ip4() + i.resolve_arp() + + def tearDown(self): + super(TestIPDeag, self).tearDown() + for i in self.pg_interfaces: + i.unconfig_ip4() + i.admin_down() + + def send_and_expect(self, input, pkts, output): + self.vapi.cli("clear trace") + input.add_stream(pkts) + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + rx = output.get_capture(len(pkts)) + return rx + + def send_and_assert_no_replies(self, intf, pkts, remark): + self.vapi.cli("clear trace") + intf.add_stream(pkts) + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + for i in self.pg_interfaces: + i.get_capture(0) + i.assert_nothing_captured(remark=remark) + + def test_ip_deag(self): + """ IP Deag Routes """ + + # + # Create a table to be used for: + # 1 - another destination address lookup + # 2 - a source address lookup + # + table_dst = VppIpTable(self, 1) + table_src = VppIpTable(self, 2) + table_dst.add_vpp_config() + table_src.add_vpp_config() + + # + # Add a route in the default table to point to a deag/ + # second lookup in each of these tables + # + route_to_dst = VppIpRoute(self, "1.1.1.1", 32, + [VppRoutePath("0.0.0.0", + 0xffffffff, + nh_table_id=1)]) + route_to_src = VppIpRoute(self, "1.1.1.2", 32, + [VppRoutePath("0.0.0.0", + 0xffffffff, + nh_table_id=2, + is_source_lookup=1)]) + route_to_dst.add_vpp_config() + route_to_src.add_vpp_config() + + # + # packets to these destination are dropped, since they'll + # hit the respective default routes in the second table + # + p_dst = (Ether(src=self.pg0.remote_mac, + dst=self.pg0.local_mac) / + IP(src="5.5.5.5", dst="1.1.1.1") / + TCP(sport=1234, dport=1234) / + Raw('\xa5' * 100)) + p_src = (Ether(src=self.pg0.remote_mac, + dst=self.pg0.local_mac) / + IP(src="2.2.2.2", dst="1.1.1.2") / + TCP(sport=1234, dport=1234) / + Raw('\xa5' * 100)) + pkts_dst = p_dst * 257 + pkts_src = p_src * 257 + + self.send_and_assert_no_replies(self.pg0, pkts_dst, + "IP in dst table") + self.send_and_assert_no_replies(self.pg0, pkts_src, + "IP in src table") + + # + # add a route in the dst table to forward via pg1 + # + route_in_dst = VppIpRoute(self, "1.1.1.1", 32, + [VppRoutePath(self.pg1.remote_ip4, + self.pg1.sw_if_index)], + table_id=1) + route_in_dst.add_vpp_config() + self.send_and_expect(self.pg0, pkts_dst, self.pg1) + + # + # add a route in the src table to forward via pg2 + # + route_in_src = VppIpRoute(self, "2.2.2.2", 32, + [VppRoutePath(self.pg2.remote_ip4, + self.pg2.sw_if_index)], + table_id=2) + route_in_src.add_vpp_config() + self.send_and_expect(self.pg0, pkts_src, self.pg2) + + if __name__ == '__main__': unittest.main(testRunner=VppTestRunner) diff --git a/test/vpp_ip_route.py b/test/vpp_ip_route.py index e670230487a..7501146e96a 100644 --- a/test/vpp_ip_route.py +++ b/test/vpp_ip_route.py @@ -107,6 +107,7 @@ class VppRoutePath(object): is_interface_rx=0, is_resolve_host=0, is_resolve_attached=0, + is_source_lookup=0, proto=DpoProto.DPO_PROTO_IP4): self.nh_itf = nh_sw_if_index self.nh_table_id = nh_table_id @@ -124,6 +125,7 @@ class VppRoutePath(object): self.is_resolve_host = is_resolve_host self.is_resolve_attached = is_resolve_attached self.is_interface_rx = is_interface_rx + self.is_source_lookup = is_source_lookup self.is_rpf_id = 0 if rpf_id != 0: self.is_rpf_id = 1 @@ -197,6 +199,7 @@ class VppIpRoute(VppObject): if path.proto == DpoProto.DPO_PROTO_ETHERNET else 0, is_resolve_host=path.is_resolve_host, is_resolve_attached=path.is_resolve_attached, + is_source_lookup=path.is_source_lookup, is_multipath=1 if len(self.paths) > 1 else 0) self._test.registry.register(self, self._test.logger) diff --git a/test/vpp_papi_provider.py b/test/vpp_papi_provider.py index 3d6a3184bb8..f7047eaf58f 100644 --- a/test/vpp_papi_provider.py +++ b/test/vpp_papi_provider.py @@ -747,6 +747,7 @@ class VppPapiProvider(object): is_classify=0, is_multipath=0, is_l2_bridged=0, + is_source_lookup=0, not_last=0): """ @@ -766,6 +767,8 @@ class VppPapiProvider(object): :param is_multipath: (Default value = 0) :param is_resolve_host: (Default value = 0) :param is_resolve_attached: (Default value = 0) + :param is_l2_bridged: (Default value = 0) + :param is_source_lookup: (Default value = 0) :param not_last: (Default value = 0) :param next_hop_weight: (Default value = 1) @@ -788,6 +791,7 @@ class VppPapiProvider(object): 'is_resolve_host': is_resolve_host, 'is_resolve_attached': is_resolve_attached, 'is_l2_bridged': is_l2_bridged, + 'is_source_lookup': is_source_lookup, 'not_last': not_last, 'next_hop_weight': next_hop_weight, 'dst_address_length': dst_address_length,