summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/vnet/dpo/lookup_dpo.h4
-rw-r--r--src/vnet/fib/fib_api.h1
-rw-r--r--src/vnet/fib/fib_path.c10
-rw-r--r--src/vnet/fib/fib_path.h11
-rw-r--r--src/vnet/fib/fib_test.c43
-rw-r--r--src/vnet/fib/fib_types.h4
-rw-r--r--src/vnet/ip/ip.api4
-rw-r--r--src/vnet/ip/ip_api.c5
-rw-r--r--src/vnet/mpls/mpls_api.c15
-rw-r--r--test/test_ip4.py110
-rw-r--r--test/vpp_ip_route.py3
-rw-r--r--test/vpp_papi_provider.py4
12 files changed, 201 insertions, 13 deletions
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,