urpf: Unicast reverse Path Forwarding (plugin)
Type: feature - move the IP4 code to plugin - add ip6 support - add suport for uRPF on TX - add tests Change-Id: I074c2debc486d3e79c12fad4b8dbd72c41e841a0 Signed-off-by: Neale Ranns <nranns@cisco.com>
This commit is contained in:
@ -660,6 +660,11 @@ I: vrrp
|
||||
M: Matthew Smith <mgsmith@netgate.com>
|
||||
F: src/plugins/vrrp
|
||||
|
||||
Plugin - Unicast Reverse Path forwarding
|
||||
I: urpf
|
||||
M: Neale Ranns <nranns@cisco.com>
|
||||
F: src/plugins/urpf
|
||||
|
||||
VPP Config Tooling
|
||||
I: vpp_config
|
||||
M: John DeNisco <jdenisco@cisco.com>
|
||||
|
27
src/plugins/urpf/CMakeLists.txt
Normal file
27
src/plugins/urpf/CMakeLists.txt
Normal file
@ -0,0 +1,27 @@
|
||||
# Copyright (c) 2020 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.
|
||||
|
||||
add_vpp_plugin(urpf
|
||||
SOURCES
|
||||
urpf.c
|
||||
urpf_api.c
|
||||
ip4_urpf.c
|
||||
ip6_urpf.c
|
||||
|
||||
MULTIARCH_SOURCES
|
||||
ip4_urpf.c
|
||||
ip6_urpf.c
|
||||
|
||||
API_FILES
|
||||
urpf.api
|
||||
)
|
171
src/plugins/urpf/ip4_urpf.c
Normal file
171
src/plugins/urpf/ip4_urpf.c
Normal file
@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Copyright (c) 2015 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.
|
||||
*/
|
||||
/*
|
||||
* ip/ip4_source_check.c: IP v4 check source address (unicast RPF check)
|
||||
*
|
||||
* Copyright (c) 2008 Eliot Dresselhaus
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <urpf/urpf.h>
|
||||
#include <urpf/urpf_dp.h>
|
||||
|
||||
static char *ip4_urpf_error_strings[] = {
|
||||
#define _(a,b) "ip4-" # b,
|
||||
foreach_urpf_error
|
||||
#undef _
|
||||
};
|
||||
|
||||
VLIB_NODE_FN (ip4_rx_urpf_loose) (vlib_main_t * vm,
|
||||
vlib_node_runtime_t * node,
|
||||
vlib_frame_t * frame)
|
||||
{
|
||||
return (urpf_inline (vm, node, frame, AF_IP4, VLIB_RX, URPF_MODE_LOOSE));
|
||||
}
|
||||
|
||||
VLIB_NODE_FN (ip4_rx_urpf_strict) (vlib_main_t * vm,
|
||||
vlib_node_runtime_t * node,
|
||||
vlib_frame_t * frame)
|
||||
{
|
||||
return (urpf_inline (vm, node, frame, AF_IP4, VLIB_RX, URPF_MODE_STRICT));
|
||||
}
|
||||
|
||||
VLIB_NODE_FN (ip4_tx_urpf_loose) (vlib_main_t * vm,
|
||||
vlib_node_runtime_t * node,
|
||||
vlib_frame_t * frame)
|
||||
{
|
||||
return (urpf_inline (vm, node, frame, AF_IP4, VLIB_TX, URPF_MODE_LOOSE));
|
||||
}
|
||||
|
||||
VLIB_NODE_FN (ip4_tx_urpf_strict) (vlib_main_t * vm,
|
||||
vlib_node_runtime_t * node,
|
||||
vlib_frame_t * frame)
|
||||
{
|
||||
return (urpf_inline (vm, node, frame, AF_IP4, VLIB_TX, URPF_MODE_STRICT));
|
||||
}
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
VLIB_REGISTER_NODE (ip4_rx_urpf_loose) = {
|
||||
.name = "ip4-rx-urpf-loose",
|
||||
.vector_size = sizeof (u32),
|
||||
|
||||
.n_next_nodes = URPF_N_NEXT,
|
||||
.next_nodes = {
|
||||
[URPF_NEXT_DROP] = "ip4-drop",
|
||||
},
|
||||
.n_errors = ARRAY_LEN (ip4_urpf_error_strings),
|
||||
.error_strings = ip4_urpf_error_strings,
|
||||
|
||||
.format_buffer = format_ip4_header,
|
||||
.format_trace = format_urpf_trace,
|
||||
};
|
||||
|
||||
VLIB_REGISTER_NODE (ip4_rx_urpf_strict) = {
|
||||
.name = "ip4-rx-urpf-strict",
|
||||
.vector_size = sizeof (u32),
|
||||
|
||||
.n_next_nodes = URPF_N_NEXT,
|
||||
.next_nodes = {
|
||||
[URPF_NEXT_DROP] = "ip4-drop",
|
||||
},
|
||||
.n_errors = ARRAY_LEN (ip4_urpf_error_strings),
|
||||
.error_strings = ip4_urpf_error_strings,
|
||||
|
||||
.format_buffer = format_ip4_header,
|
||||
.format_trace = format_urpf_trace,
|
||||
};
|
||||
|
||||
VLIB_REGISTER_NODE (ip4_tx_urpf_loose) = {
|
||||
.name = "ip4-tx-urpf-loose",
|
||||
.vector_size = sizeof (u32),
|
||||
|
||||
.n_next_nodes = URPF_N_NEXT,
|
||||
.next_nodes = {
|
||||
[URPF_NEXT_DROP] = "ip4-drop",
|
||||
},
|
||||
.n_errors = ARRAY_LEN (ip4_urpf_error_strings),
|
||||
.error_strings = ip4_urpf_error_strings,
|
||||
|
||||
.format_buffer = format_ip4_header,
|
||||
.format_trace = format_urpf_trace,
|
||||
};
|
||||
|
||||
VLIB_REGISTER_NODE (ip4_tx_urpf_strict) = {
|
||||
.name = "ip4-tx-urpf-strict",
|
||||
.vector_size = sizeof (u32),
|
||||
|
||||
.n_next_nodes = URPF_N_NEXT,
|
||||
.next_nodes = {
|
||||
[URPF_NEXT_DROP] = "ip4-drop",
|
||||
},
|
||||
.n_errors = ARRAY_LEN (ip4_urpf_error_strings),
|
||||
.error_strings = ip4_urpf_error_strings,
|
||||
|
||||
.format_buffer = format_ip4_header,
|
||||
.format_trace = format_urpf_trace,
|
||||
};
|
||||
|
||||
VNET_FEATURE_INIT (ip4_rx_urpf_loose_feat, static) =
|
||||
{
|
||||
.arc_name = "ip4-unicast",
|
||||
.node_name = "ip4-rx-urpf-loose",
|
||||
.runs_before = VNET_FEATURES ("ip4-rx-urpf-strict"),
|
||||
};
|
||||
|
||||
VNET_FEATURE_INIT (ip4_rx_urpf_strict_feat, static) =
|
||||
{
|
||||
.arc_name = "ip4-unicast",
|
||||
.node_name = "ip4-rx-urpf-strict",
|
||||
.runs_before = VNET_FEATURES ("ip4-policer-classify"),
|
||||
};
|
||||
|
||||
VNET_FEATURE_INIT (ip4_tx_urpf_loose_feat, static) =
|
||||
{
|
||||
.arc_name = "ip4-output",
|
||||
.node_name = "ip4-tx-urpf-loose",
|
||||
};
|
||||
|
||||
VNET_FEATURE_INIT (ip4_tx_urpf_strict_feat, static) =
|
||||
{
|
||||
.arc_name = "ip4-output",
|
||||
.node_name = "ip4-tx-urpf-strict",
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
*
|
||||
* Local Variables:
|
||||
* eval: (c-set-style "gnu")
|
||||
* End:
|
||||
*/
|
171
src/plugins/urpf/ip6_urpf.c
Normal file
171
src/plugins/urpf/ip6_urpf.c
Normal file
@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Copyright (c) 2015 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.
|
||||
*/
|
||||
/*
|
||||
* ip/ip4_source_check.c: IP v4 check source address (unicast RPF check)
|
||||
*
|
||||
* Copyright (c) 2008 Eliot Dresselhaus
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <urpf/urpf.h>
|
||||
#include <urpf/urpf_dp.h>
|
||||
|
||||
static char *ip6_urpf_error_strings[] = {
|
||||
#define _(a,b) "ip6-" # b,
|
||||
foreach_urpf_error
|
||||
#undef _
|
||||
};
|
||||
|
||||
VLIB_NODE_FN (ip6_rx_urpf_loose) (vlib_main_t * vm,
|
||||
vlib_node_runtime_t * node,
|
||||
vlib_frame_t * frame)
|
||||
{
|
||||
return (urpf_inline (vm, node, frame, AF_IP6, VLIB_RX, URPF_MODE_LOOSE));
|
||||
}
|
||||
|
||||
VLIB_NODE_FN (ip6_rx_urpf_strict) (vlib_main_t * vm,
|
||||
vlib_node_runtime_t * node,
|
||||
vlib_frame_t * frame)
|
||||
{
|
||||
return (urpf_inline (vm, node, frame, AF_IP6, VLIB_RX, URPF_MODE_STRICT));
|
||||
}
|
||||
|
||||
VLIB_NODE_FN (ip6_tx_urpf_loose) (vlib_main_t * vm,
|
||||
vlib_node_runtime_t * node,
|
||||
vlib_frame_t * frame)
|
||||
{
|
||||
return (urpf_inline (vm, node, frame, AF_IP6, VLIB_TX, URPF_MODE_LOOSE));
|
||||
}
|
||||
|
||||
VLIB_NODE_FN (ip6_tx_urpf_strict) (vlib_main_t * vm,
|
||||
vlib_node_runtime_t * node,
|
||||
vlib_frame_t * frame)
|
||||
{
|
||||
return (urpf_inline (vm, node, frame, AF_IP6, VLIB_TX, URPF_MODE_STRICT));
|
||||
}
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
VLIB_REGISTER_NODE (ip6_rx_urpf_loose) = {
|
||||
.name = "ip6-rx-urpf-loose",
|
||||
.vector_size = sizeof (u32),
|
||||
|
||||
.n_next_nodes = URPF_N_NEXT,
|
||||
.next_nodes = {
|
||||
[URPF_NEXT_DROP] = "ip6-drop",
|
||||
},
|
||||
.n_errors = ARRAY_LEN (ip6_urpf_error_strings),
|
||||
.error_strings = ip6_urpf_error_strings,
|
||||
|
||||
.format_buffer = format_ip6_header,
|
||||
.format_trace = format_urpf_trace,
|
||||
};
|
||||
|
||||
VLIB_REGISTER_NODE (ip6_rx_urpf_strict) = {
|
||||
.name = "ip6-rx-urpf-strict",
|
||||
.vector_size = sizeof (u32),
|
||||
|
||||
.n_next_nodes = URPF_N_NEXT,
|
||||
.next_nodes = {
|
||||
[URPF_NEXT_DROP] = "ip6-drop",
|
||||
},
|
||||
.n_errors = ARRAY_LEN (ip6_urpf_error_strings),
|
||||
.error_strings = ip6_urpf_error_strings,
|
||||
|
||||
.format_buffer = format_ip6_header,
|
||||
.format_trace = format_urpf_trace,
|
||||
};
|
||||
|
||||
VLIB_REGISTER_NODE (ip6_tx_urpf_loose) = {
|
||||
.name = "ip6-tx-urpf-loose",
|
||||
.vector_size = sizeof (u32),
|
||||
|
||||
.n_next_nodes = URPF_N_NEXT,
|
||||
.next_nodes = {
|
||||
[URPF_NEXT_DROP] = "ip6-drop",
|
||||
},
|
||||
.n_errors = ARRAY_LEN (ip6_urpf_error_strings),
|
||||
.error_strings = ip6_urpf_error_strings,
|
||||
|
||||
.format_buffer = format_ip6_header,
|
||||
.format_trace = format_urpf_trace,
|
||||
};
|
||||
|
||||
VLIB_REGISTER_NODE (ip6_tx_urpf_strict) = {
|
||||
.name = "ip6-tx-urpf-strict",
|
||||
.vector_size = sizeof (u32),
|
||||
|
||||
.n_next_nodes = URPF_N_NEXT,
|
||||
.next_nodes = {
|
||||
[URPF_NEXT_DROP] = "ip6-drop",
|
||||
},
|
||||
.n_errors = ARRAY_LEN (ip6_urpf_error_strings),
|
||||
.error_strings = ip6_urpf_error_strings,
|
||||
|
||||
.format_buffer = format_ip6_header,
|
||||
.format_trace = format_urpf_trace,
|
||||
};
|
||||
|
||||
VNET_FEATURE_INIT (ip6_rx_urpf_loose_feat, static) =
|
||||
{
|
||||
.arc_name = "ip6-unicast",
|
||||
.node_name = "ip6-rx-urpf-loose",
|
||||
.runs_before = VNET_FEATURES ("ip6-rx-urpf-strict"),
|
||||
};
|
||||
|
||||
VNET_FEATURE_INIT (ip6_rx_urpf_strict_feat, static) =
|
||||
{
|
||||
.arc_name = "ip6-unicast",
|
||||
.node_name = "ip6-rx-urpf-strict",
|
||||
.runs_before = VNET_FEATURES ("ip6-policer-classify"),
|
||||
};
|
||||
|
||||
VNET_FEATURE_INIT (ip6_tx_urpf_loose_feat, static) =
|
||||
{
|
||||
.arc_name = "ip6-output",
|
||||
.node_name = "ip6-tx-urpf-loose",
|
||||
};
|
||||
|
||||
VNET_FEATURE_INIT (ip6_tx_urpf_strict_feat, static) =
|
||||
{
|
||||
.arc_name = "ip6-output",
|
||||
.node_name = "ip6-tx-urpf-strict",
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
*
|
||||
* Local Variables:
|
||||
* eval: (c-set-style "gnu")
|
||||
* End:
|
||||
*/
|
295
src/plugins/urpf/test/test_urpf.py
Normal file
295
src/plugins/urpf/test/test_urpf.py
Normal file
@ -0,0 +1,295 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import unittest
|
||||
|
||||
from framework import VppTestCase, VppTestRunner
|
||||
|
||||
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
|
||||
|
||||
N_PKTS = 63
|
||||
|
||||
|
||||
class TestURPF(VppTestCase):
|
||||
""" Unicast Reverse Path Forwarding Test Case """
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestURPF, cls).setUpClass()
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
super(TestURPF, cls).tearDownClass()
|
||||
|
||||
def setUp(self):
|
||||
super(TestURPF, self).setUp()
|
||||
|
||||
# create 4 pg interfaces so there are a few addresses
|
||||
# in the FIB
|
||||
self.create_pg_interfaces(range(4))
|
||||
|
||||
for i in self.pg_interfaces:
|
||||
i.admin_up()
|
||||
i.config_ip4()
|
||||
i.resolve_arp()
|
||||
i.config_ip6()
|
||||
i.resolve_ndp()
|
||||
|
||||
def tearDown(self):
|
||||
for i in self.pg_interfaces:
|
||||
i.unconfig_ip4()
|
||||
i.unconfig_ip6()
|
||||
i.admin_down()
|
||||
super(TestURPF, self).tearDown()
|
||||
|
||||
def test_urpf4(self):
|
||||
""" uRPF IP4 """
|
||||
|
||||
e = VppEnum
|
||||
p_spoof_loose = (Ether(dst=self.pg0.local_mac,
|
||||
src=self.pg0.remote_mac) /
|
||||
IP(src="3.3.3.3", dst=self.pg1.remote_ip4) /
|
||||
UDP(sport=1234, dport=1234) /
|
||||
Raw(b'\xa5' * 100)) * N_PKTS
|
||||
p_spoof_strict = (Ether(dst=self.pg0.local_mac,
|
||||
src=self.pg0.remote_mac) /
|
||||
IP(src=self.pg2.remote_ip4,
|
||||
dst=self.pg1.remote_ip4) /
|
||||
UDP(sport=1234, dport=1234) /
|
||||
Raw(b'\xa5' * 100)) * N_PKTS
|
||||
p_good = (Ether(dst=self.pg0.local_mac,
|
||||
src=self.pg0.remote_mac) /
|
||||
IP(src=self.pg0.remote_ip4,
|
||||
dst=self.pg1.remote_ip4) /
|
||||
UDP(sport=1234, dport=1234) /
|
||||
Raw(b'\xa5' * 100)) * N_PKTS
|
||||
|
||||
#
|
||||
# before adding the uRPF, ensure all packets are forwarded
|
||||
#
|
||||
self.send_and_expect(self.pg0, p_good, self.pg1)
|
||||
self.send_and_expect(self.pg0, p_spoof_strict, self.pg1)
|
||||
self.send_and_expect(self.pg0, p_spoof_loose, self.pg1)
|
||||
|
||||
#
|
||||
# apply loose uRPF check on pg0 rx
|
||||
#
|
||||
self.vapi.urpf_update(is_input=True,
|
||||
mode=e.vl_api_urpf_mode_t.URPF_API_MODE_LOOSE,
|
||||
af=e.vl_api_address_family_t.ADDRESS_IP4,
|
||||
sw_if_index=self.pg0.sw_if_index)
|
||||
|
||||
# good packets still pass
|
||||
self.send_and_expect(self.pg0, p_good, self.pg1)
|
||||
# packets from address for which there is a route are forwarded
|
||||
self.send_and_expect(self.pg0, p_spoof_strict, self.pg1)
|
||||
# packets from address to which there is no route are dropped
|
||||
self.send_and_assert_no_replies(self.pg0, p_spoof_loose)
|
||||
|
||||
self.assert_error_counter_equal("ip4-rx-urpf-loose", N_PKTS)
|
||||
|
||||
#
|
||||
# crank it up to strict mode
|
||||
#
|
||||
self.vapi.urpf_update(is_input=True,
|
||||
mode=e.vl_api_urpf_mode_t.URPF_API_MODE_STRICT,
|
||||
af=e.vl_api_address_family_t.ADDRESS_IP4,
|
||||
sw_if_index=self.pg0.sw_if_index)
|
||||
|
||||
# good packets still pass
|
||||
self.send_and_expect(self.pg0, p_good, self.pg1)
|
||||
# packets that would not be routed back thru pg0 are dropped
|
||||
self.send_and_assert_no_replies(self.pg0, p_spoof_strict)
|
||||
self.send_and_assert_no_replies(self.pg0, p_spoof_loose)
|
||||
|
||||
self.assert_error_counter_equal("ip4-rx-urpf-strict", 2 * N_PKTS)
|
||||
|
||||
#
|
||||
# disable uRPF, all traffic should pass
|
||||
#
|
||||
self.vapi.urpf_update(is_input=True,
|
||||
mode=e.vl_api_urpf_mode_t.URPF_API_MODE_OFF,
|
||||
af=e.vl_api_address_family_t.ADDRESS_IP4,
|
||||
sw_if_index=self.pg0.sw_if_index)
|
||||
|
||||
self.send_and_expect(self.pg0, p_good, self.pg1)
|
||||
self.send_and_expect(self.pg0, p_spoof_strict, self.pg1)
|
||||
self.send_and_expect(self.pg0, p_spoof_loose, self.pg1)
|
||||
|
||||
#
|
||||
# Now apply in the TX direction
|
||||
# for loose it is the same deal, they should not be forwarded
|
||||
# if there's no route
|
||||
# for strict they should not be forwarded if they would be
|
||||
# forwarded thru that interface.
|
||||
#
|
||||
self.vapi.urpf_update(is_input=False,
|
||||
mode=e.vl_api_urpf_mode_t.URPF_API_MODE_LOOSE,
|
||||
af=e.vl_api_address_family_t.ADDRESS_IP4,
|
||||
sw_if_index=self.pg1.sw_if_index)
|
||||
|
||||
self.send_and_expect(self.pg0, p_good, self.pg1)
|
||||
self.send_and_expect(self.pg0, p_spoof_strict, self.pg1)
|
||||
self.send_and_assert_no_replies(self.pg0, p_spoof_loose)
|
||||
|
||||
self.assert_error_counter_equal("ip4-tx-urpf-loose", N_PKTS)
|
||||
|
||||
self.vapi.urpf_update(is_input=False,
|
||||
mode=e.vl_api_urpf_mode_t.URPF_API_MODE_STRICT,
|
||||
af=e.vl_api_address_family_t.ADDRESS_IP4,
|
||||
sw_if_index=self.pg1.sw_if_index)
|
||||
|
||||
self.send_and_expect(self.pg0, p_good, self.pg1)
|
||||
# the strict packet, from a peer is allowed, since it does
|
||||
# not forward via pg1
|
||||
self.send_and_expect(self.pg0, p_spoof_strict, self.pg1)
|
||||
self.send_and_assert_no_replies(self.pg0, p_spoof_loose)
|
||||
|
||||
self.assert_error_counter_equal("ip4-tx-urpf-strict", N_PKTS)
|
||||
|
||||
# change the strict packet so that it would forward through pg1
|
||||
p_spoof_strict = (Ether(dst=self.pg0.local_mac,
|
||||
src=self.pg0.remote_mac) /
|
||||
IP(src=self.pg1.remote_ip4,
|
||||
dst=self.pg1.remote_ip4) /
|
||||
UDP(sport=1234, dport=1234) /
|
||||
Raw(b'\xa5' * 100)) * N_PKTS
|
||||
|
||||
self.send_and_assert_no_replies(self.pg0, p_spoof_strict)
|
||||
self.assert_error_counter_equal("ip4-tx-urpf-strict", 2 * N_PKTS)
|
||||
|
||||
# cleanup
|
||||
self.vapi.urpf_update(is_input=False,
|
||||
mode=e.vl_api_urpf_mode_t.URPF_API_MODE_OFF,
|
||||
af=e.vl_api_address_family_t.ADDRESS_IP4,
|
||||
sw_if_index=self.pg1.sw_if_index)
|
||||
|
||||
def test_urpf6(self):
|
||||
""" uRPF IP6 """
|
||||
|
||||
e = VppEnum
|
||||
p_spoof_loose = (Ether(dst=self.pg0.local_mac,
|
||||
src=self.pg0.remote_mac) /
|
||||
IPv6(src="3::3", dst=self.pg1.remote_ip6) /
|
||||
UDP(sport=1236, dport=1236) /
|
||||
Raw(b'\xa5' * 100)) * N_PKTS
|
||||
p_spoof_strict = (Ether(dst=self.pg0.local_mac,
|
||||
src=self.pg0.remote_mac) /
|
||||
IPv6(src=self.pg2.remote_ip6,
|
||||
dst=self.pg1.remote_ip6) /
|
||||
UDP(sport=1236, dport=1236) /
|
||||
Raw(b'\xa5' * 100)) * N_PKTS
|
||||
p_good = (Ether(dst=self.pg0.local_mac,
|
||||
src=self.pg0.remote_mac) /
|
||||
IPv6(src=self.pg0.remote_ip6,
|
||||
dst=self.pg1.remote_ip6) /
|
||||
UDP(sport=1236, dport=1236) /
|
||||
Raw(b'\xa5' * 100)) * N_PKTS
|
||||
|
||||
#
|
||||
# before adding the uRPF, ensure all packets are forwarded
|
||||
#
|
||||
self.send_and_expect(self.pg0, p_good, self.pg1)
|
||||
self.send_and_expect(self.pg0, p_spoof_strict, self.pg1)
|
||||
self.send_and_expect(self.pg0, p_spoof_loose, self.pg1)
|
||||
|
||||
#
|
||||
# apply loose uRPF check on pg0 rx
|
||||
#
|
||||
self.vapi.urpf_update(is_input=True,
|
||||
mode=e.vl_api_urpf_mode_t.URPF_API_MODE_LOOSE,
|
||||
af=e.vl_api_address_family_t.ADDRESS_IP6,
|
||||
sw_if_index=self.pg0.sw_if_index)
|
||||
|
||||
# good packets still pass
|
||||
self.send_and_expect(self.pg0, p_good, self.pg1)
|
||||
# packets from address for which there is a route are forwarded
|
||||
self.send_and_expect(self.pg0, p_spoof_strict, self.pg1)
|
||||
# packets from address to which there is no route are dropped
|
||||
self.send_and_assert_no_replies(self.pg0, p_spoof_loose)
|
||||
|
||||
self.assert_error_counter_equal("ip6-rx-urpf-loose", N_PKTS)
|
||||
|
||||
#
|
||||
# crank it up to strict mode
|
||||
#
|
||||
self.vapi.urpf_update(is_input=True,
|
||||
mode=e.vl_api_urpf_mode_t.URPF_API_MODE_STRICT,
|
||||
af=e.vl_api_address_family_t.ADDRESS_IP6,
|
||||
sw_if_index=self.pg0.sw_if_index)
|
||||
|
||||
# good packets still pass
|
||||
self.send_and_expect(self.pg0, p_good, self.pg1)
|
||||
# packets that would not be routed back thru pg0 are dropped
|
||||
self.send_and_assert_no_replies(self.pg0, p_spoof_strict)
|
||||
self.send_and_assert_no_replies(self.pg0, p_spoof_loose)
|
||||
|
||||
self.assert_error_counter_equal("ip6-rx-urpf-strict", 2 * N_PKTS)
|
||||
|
||||
#
|
||||
# disable uRPF, all traffic should pass
|
||||
#
|
||||
self.vapi.urpf_update(is_input=True,
|
||||
mode=e.vl_api_urpf_mode_t.URPF_API_MODE_OFF,
|
||||
af=e.vl_api_address_family_t.ADDRESS_IP6,
|
||||
sw_if_index=self.pg0.sw_if_index)
|
||||
|
||||
self.send_and_expect(self.pg0, p_good, self.pg1)
|
||||
self.send_and_expect(self.pg0, p_spoof_strict, self.pg1)
|
||||
self.send_and_expect(self.pg0, p_spoof_loose, self.pg1)
|
||||
|
||||
#
|
||||
# Now apply in the TX direction
|
||||
# for loose it is the same deal, they should not be forwarded
|
||||
# if there's no route
|
||||
# for strict they should not be forwarded if they would be
|
||||
# forwarded thru that interface.
|
||||
#
|
||||
self.vapi.urpf_update(is_input=False,
|
||||
mode=e.vl_api_urpf_mode_t.URPF_API_MODE_LOOSE,
|
||||
af=e.vl_api_address_family_t.ADDRESS_IP6,
|
||||
sw_if_index=self.pg1.sw_if_index)
|
||||
|
||||
self.send_and_expect(self.pg0, p_good, self.pg1)
|
||||
self.send_and_expect(self.pg0, p_spoof_strict, self.pg1)
|
||||
self.send_and_assert_no_replies(self.pg0, p_spoof_loose)
|
||||
|
||||
self.assert_error_counter_equal("ip6-tx-urpf-loose", N_PKTS)
|
||||
|
||||
self.vapi.urpf_update(is_input=False,
|
||||
mode=e.vl_api_urpf_mode_t.URPF_API_MODE_STRICT,
|
||||
af=e.vl_api_address_family_t.ADDRESS_IP6,
|
||||
sw_if_index=self.pg1.sw_if_index)
|
||||
|
||||
self.send_and_expect(self.pg0, p_good, self.pg1)
|
||||
# the strict packet, from a peer is allowed, since it does
|
||||
# not forward via pg1
|
||||
self.send_and_expect(self.pg0, p_spoof_strict, self.pg1)
|
||||
self.send_and_assert_no_replies(self.pg0, p_spoof_loose)
|
||||
|
||||
self.assert_error_counter_equal("ip6-tx-urpf-strict", N_PKTS)
|
||||
|
||||
# change the strict packet so that it would forward through pg1
|
||||
p_spoof_strict = (Ether(dst=self.pg0.local_mac,
|
||||
src=self.pg0.remote_mac) /
|
||||
IPv6(src=self.pg1.remote_ip6,
|
||||
dst=self.pg1.remote_ip6) /
|
||||
UDP(sport=1236, dport=1236) /
|
||||
Raw(b'\xa5' * 100)) * N_PKTS
|
||||
|
||||
self.send_and_assert_no_replies(self.pg0, p_spoof_strict)
|
||||
self.assert_error_counter_equal("ip6-tx-urpf-strict", 2 * N_PKTS)
|
||||
|
||||
# cleanup
|
||||
self.vapi.urpf_update(is_input=False,
|
||||
mode=e.vl_api_urpf_mode_t.URPF_API_MODE_OFF,
|
||||
af=e.vl_api_address_family_t.ADDRESS_IP6,
|
||||
sw_if_index=self.pg1.sw_if_index)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(testRunner=VppTestRunner)
|
59
src/plugins/urpf/urpf.api
Normal file
59
src/plugins/urpf/urpf.api
Normal file
@ -0,0 +1,59 @@
|
||||
/* Hey Emacs use -*- mode: C -*- */
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
This file defines the vpp control-plane API messages
|
||||
used to control the URPF plugin
|
||||
*/
|
||||
|
||||
option version = "1.0.0";
|
||||
import "vnet/ip/ip_types.api";
|
||||
import "vnet/fib/fib_types.api";
|
||||
import "vnet/interface_types.api";
|
||||
|
||||
enum urpf_mode:u8
|
||||
{
|
||||
URPF_API_MODE_OFF,
|
||||
URPF_API_MODE_LOOSE,
|
||||
URPF_API_MODE_STRICT,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Enable uRPF on a given interface in a given direction
|
||||
* @param client_index - opaque cookie to identify the sender
|
||||
* @param context - sender context, to match reply w/ request
|
||||
* @param mode - Mode
|
||||
* @param af - Address Family
|
||||
* @param sw_if_index - Interface
|
||||
* @param is_input - Direction.
|
||||
*/
|
||||
autoreply define urpf_update
|
||||
{
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
bool is_input[default = true];
|
||||
vl_api_urpf_mode_t mode;
|
||||
vl_api_address_family_t af;
|
||||
vl_api_interface_index_t sw_if_index;
|
||||
};
|
||||
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
*
|
||||
* Local Variables:
|
||||
* eval: (c-set-style "gnu")
|
||||
* End:
|
||||
*/
|
323
src/plugins/urpf/urpf.c
Normal file
323
src/plugins/urpf/urpf.c
Normal file
File diff suppressed because it is too large
Load Diff
50
src/plugins/urpf/urpf.h
Normal file
50
src/plugins/urpf/urpf.h
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2020 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 __URPF_H__
|
||||
#define __URPF_H__
|
||||
|
||||
#include <vnet/ip/ip_types.h>
|
||||
|
||||
#define foreach_urpf_mode \
|
||||
_(OFF, "off") \
|
||||
_(LOOSE, "loose") \
|
||||
_(STRICT, "strict") \
|
||||
|
||||
typedef enum urpf_mode_t_
|
||||
{
|
||||
#define _(a,b) URPF_MODE_##a,
|
||||
foreach_urpf_mode
|
||||
#undef _
|
||||
} __clib_packed urpf_mode_t;
|
||||
|
||||
#define URPF_N_MODES (URPF_MODE_STRICT+1)
|
||||
|
||||
extern u8 *format_urpf_mode (u8 * s, va_list * a);
|
||||
|
||||
extern void urpf_update (urpf_mode_t mode,
|
||||
u32 sw_if_index,
|
||||
ip_address_family_t af, vlib_dir_t dir);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
*
|
||||
* Local Variables:
|
||||
* eval: (c-set-style "gnu")
|
||||
* End:
|
||||
*/
|
108
src/plugins/urpf/urpf_api.c
Normal file
108
src/plugins/urpf/urpf_api.c
Normal file
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <urpf/urpf.h>
|
||||
#include <vnet/plugin/plugin.h>
|
||||
#include <vnet/ip/ip_types_api.h>
|
||||
|
||||
#include <vpp/app/version.h>
|
||||
|
||||
#include <vlibapi/api.h>
|
||||
#include <vlibmemory/api.h>
|
||||
|
||||
/* define message IDs */
|
||||
#include <vnet/format_fns.h>
|
||||
#include <urpf/urpf.api_enum.h>
|
||||
#include <urpf/urpf.api_types.h>
|
||||
|
||||
/**
|
||||
* Base message ID fot the plugin
|
||||
*/
|
||||
static u32 urpf_base_msg_id;
|
||||
#define REPLY_MSG_ID_BASE urpf_base_msg_id
|
||||
|
||||
#include <vlibapi/api_helper_macros.h>
|
||||
|
||||
static int
|
||||
urpf_mode_decode (vl_api_urpf_mode_t in, urpf_mode_t * out)
|
||||
{
|
||||
if (0)
|
||||
;
|
||||
#define _(a,b) \
|
||||
else if (URPF_API_MODE_##a == in) \
|
||||
{ \
|
||||
*out = URPF_MODE_##a; \
|
||||
return (0); \
|
||||
}
|
||||
foreach_urpf_mode
|
||||
#undef _
|
||||
return (VNET_API_ERROR_INVALID_VALUE);
|
||||
}
|
||||
|
||||
static void
|
||||
vl_api_urpf_update_t_handler (vl_api_urpf_update_t * mp)
|
||||
{
|
||||
vl_api_urpf_update_reply_t *rmp;
|
||||
ip_address_family_t af;
|
||||
urpf_mode_t mode;
|
||||
int rv = 0;
|
||||
|
||||
VALIDATE_SW_IF_INDEX (mp);
|
||||
|
||||
rv = urpf_mode_decode (mp->mode, &mode);
|
||||
|
||||
if (rv)
|
||||
goto done;
|
||||
|
||||
rv = ip_address_family_decode (mp->af, &af);
|
||||
|
||||
if (rv)
|
||||
goto done;
|
||||
|
||||
urpf_update (mode, htonl (mp->sw_if_index), af,
|
||||
(mp->is_input ? VLIB_RX : VLIB_TX));
|
||||
|
||||
BAD_SW_IF_INDEX_LABEL;
|
||||
done:
|
||||
REPLY_MACRO (VL_API_URPF_UPDATE_REPLY);
|
||||
}
|
||||
|
||||
#include <urpf/urpf.api.c>
|
||||
|
||||
static clib_error_t *
|
||||
urpf_api_init (vlib_main_t * vm)
|
||||
{
|
||||
/* Ask for a correctly-sized block of API message decode slots */
|
||||
urpf_base_msg_id = setup_message_id_table ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
VLIB_INIT_FUNCTION (urpf_api_init);
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
VLIB_PLUGIN_REGISTER () = {
|
||||
.version = VPP_BUILD_VER,
|
||||
.description = "Unicast Reverse Path Forwarding (uRPF)",
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
*
|
||||
* Local Variables:
|
||||
* eval: (c-set-style "gnu")
|
||||
* End:
|
||||
*/
|
331
src/plugins/urpf/urpf_dp.h
Normal file
331
src/plugins/urpf/urpf_dp.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -440,7 +440,6 @@ list(APPEND VNET_SOURCES
|
||||
ip/ip4_mtrie.c
|
||||
ip/ip4_pg.c
|
||||
ip/ip4_source_and_port_range_check.c
|
||||
ip/ip4_source_check.c
|
||||
ip/reass/ip4_full_reass.c
|
||||
ip/reass/ip4_sv_reass.c
|
||||
ip/ip6_format.c
|
||||
@ -470,7 +469,6 @@ list(APPEND VNET_SOURCES
|
||||
)
|
||||
|
||||
list(APPEND VNET_MULTIARCH_SOURCES
|
||||
ip/ip4_source_check.c
|
||||
ip/ip4_punt_drop.c
|
||||
ip/reass/ip4_full_reass.c
|
||||
ip/ip6_hop_by_hop.c
|
||||
|
@ -172,6 +172,30 @@ ip4_fib_forwarding_lookup (u32 fib_index,
|
||||
return (ip4_fib_mtrie_leaf_get_adj_index(leaf));
|
||||
}
|
||||
|
||||
static_always_inline void
|
||||
ip4_fib_forwarding_lookup_x2 (u32 fib_index0,
|
||||
u32 fib_index1,
|
||||
const ip4_address_t * addr0,
|
||||
const ip4_address_t * addr1,
|
||||
index_t *lb0,
|
||||
index_t *lb1)
|
||||
{
|
||||
ip4_fib_mtrie_leaf_t leaf[2];
|
||||
ip4_fib_mtrie_t * mtrie[2];
|
||||
|
||||
mtrie[0] = &ip4_fib_get(fib_index0)->mtrie;
|
||||
mtrie[1] = &ip4_fib_get(fib_index1)->mtrie;
|
||||
|
||||
leaf[0] = ip4_fib_mtrie_lookup_step_one (mtrie[0], addr0);
|
||||
leaf[1] = ip4_fib_mtrie_lookup_step_one (mtrie[1], addr1);
|
||||
leaf[0] = ip4_fib_mtrie_lookup_step (mtrie[0], leaf[0], addr0, 2);
|
||||
leaf[1] = ip4_fib_mtrie_lookup_step (mtrie[1], leaf[1], addr1, 2);
|
||||
leaf[0] = ip4_fib_mtrie_lookup_step (mtrie[0], leaf[0], addr0, 3);
|
||||
leaf[1] = ip4_fib_mtrie_lookup_step (mtrie[1], leaf[1], addr1, 3);
|
||||
|
||||
*lb0 = ip4_fib_mtrie_leaf_get_adj_index(leaf[0]);
|
||||
*lb1 = ip4_fib_mtrie_leaf_get_adj_index(leaf[1]);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
88
src/vnet/interface_types_api.h
Normal file
88
src/vnet/interface_types_api.h
Normal file
@ -0,0 +1,88 @@
|
||||
/* Hey Emacs use -*- mode: C -*- */
|
||||
/*
|
||||
* Copyright (c) 2018 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.
|
||||
*/
|
||||
|
||||
typedef u32 interface_index;
|
||||
|
||||
enum if_status_flags
|
||||
{
|
||||
IF_STATUS_API_FLAG_ADMIN_UP = 1,
|
||||
IF_STATUS_API_FLAG_LINK_UP = 2,
|
||||
};
|
||||
|
||||
/* Per protocol MTU */
|
||||
enum mtu_proto
|
||||
{
|
||||
MTU_PROTO_API_L3, /* Default payload MTU (without L2 headers) */
|
||||
MTU_PROTO_API_IP4, /* Per-protocol MTUs overriding default */
|
||||
MTU_PROTO_API_IP6,
|
||||
MTU_PROTO_API_MPLS,
|
||||
MTU_PROTO_API_N,
|
||||
};
|
||||
|
||||
enum link_duplex
|
||||
{
|
||||
LINK_DUPLEX_API_UNKNOWN = 0,
|
||||
LINK_DUPLEX_API_HALF = 1,
|
||||
LINK_DUPLEX_API_FULL = 2,
|
||||
};
|
||||
|
||||
enum sub_if_flags
|
||||
{
|
||||
SUB_IF_API_FLAG_NO_TAGS = 1,
|
||||
SUB_IF_API_FLAG_ONE_TAG = 2,
|
||||
SUB_IF_API_FLAG_TWO_TAGS = 4,
|
||||
SUB_IF_API_FLAG_DOT1AD = 8,
|
||||
SUB_IF_API_FLAG_EXACT_MATCH = 16,
|
||||
SUB_IF_API_FLAG_DEFAULT = 32,
|
||||
SUB_IF_API_FLAG_OUTER_VLAN_ID_ANY = 64,
|
||||
SUB_IF_API_FLAG_INNER_VLAN_ID_ANY = 128,
|
||||
SUB_IF_API_FLAG_MASK_VNET = 254, /* use with vnet_sub_interface_t raw_flags */
|
||||
SUB_IF_API_FLAG_DOT1AH = 256,
|
||||
};
|
||||
|
||||
enum rx_mode
|
||||
{
|
||||
RX_MODE_API_UNKNOWN = 0,
|
||||
RX_MODE_API_POLLING,
|
||||
RX_MODE_API_INTERRUPT,
|
||||
RX_MODE_API_ADAPTIVE,
|
||||
RX_MODE_API_DEFAULT,
|
||||
};
|
||||
|
||||
enum if_type
|
||||
{
|
||||
/* A hw interface. */
|
||||
IF_API_TYPE_HARDWARE,
|
||||
|
||||
/* A sub-interface. */
|
||||
IF_API_TYPE_SUB,
|
||||
IF_API_TYPE_P2P,
|
||||
IF_API_TYPE_PIPE,
|
||||
};
|
||||
|
||||
enum direction:u8
|
||||
{
|
||||
DIRECTION_RX,
|
||||
DIRECTION_TX,
|
||||
};
|
||||
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
*
|
||||
* Local Variables:
|
||||
* eval: (c-set-style "gnu")
|
||||
* End:
|
||||
*/
|
@ -509,22 +509,6 @@ autoreply define ip_source_and_port_range_check_interface_add_del
|
||||
u32 udp_out_vrf_id;
|
||||
};
|
||||
|
||||
/** \brief Set interface source check request
|
||||
@param client_index - opaque cookie to identify the sender
|
||||
@param context - sender context, to match reply w/ request
|
||||
@param is_add - add or del
|
||||
@param loose - strict or loose
|
||||
@param sw_if_index - interface index
|
||||
*/
|
||||
autoreply define ip_source_check_interface_add_del
|
||||
{
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
bool is_add [default=true];
|
||||
bool loose;
|
||||
vl_api_interface_index_t sw_if_index;
|
||||
};
|
||||
|
||||
/** \brief IPv6 set link local address on interface request
|
||||
@param client_index - opaque cookie to identify the sender
|
||||
@param context - sender context, to match reply w/ request
|
||||
|
@ -67,9 +67,6 @@
|
||||
_ (UDP_CHECKSUM, "bad udp checksum") \
|
||||
_ (UDP_LENGTH, "inconsistent udp/ip lengths") \
|
||||
\
|
||||
/* Errors signalled by ip4-source-check. */ \
|
||||
_ (UNICAST_SOURCE_CHECK_FAILS, "ip4 unicast source check fails") \
|
||||
\
|
||||
/* Spoofed packets in ip4-rewrite-local */ \
|
||||
_ (SPOOFED_LOCAL_PACKETS, "ip4 spoofed local-address packet drops") \
|
||||
\
|
||||
|
@ -903,20 +903,6 @@ VNET_FEATURE_INIT (ip4_inacl, static) =
|
||||
{
|
||||
.arc_name = "ip4-unicast",
|
||||
.node_name = "ip4-inacl",
|
||||
.runs_before = VNET_FEATURES ("ip4-source-check-via-rx"),
|
||||
};
|
||||
|
||||
VNET_FEATURE_INIT (ip4_source_check_1, static) =
|
||||
{
|
||||
.arc_name = "ip4-unicast",
|
||||
.node_name = "ip4-source-check-via-rx",
|
||||
.runs_before = VNET_FEATURES ("ip4-source-check-via-any"),
|
||||
};
|
||||
|
||||
VNET_FEATURE_INIT (ip4_source_check_2, static) =
|
||||
{
|
||||
.arc_name = "ip4-unicast",
|
||||
.node_name = "ip4-source-check-via-any",
|
||||
.runs_before = VNET_FEATURES ("ip4-policer-classify"),
|
||||
};
|
||||
|
||||
|
@ -436,9 +436,6 @@ ip4_init (vlib_main_t * vm)
|
||||
if ((error = vlib_call_init_function (vm, ip4_cli_init)))
|
||||
return error;
|
||||
|
||||
if ((error = vlib_call_init_function (vm, ip4_source_check_init)))
|
||||
return error;
|
||||
|
||||
if ((error = vlib_call_init_function
|
||||
(vm, ip4_source_and_port_range_check_init)))
|
||||
return error;
|
||||
|
@ -384,6 +384,12 @@ ip4_address_is_multicast (const ip4_address_t * a)
|
||||
return (a->data[0] & 0xf0) == 0xe0;
|
||||
}
|
||||
|
||||
always_inline uword
|
||||
ip4_address_is_global_broadcast (const ip4_address_t * a)
|
||||
{
|
||||
return (a->as_u32) == 0xffffffff;
|
||||
}
|
||||
|
||||
always_inline void
|
||||
ip4_multicast_address_set_for_group (ip4_address_t * a,
|
||||
ip_multicast_group_t g)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -94,8 +94,6 @@ _(IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL, \
|
||||
ip_source_and_port_range_check_add_del) \
|
||||
_(IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL, \
|
||||
ip_source_and_port_range_check_interface_add_del) \
|
||||
_(IP_SOURCE_CHECK_INTERFACE_ADD_DEL, \
|
||||
ip_source_check_interface_add_del) \
|
||||
_(SW_INTERFACE_IP6_SET_LINK_LOCAL_ADDRESS, \
|
||||
sw_interface_ip6_set_link_local_address) \
|
||||
_(IP_REASSEMBLY_SET, ip_reassembly_set) \
|
||||
@ -1270,37 +1268,6 @@ static void
|
||||
REPLY_MACRO (VL_API_SW_INTERFACE_IP6_SET_LINK_LOCAL_ADDRESS_REPLY);
|
||||
}
|
||||
|
||||
typedef union
|
||||
{
|
||||
u32 fib_index;
|
||||
} ip4_source_check_config_t;
|
||||
|
||||
static void
|
||||
vl_api_ip_source_check_interface_add_del_t_handler
|
||||
(vl_api_ip_source_check_interface_add_del_t * mp)
|
||||
{
|
||||
vl_api_ip_source_check_interface_add_del_reply_t *rmp;
|
||||
int rv;
|
||||
u32 sw_if_index = ntohl (mp->sw_if_index);
|
||||
u8 is_add = mp->is_add;
|
||||
char *feature_name =
|
||||
mp->loose ? "ip4-source-check-via-any" : "ip4-source-check-via-rx";
|
||||
|
||||
ip4_source_check_config_t config;
|
||||
|
||||
VALIDATE_SW_IF_INDEX (mp);
|
||||
|
||||
config.fib_index =
|
||||
fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4, sw_if_index);
|
||||
rv =
|
||||
vnet_feature_enable_disable ("ip4-unicast", feature_name, sw_if_index,
|
||||
is_add, &config, sizeof (config));
|
||||
BAD_SW_IF_INDEX_LABEL;
|
||||
|
||||
REPLY_MACRO (VL_API_IP_SOURCE_CHECK_INTERFACE_ADD_DEL_REPLY);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
vl_api_ip_table_replace_begin_t_handler (vl_api_ip_table_replace_begin_t * mp)
|
||||
{
|
||||
|
Reference in New Issue
Block a user