1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
@media only all and (prefers-color-scheme: dark) {
.highlight .hll { background-color: #49483e }
.highlight .c { color: #75715e } /* Comment */
.highlight .err { color: #960050; background-color: #1e0010 } /* Error */
.highlight .k { color: #66d9ef } /* Keyword */
.highlight .l { color: #ae81ff } /* Literal */
.highlight .n { color: #f8f8f2 } /* Name */
.highlight .o { color: #f92672 } /* Operator */
.highlight .p { color: #f8f8f2 } /* Punctuation */
.highlight .ch { color: #75715e } /* Comment.Hashbang */
.highlight .cm { color: #75715e } /* Comment.Multiline */
.highlight .cp { color: #75715e } /* Comment.Preproc */
.highlight .cpf { color: #75715e } /* Comment.PreprocFile */
.highlight .c1 { color: #75715e } /* Comment.Single */
.highlight .cs { color: #75715e } /* Comment.Special */
.highlight .gd { color: #f92672 } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gi { color: #a6e22e } /* Generic.Inserted */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #75715e } /* Generic.Subheading */
.highlight .kc { color: #66d9ef } /* Keyword.Constant */
.highlight .kd { color: #66d9ef } /* Keyword.Declaration */
.highlight .kn { color: #f92672 } /* Keyword.Namespace */
.highlight .kp { color: #66d9ef } /* Keyword.Pseudo */
.highlight .kr { color: #66d9ef } /* Keyword.Reserved */
.highlight .kt { color: #66d9ef } /* Keyword.Type */
.highlight .ld { color: #e6db74 } /* Literal.Date */
.highlight .m { color: #ae81ff } /* Literal.Number */
.highlight .s { color: #e6db74 } /* Literal.String */
.highlight .na { color: #a6e22e } /* Name.Attribute */
.highlight .nb { color: #f8f8f2 } /* Name.Builtin */
.highlight .nc { color: #a6e22e } /* Name.Class */
.highlight .no { color: #66d9ef } /* Name.Constant */
.highlight .nd { color: #a6e22e } /* Name.Decorator */
.highlight .ni { color: #f8f8f2 } /* Name.Entity */
.highlight .ne { color: #a6e22e } /* Name.Exception */
.highlight .nf { color: #a6e22e } /* Name.Function */
.highlight .nl { color: #f8f8f2 } /* Name.Label */
.highlight .nn { color: #f8f8f2 } /* Name.Namespace */
.highlight .nx { color: #a6e22e } /* Name.Other */
.highlight .py { color: #f8f8f2 } /* Name.Property */
.highlight .nt { color: #f92672 } /* Name.Tag */
.highlight .nv { color: #f8f8f2 } /* Name.Variable */
.highlight .ow { color: #f92672 } /* Operator.Word */
.highlight .w { color: #f8f8f2 } /* Text.Whitespace */
.highlight .mb { color: #ae81ff } /* Literal.Number.Bin */
.highlight .mf { color: #ae81ff } /* Literal.Number.Float */
.highlight .mh { color: #ae81ff } /* Literal.Number.Hex */
.highlight .mi { color: #ae81ff } /* Literal.Number.Integer */
.highlight .mo { color: #ae81ff } /* Literal.Number.Oct */
.highlight .sa { color: #e6db74 } /* Literal.String.Affix */
.highlight .sb { color: #e6db74 } /* Literal.String.Backtick */
.highlight .sc { color: #e6db74 } /* Literal.String.Char */
.highlight .dl { color: #e6db74 } /* Literal.String.Delimiter */
.highlight .sd { color: #e6db74 } /* Literal.String.Doc */
.highlight .s2 { color: #e6db74 } /* Literal.String.Double */
.highlight .se { color: #ae81ff } /* Literal.String.Escape */
.highlight .sh { color: #e6db74 } /* Literal.String.Heredoc */
.highlight .si { color: #e6db74 } /* Literal.String.Interpol */
.highlight .sx { color: #e6db74 } /* Literal.String.Other */
.highlight .sr { color: #e6db74 } /* Literal.String.Regex */
.highlight .s1 { color: #e6db74 } /* Literal.String.Single */
.highlight .ss { color: #e6db74 } /* Literal.String.Symbol */
.highlight .bp { color: #f8f8f2 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #a6e22e } /* Name.Function.Magic */
.highlight .vc { color: #f8f8f2 } /* Name.Variable.Class */
.highlight .vg { color: #f8f8f2 } /* Name.Variable.Global */
.highlight .vi { color: #f8f8f2 } /* Name.Variable.Instance */
.highlight .vm { color: #f8f8f2 } /* Name.Variable.Magic */
.highlight .il { color: #ae81ff } /* Literal.Number.Integer.Long */
}
@media (prefers-color-scheme: light) {
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
}
/*
* Copyright (c) 2016 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __FIB_API_H__
#define __FIB_API_H__
int
add_del_route_check (fib_protocol_t table_proto,
u32 table_id,
u32 next_hop_sw_if_index,
fib_protocol_t next_hop_table_proto,
u32 next_hop_table_id,
u8 create_missing_tables,
u32 * fib_index, u32 * next_hop_fib_index);
int
add_del_route_t_handler (u8 is_multipath,
u8 is_add,
u8 is_drop,
u8 is_unreach,
#!/usr/bin/env python3
import unittest
from framework import VppTestCase, VppTestRunner
from vpp_ip_route import VppIpTable
from scapy.packet import Raw
from scapy.layers.l2 import Ether
from scapy.layers.inet import IP, UDP, ICMP
from scapy.layers.inet6 import IPv6
from vpp_papi import VppEnum
NUM_PKTS = 67
class TestSVS(VppTestCase):
"""SVS Test Case"""
@classmethod
def setUpClass(cls):
super(TestSVS, cls).setUpClass()
@classmethod
def tearDownClass(cls):
super(TestSVS, cls).tearDownClass()
def setUp(self):
super(TestSVS, self).setUp()
# create 2 pg interfaces
self.create_pg_interfaces(range(4))
table_id = 0
for i in self.pg_interfaces:
i.admin_up()
if table_id != 0:
tbl = VppIpTable(self, table_id)
tbl.add_vpp_config()
tbl = VppIpTable(self, table_id, is_ip6=1)
tbl.add_vpp_config()
i.set_table_ip4(table_id)
i.set_table_ip6(table_id)
i.config_ip4()
i.resolve_arp()
i.config_ip6()
i.resolve_ndp()
table_id += 1
def tearDown(self):
for i in self.pg_interfaces:
i.unconfig_ip4()
i.unconfig_ip6()
i.set_table_ip4(0)
i.set_table_ip6(0)
i.admin_down()
super(TestSVS, self).tearDown()
def test_svs4(self):
"""Source VRF Select IP4"""
#
# packets destined out of the 3 non-default table interfaces
#
pkts_0 = [
(
Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
/ IP(src="1.1.1.1", dst=self.pg1.remote_ip4)
/ UDP(sport=1234, dport=1234)
/ Raw(b"\xa5" * 100)
),
(
Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
/ IP(src="2.2.2.2", dst=self.pg2.remote_ip4)
/ UDP(sport=1234, dport=1234)
/ Raw(b"\xa5" * 100)
),
(
Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
/ IP(src="3.3.3.3", dst=self.pg3.remote_ip4)
/ UDP(sport=1234, dport=1234)
/ Raw(b"\xa5" * 100)
),
]
pkts_1 = [
(
Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
/ IP(src="1.1.1.1", dst=self.pg1.remote_ip4)
/ UDP(sport=1234, dport=1234)
/ Raw(b"\xa5" * 100)
),
(
Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
/ IP(src="2.2.2.2", dst=self.pg2.remote_ip4)
/ UDP(sport=1234, dport=1234)
/ Raw(b"\xa5" * 100)
),
(
Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
/ IP(src="3.3.3.3", dst=self.pg3.remote_ip4)
/ UDP(sport=1234, dport=1234)
/ Raw(b"\xa5" * 100)
),
]
#
# before adding the SVS config all these packets are dropped when
# ingressing on pg0 since pg0 is in the default table
#
for p in pkts_0:
self.send_and_assert_no_replies(self.pg0, p * 1)
#
# Add table 1001 & 1002 into which we'll add the routes
# determining the source VRF selection
#
table_ids = [101, 102]
for table_id in table_ids:
self.vapi.svs_table_add_del(
is_add=1,
af=VppEnum.vl_api_address_family_t.ADDRESS_IP4,
table_id=table_id,
)
#
# map X.0.0.0/8 to each SVS table for lookup in table X
#
for i in range(1, 4):
self.vapi.svs_route_add_del(
is_add=1,
prefix="%d.0.0.0/8" % i,
table_id=table_id,
source_table_id=i,
)
#
# Enable SVS on pg0/pg1 using table 1001/1002
#
self.vapi.svs_enable_disable(
is_enable=1,
af=VppEnum.vl_api_address_family_t.ADDRESS_IP4,
table_id=table_ids[0],
sw_if_index=self.pg0.sw_if_index,
)
self.vapi.svs_enable_disable(
is_enable=1,
af=VppEnum.vl_api_address_family_t.ADDRESS_IP4,
table_id=table_ids[1],
sw_if_index=self.pg1.sw_if_index,
)
#
# now all the packets should be delivered out the respective interface
#
self.send_and_expect(self.pg0, pkts_0[0] * NUM_PKTS, self.pg1)
self.send_and_expect(self.pg0, pkts_0[1] * NUM_PKTS, self.pg2)
self.send_and_expect(self.pg0, pkts_0[2] * NUM_PKTS, self.pg3)
self.send_and_expect(self.pg1, pkts_1[0] * NUM_PKTS, self.pg1)
self.send_and_expect(self.pg1, pkts_1[1] * NUM_PKTS, self.pg2)
self.send_and_expect(self.pg1, pkts_1[2] * NUM_PKTS, self.pg3)
#
# check that if the SVS lookup does not match a route the packet
# is forwarded using the interface's routing table
#
p = (
Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
/ IP(src=self.pg0.remote_ip4, dst=self.pg0.remote_ip4)
/ UDP(sport=1234, dport=1234)
/ Raw(b"\xa5" * 100)
)
self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg0)
p = (
Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
/ IP(src=self.pg1.remote_ip4, dst=self.pg1.remote_ip4)
/ UDP(sport=1234, dport=1234)
/ Raw(b"\xa5" * 100)
)
self.send_and_expect(self.pg1, p * NUM_PKTS, self.pg1)
#
# dump the SVS configs
#
ss = self.vapi.svs_dump()
self.assertEqual(ss[0].table_id, table_ids[0])
self.assertEqual(ss[0].sw_if_index, self.pg0.sw_if_index)
self.assertEqual(ss[0].af, VppEnum.vl_api_address_family_t.ADDRESS_IP4)
self.assertEqual(ss[1].table_id, table_ids[1])
self.assertEqual(ss[1].sw_if_index, self.pg1.sw_if_index)
self.assertEqual(ss[1].af, VppEnum.vl_api_address_family_t.ADDRESS_IP4)
#
# cleanup
#
self.vapi.svs_enable_disable(
is_enable=0,
af=VppEnum.vl_api_address_family_t.ADDRESS_IP4,
table_id=table_ids[0],
sw_if_index=self.pg0.sw_if_index,
)
self.vapi.svs_enable_disable(
is_enable=0,
af=VppEnum.vl_api_address_family_t.ADDRESS_IP4,
table_id=table_ids[1],
sw_if_index=self.pg1.sw_if_index,
)
for table_id in table_ids:
for i in range(1, 4):
self.vapi.svs_route_add_del(
is_add=0,
prefix="%d.0.0.0/8" % i,
table_id=table_id,
source_table_id=0,
)
self.vapi.svs_table_add_del(
is_add=0,
af=VppEnum.vl_api_address_family_t.ADDRESS_IP4,
table_id=table_id,
)
def test_svs6(self):
"""Source VRF Select IP6"""
#
# packets destined out of the 3 non-default table interfaces
#
pkts_0 = [
(
Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
/ IPv6(src="2001:1::1", dst=self.pg1.remote_ip6)
/ UDP(sport=1234, dport=1234)
/ Raw(b"\xa5" * 100)
),
(
Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
/ IPv6(src="2001:2::1", dst=self.pg2.remote_ip6)
/ UDP(sport=1234, dport=1234)
/ Raw(b"\xa5" * 100)
),
(
Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
/ IPv6(src="2001:3::1", dst=self.pg3.remote_ip6)
/ UDP(sport=1234, dport=1234)
/ Raw(b"\xa5" * 100)
),
]
pkts_1 = [
(
Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
/ IPv6(src="2001:1::1", dst=self.pg1.remote_ip6)
/ UDP(sport=1234, dport=1234)
/ Raw(b"\xa5" * 100)
),
(
Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
/ IPv6(src="2001:2::1", dst=self.pg2.remote_ip6)
/ UDP(sport=1234, dport=1234)
/ Raw(b"\xa5" * 100)
),
(
Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
/ IPv6(src="2001:3::1", dst=self.pg3.remote_ip6)
/ UDP(sport=1234, dport=1234)
/ Raw(b"\xa5" * 100)
),
]
#
# before adding the SVS config all these packets are dropped when
# ingressing on pg0 since pg0 is in the default table
#
for p in pkts_0:
self.send_and_assert_no_replies(self.pg0, p * 1)
#
# Add table 1001 & 1002 into which we'll add the routes
# determining the source VRF selection
#
table_ids = [101, 102]
for table_id in table_ids:
self.vapi.svs_table_add_del(
is_add=1,
af=VppEnum.vl_api_address_family_t.ADDRESS_IP6,
table_id=table_id,
)
#
# map X.0.0.0/8 to each SVS table for lookup in table X
#
for i in range(1, 4):
self.vapi.svs_route_add_del(
is_add=1,
prefix="2001:%d::/32" % i,
table_id=table_id,
source_table_id=i,
)
#
# Enable SVS on pg0/pg1 using table 1001/1002
#
self.vapi.svs_enable_disable(
is_enable=1,
af=VppEnum.vl_api_address_family_t.ADDRESS_IP6,
table_id=table_ids[0],
sw_if_index=self.pg0.sw_if_index,
)
self.vapi.svs_enable_disable(
is_enable=1,
af=VppEnum.vl_api_address_family_t.ADDRESS_IP6,
table_id=table_ids[1],
sw_if_index=self.pg1.sw_if_index,
)
#
# now all the packets should be delivered out the respective interface
#
self.send_and_expect(self.pg0, pkts_0[0] * NUM_PKTS, self.pg1)
self.send_and_expect(self.pg0, pkts_0[1] * NUM_PKTS, self.pg2)
self.send_and_expect(self.pg0, pkts_0[2] * NUM_PKTS, self.pg3)
self.send_and_expect(self.pg1, pkts_1[0] * NUM_PKTS, self.pg1)
self.send_and_expect(self.pg1, pkts_1[1] * NUM_PKTS, self.pg2)
self.send_and_expect(self.pg1, pkts_1[2] * NUM_PKTS, self.pg3)
#
# check that if the SVS lookup does not match a route the packet
# is forwarded using the interface's routing table
#
p = (
Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
/ IPv6(src=self.pg0.remote_ip6, dst=self.pg0.remote_ip6)
/ UDP(sport=1234, dport=1234)
/ Raw(b"\xa5" * 100)
)
self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg0)
p = (
Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
/ IPv6(src=self.pg1.remote_ip6, dst=self.pg1.remote_ip6)
/ UDP(sport=1234, dport=1234)
/ Raw(b"\xa5" * 100)
)
self.send_and_expect(self.pg1, p * NUM_PKTS, self.pg1)
#
# dump the SVS configs
#
ss = self.vapi.svs_dump()
self.assertEqual(ss[0].table_id, table_ids[0])
self.assertEqual(ss[0].sw_if_index, self.pg0.sw_if_index)
self.assertEqual(ss[0].af, VppEnum.vl_api_address_family_t.ADDRESS_IP6)
self.assertEqual(ss[1].table_id, table_ids[1])
self.assertEqual(ss[1].sw_if_index, self.pg1.sw_if_index)
self.assertEqual(ss[1].af, VppEnum.vl_api_address_family_t.ADDRESS_IP6)
#
# cleanup
#
self.vapi.svs_enable_disable(
is_enable=0,
af=VppEnum.vl_api_address_family_t.ADDRESS_IP6,
table_id=table_ids[0],
sw_if_index=self.pg0.sw_if_index,
)
self.vapi.svs_enable_disable(
is_enable=0,
af=VppEnum.vl_api_address_family_t.ADDRESS_IP6,
table_id=table_ids[1],
sw_if_index=self.pg1.sw_if_index,
)
for table_id in table_ids:
for i in range(1, 4):
self.vapi.svs_route_add_del(
is_add=0,
prefix="2001:%d::/32" % i,
table_id=table_id,
source_table_id=0,
)
self.vapi.svs_table_add_del(
is_add=0,
af=VppEnum.vl_api_address_family_t.ADDRESS_IP6,
table_id=table_id,
)
if __name__ == "__main__":
unittest.main(testRunner=VppTestRunner)
|