IP Multicast FIB (mfib)
- IPv[46] mfib tables with support for (*,G/m), (*,G) and (S,G) exact and longest prefix match - Replication represented via a new replicate DPO. - RPF configuration and data-plane checking - data-plane signals sent to listening control planes. The functions of multicast forwarding entries differ from their unicast conterparts, so we introduce a new mfib_table_t and mfib_entry_t objects. However, we re-use the fib_path_list to resolve and build the entry's output list. the fib_path_list provides the service to construct a replicate DPO for multicast. 'make tests' is added to with two new suites; TEST=mfib, this is invocation of the CLI command 'test mfib' which deals with many path add/remove, flag set/unset scenarios, TEST=ip-mcast, data-plane forwarding tests. Updated applications to use the new MIFB functions; - IPv6 NS/RA. - DHCPv6 unit tests for these are undated accordingly. Change-Id: I49ec37b01f1b170335a5697541c8fd30e6d3a961 Signed-off-by: Neale Ranns <nranns@cisco.com>
This commit is contained in:
committed by
Damjan Marion
parent
6f692d6e5a
commit
32e1c010b0
@@ -0,0 +1,22 @@
|
||||
packet-generator new {
|
||||
name x
|
||||
limit 1
|
||||
node ip4-input
|
||||
size 64-64
|
||||
no-recycle
|
||||
data {
|
||||
ICMP: 1.0.0.2 -> 232.1.1.1
|
||||
ICMP echo_request
|
||||
incrementing 100
|
||||
}
|
||||
}
|
||||
|
||||
trace add pg-input 100
|
||||
loop create
|
||||
loop create
|
||||
set int state loop0 up
|
||||
set int state loop1 up
|
||||
|
||||
ip mroute add 232.1.1.1 via pg0 Accept
|
||||
ip mroute add 232.1.1.1 via loop0 Forward
|
||||
ip mroute add 232.1.1.1 via loop1 Forward
|
||||
@@ -48,6 +48,7 @@
|
||||
#include <vnet/span/span.h>
|
||||
#include <vnet/policer/policer.h>
|
||||
#include <vnet/policer/police.h>
|
||||
#include <vnet/mfib/mfib_types.h>
|
||||
|
||||
#include "vat/json_format.h"
|
||||
|
||||
@@ -505,6 +506,53 @@ unformat_flow_classify_table_type (unformat_input_t * input, va_list * va)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const char *mfib_flag_names[] = MFIB_ENTRY_NAMES_SHORT;
|
||||
static const char *mfib_flag_long_names[] = MFIB_ENTRY_NAMES_LONG;
|
||||
static const char *mfib_itf_flag_long_names[] = MFIB_ITF_NAMES_LONG;
|
||||
static const char *mfib_itf_flag_names[] = MFIB_ITF_NAMES_SHORT;
|
||||
|
||||
uword
|
||||
unformat_mfib_itf_flags (unformat_input_t * input, va_list * args)
|
||||
{
|
||||
mfib_itf_flags_t old, *iflags = va_arg (*args, mfib_itf_flags_t *);
|
||||
mfib_itf_attribute_t attr;
|
||||
|
||||
old = *iflags;
|
||||
FOR_EACH_MFIB_ITF_ATTRIBUTE (attr)
|
||||
{
|
||||
if (unformat (input, mfib_itf_flag_long_names[attr]))
|
||||
*iflags |= (1 << attr);
|
||||
}
|
||||
FOR_EACH_MFIB_ITF_ATTRIBUTE (attr)
|
||||
{
|
||||
if (unformat (input, mfib_itf_flag_names[attr]))
|
||||
*iflags |= (1 << attr);
|
||||
}
|
||||
|
||||
return (old == *iflags ? 0 : 1);
|
||||
}
|
||||
|
||||
uword
|
||||
unformat_mfib_entry_flags (unformat_input_t * input, va_list * args)
|
||||
{
|
||||
mfib_entry_flags_t old, *eflags = va_arg (*args, mfib_entry_flags_t *);
|
||||
mfib_entry_attribute_t attr;
|
||||
|
||||
old = *eflags;
|
||||
FOR_EACH_MFIB_ATTRIBUTE (attr)
|
||||
{
|
||||
if (unformat (input, mfib_flag_long_names[attr]))
|
||||
*eflags |= (1 << attr);
|
||||
}
|
||||
FOR_EACH_MFIB_ATTRIBUTE (attr)
|
||||
{
|
||||
if (unformat (input, mfib_flag_names[attr]))
|
||||
*eflags |= (1 << attr);
|
||||
}
|
||||
|
||||
return (old == *eflags ? 0 : 1);
|
||||
}
|
||||
|
||||
#if (VPP_API_TEST_BUILTIN==0)
|
||||
u8 *
|
||||
format_ip4_address (u8 * s, va_list * args)
|
||||
@@ -3592,6 +3640,7 @@ _(bridge_domain_add_del_reply) \
|
||||
_(sw_interface_set_l2_xconnect_reply) \
|
||||
_(l2fib_add_del_reply) \
|
||||
_(ip_add_del_route_reply) \
|
||||
_(ip_mroute_add_del_reply) \
|
||||
_(mpls_route_add_del_reply) \
|
||||
_(mpls_ip_bind_unbind_reply) \
|
||||
_(proxy_arp_add_del_reply) \
|
||||
@@ -3792,6 +3841,7 @@ _(TAP_MODIFY_REPLY, tap_modify_reply) \
|
||||
_(TAP_DELETE_REPLY, tap_delete_reply) \
|
||||
_(SW_INTERFACE_TAP_DETAILS, sw_interface_tap_details) \
|
||||
_(IP_ADD_DEL_ROUTE_REPLY, ip_add_del_route_reply) \
|
||||
_(IP_MROUTE_ADD_DEL_REPLY, ip_mroute_add_del_reply) \
|
||||
_(MPLS_ROUTE_ADD_DEL_REPLY, mpls_route_add_del_reply) \
|
||||
_(MPLS_IP_BIND_UNBIND_REPLY, mpls_ip_bind_unbind_reply) \
|
||||
_(PROXY_ARP_ADD_DEL_REPLY, proxy_arp_add_del_reply) \
|
||||
@@ -6383,6 +6433,126 @@ api_ip_add_del_route (vat_main_t * vam)
|
||||
return (vam->retval);
|
||||
}
|
||||
|
||||
static int
|
||||
api_ip_mroute_add_del (vat_main_t * vam)
|
||||
{
|
||||
unformat_input_t *i = vam->input;
|
||||
vl_api_ip_mroute_add_del_t *mp;
|
||||
f64 timeout;
|
||||
u32 sw_if_index = ~0, vrf_id = 0;
|
||||
u8 is_ipv6 = 0;
|
||||
u8 is_local = 0;
|
||||
u8 create_vrf_if_needed = 0;
|
||||
u8 is_add = 1;
|
||||
u8 address_set = 0;
|
||||
u32 grp_address_length = 0;
|
||||
ip4_address_t v4_grp_address, v4_src_address;
|
||||
ip6_address_t v6_grp_address, v6_src_address;
|
||||
mfib_itf_flags_t iflags = 0;
|
||||
mfib_entry_flags_t eflags = 0;
|
||||
|
||||
/* Parse args required to build the message */
|
||||
while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
|
||||
{
|
||||
if (unformat (i, "sw_if_index %d", &sw_if_index))
|
||||
;
|
||||
else if (unformat (i, "%U %U",
|
||||
unformat_ip4_address, &v4_src_address,
|
||||
unformat_ip4_address, &v4_grp_address))
|
||||
{
|
||||
grp_address_length = 64;
|
||||
address_set = 1;
|
||||
is_ipv6 = 0;
|
||||
}
|
||||
else if (unformat (i, "%U %U",
|
||||
unformat_ip6_address, &v6_src_address,
|
||||
unformat_ip6_address, &v6_grp_address))
|
||||
{
|
||||
grp_address_length = 256;
|
||||
address_set = 1;
|
||||
is_ipv6 = 1;
|
||||
}
|
||||
else if (unformat (i, "%U", unformat_ip4_address, &v4_grp_address))
|
||||
{
|
||||
memset (&v4_src_address, 0, sizeof (v4_src_address));
|
||||
grp_address_length = 32;
|
||||
address_set = 1;
|
||||
is_ipv6 = 0;
|
||||
}
|
||||
else if (unformat (i, "%U", unformat_ip6_address, &v6_grp_address))
|
||||
{
|
||||
memset (&v6_src_address, 0, sizeof (v6_src_address));
|
||||
grp_address_length = 128;
|
||||
address_set = 1;
|
||||
is_ipv6 = 1;
|
||||
}
|
||||
else if (unformat (i, "/%d", &grp_address_length))
|
||||
;
|
||||
else if (unformat (i, "local"))
|
||||
{
|
||||
is_local = 1;
|
||||
}
|
||||
else if (unformat (i, "del"))
|
||||
is_add = 0;
|
||||
else if (unformat (i, "add"))
|
||||
is_add = 1;
|
||||
else if (unformat (i, "vrf %d", &vrf_id))
|
||||
;
|
||||
else if (unformat (i, "create-vrf"))
|
||||
create_vrf_if_needed = 1;
|
||||
else if (unformat (i, "%U", unformat_mfib_itf_flags, &iflags))
|
||||
;
|
||||
else if (unformat (i, "%U", unformat_mfib_entry_flags, &eflags))
|
||||
;
|
||||
else
|
||||
{
|
||||
clib_warning ("parse error '%U'", format_unformat_error, i);
|
||||
return -99;
|
||||
}
|
||||
}
|
||||
|
||||
if (address_set == 0)
|
||||
{
|
||||
errmsg ("missing addresses\n");
|
||||
return -99;
|
||||
}
|
||||
|
||||
/* Construct the API message */
|
||||
M (IP_MROUTE_ADD_DEL, ip_mroute_add_del);
|
||||
|
||||
mp->next_hop_sw_if_index = ntohl (sw_if_index);
|
||||
mp->table_id = ntohl (vrf_id);
|
||||
mp->create_vrf_if_needed = create_vrf_if_needed;
|
||||
|
||||
mp->is_add = is_add;
|
||||
mp->is_ipv6 = is_ipv6;
|
||||
mp->is_local = is_local;
|
||||
mp->itf_flags = ntohl (iflags);
|
||||
mp->entry_flags = ntohl (eflags);
|
||||
mp->grp_address_length = grp_address_length;
|
||||
mp->grp_address_length = ntohs (mp->grp_address_length);
|
||||
|
||||
if (is_ipv6)
|
||||
{
|
||||
clib_memcpy (mp->grp_address, &v6_grp_address, sizeof (v6_grp_address));
|
||||
clib_memcpy (mp->src_address, &v6_src_address, sizeof (v6_src_address));
|
||||
}
|
||||
else
|
||||
{
|
||||
clib_memcpy (mp->grp_address, &v4_grp_address, sizeof (v4_grp_address));
|
||||
clib_memcpy (mp->src_address, &v4_src_address, sizeof (v4_src_address));
|
||||
|
||||
}
|
||||
|
||||
/* send it... */
|
||||
S;
|
||||
/* Wait for a reply... */
|
||||
W;
|
||||
|
||||
/* Return the good/bad news */
|
||||
return (vam->retval);
|
||||
}
|
||||
|
||||
static int
|
||||
api_mpls_route_add_del (vat_main_t * vam)
|
||||
{
|
||||
@@ -17512,6 +17682,9 @@ _(ip_add_del_route, \
|
||||
"[<intfc> | sw_if_index <id>] [resolve-attempts <n>]\n" \
|
||||
"[weight <n>] [drop] [local] [classify <n>] [del]\n" \
|
||||
"[multipath] [count <n>]") \
|
||||
_(ip_mroute_add_del, \
|
||||
"<src> <grp>/<mask> [table-id <n>]\n" \
|
||||
"[<intfc> | sw_if_index <id>] [local] [del]") \
|
||||
_(mpls_route_add_del, \
|
||||
"<label> <eos> via <addr> [table-id <n>]\n" \
|
||||
"[<intfc> | sw_if_index <id>] [resolve-attempts <n>]\n" \
|
||||
|
||||
+31
-4
@@ -946,16 +946,15 @@ nobase_include_HEADERS += \
|
||||
|
||||
libvnet_la_SOURCES += \
|
||||
vnet/adj/adj_nbr.c \
|
||||
vnet/adj/adj_rewrite.c \
|
||||
vnet/adj/adj_glean.c \
|
||||
vnet/adj/adj_midchain.c \
|
||||
vnet/adj/adj_mcast.c \
|
||||
vnet/adj/adj_l2.c \
|
||||
vnet/adj/adj.c
|
||||
|
||||
nobase_include_HEADERS += \
|
||||
vnet/adj/adj.h \
|
||||
vnet/adj/adj_types.h \
|
||||
vnet/adj/adj_rewrite.h \
|
||||
vnet/adj/adj_glean.h \
|
||||
vnet/adj/adj_nbr.h
|
||||
|
||||
@@ -971,8 +970,9 @@ libvnet_la_SOURCES += \
|
||||
vnet/dpo/receive_dpo.c \
|
||||
vnet/dpo/load_balance.c \
|
||||
vnet/dpo/load_balance_map.c \
|
||||
vnet/dpo/lookup_dpo.c \
|
||||
vnet/dpo/classify_dpo.c \
|
||||
vnet/dpo/lookup_dpo.c \
|
||||
vnet/dpo/classify_dpo.c \
|
||||
vnet/dpo/replicate_dpo.c \
|
||||
vnet/dpo/mpls_label_dpo.c
|
||||
|
||||
nobase_include_HEADERS += \
|
||||
@@ -985,6 +985,33 @@ nobase_include_HEADERS += \
|
||||
vnet/dpo/ip_null_dpo.h \
|
||||
vnet/dpo/dpo.h
|
||||
|
||||
########################################
|
||||
# Multicast FIB
|
||||
########################################
|
||||
|
||||
libvnet_la_SOURCES += \
|
||||
vnet/mfib/mfib_test.c \
|
||||
vnet/mfib/mfib_forward.c \
|
||||
vnet/mfib/ip4_mfib.c \
|
||||
vnet/mfib/ip6_mfib.c \
|
||||
vnet/mfib/mfib_types.c \
|
||||
vnet/mfib/mfib_signal.c \
|
||||
vnet/mfib/mfib_itf.c \
|
||||
vnet/mfib/mfib_entry.c \
|
||||
vnet/mfib/mfib_table.c
|
||||
|
||||
nobase_include_HEADERS += \
|
||||
vnet/mfib/ip4_mfib.h \
|
||||
vnet/mfib/mfib_types.h \
|
||||
vnet/mfib/mfib_table.h
|
||||
|
||||
########################################
|
||||
# Utilities
|
||||
########################################
|
||||
|
||||
libvnet_la_SOURCES += \
|
||||
vnet/util/radix.c
|
||||
|
||||
########################################
|
||||
# Plugin client library
|
||||
########################################
|
||||
|
||||
+9
-2
@@ -17,6 +17,7 @@
|
||||
#include <vnet/adj/adj_internal.h>
|
||||
#include <vnet/adj/adj_glean.h>
|
||||
#include <vnet/adj/adj_midchain.h>
|
||||
#include <vnet/adj/adj_mcast.h>
|
||||
#include <vnet/fib/fib_node_list.h>
|
||||
|
||||
/*
|
||||
@@ -58,8 +59,6 @@ adj_alloc (fib_protocol_t proto)
|
||||
adj_get_index(adj));
|
||||
|
||||
adj->rewrite_header.sw_if_index = ~0;
|
||||
adj->mcast_group_index = ~0;
|
||||
adj->saved_lookup_next_index = 0;
|
||||
adj->n_adj = 1;
|
||||
adj->lookup_next_index = 0;
|
||||
|
||||
@@ -116,6 +115,9 @@ format_ip_adjacency (u8 * s, va_list * args)
|
||||
case IP_LOOKUP_NEXT_MIDCHAIN:
|
||||
s = format (s, "%U", format_adj_midchain, adj_index, 2);
|
||||
break;
|
||||
case IP_LOOKUP_NEXT_MCAST:
|
||||
s = format (s, "%U", format_adj_mcast, adj_index, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -179,6 +181,10 @@ adj_last_lock_gone (ip_adjacency_t *adj)
|
||||
adj_glean_remove(adj->ia_nh_proto,
|
||||
adj->rewrite_header.sw_if_index);
|
||||
break;
|
||||
case IP_LOOKUP_NEXT_MCAST:
|
||||
adj_mcast_remove(adj->ia_nh_proto,
|
||||
adj->rewrite_header.sw_if_index);
|
||||
break;
|
||||
default:
|
||||
/*
|
||||
* type not stored in any DB from which we need to remove it
|
||||
@@ -350,6 +356,7 @@ adj_module_init (vlib_main_t * vm)
|
||||
adj_nbr_module_init();
|
||||
adj_glean_module_init();
|
||||
adj_midchain_module_init();
|
||||
adj_mcast_module_init();
|
||||
|
||||
/*
|
||||
* one special adj to reserve index 0
|
||||
|
||||
@@ -45,7 +45,6 @@
|
||||
#include <vnet/ip/lookup.h>
|
||||
#include <vnet/adj/adj_types.h>
|
||||
#include <vnet/adj/adj_nbr.h>
|
||||
#include <vnet/adj/adj_rewrite.h>
|
||||
#include <vnet/adj/adj_glean.h>
|
||||
|
||||
/**
|
||||
|
||||
@@ -100,5 +100,7 @@ extern void adj_nbr_remove(adj_index_t ai,
|
||||
u32 sw_if_index);
|
||||
extern void adj_glean_remove(fib_protocol_t proto,
|
||||
u32 sw_if_index);
|
||||
extern void adj_mcast_remove(fib_protocol_t proto,
|
||||
u32 sw_if_index);
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Mcast Adjacency
|
||||
*
|
||||
* The multicast adjacency forwards IP traffic on an interface toward a multicast
|
||||
* group address. This is a different type of adjacency to a unicast adjacency
|
||||
* since the application of the MAC header is different, and so the VLIB node
|
||||
* visited is also different. DPO types have different VLIB nodes.
|
||||
*/
|
||||
|
||||
#ifndef __ADJ_MCAST_H__
|
||||
#define __ADJ_MCAST_H__
|
||||
|
||||
#include <vnet/adj/adj_types.h>
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* Add (and lock) a new or lock an existing mcast adjacency
|
||||
*
|
||||
* @param proto
|
||||
* The protocol for the neighbours that we wish to mcast
|
||||
*
|
||||
* @param link_type
|
||||
* A description of the protocol of the packets that will forward
|
||||
* through this adj. On an ethernet interface this is the MAC header's
|
||||
* ether-type
|
||||
*
|
||||
* @param sw_if_index
|
||||
* The interface on which to mcast
|
||||
*/
|
||||
extern adj_index_t adj_mcast_add_or_lock(fib_protocol_t proto,
|
||||
vnet_link_t link_type,
|
||||
u32 sw_if_index);
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* Update the rewrite string for an existing adjacecny.
|
||||
*
|
||||
* @param
|
||||
* The index of the adj to update
|
||||
*
|
||||
* @param
|
||||
* The new rewrite
|
||||
*/
|
||||
extern void adj_mcast_update_rewrite(adj_index_t adj_index,
|
||||
u8 *rewrite);
|
||||
|
||||
/**
|
||||
* @brief Format/display a mcast adjacency.
|
||||
*/
|
||||
extern u8* format_adj_mcast(u8* s, va_list *ap);
|
||||
|
||||
/**
|
||||
* @brief Get the sze of the mcast adj DB. Test purposes only.
|
||||
*/
|
||||
extern u32 adj_mcast_db_size(void);
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* Module initialisation
|
||||
*/
|
||||
extern void adj_mcast_module_init(void);
|
||||
|
||||
#endif
|
||||
@@ -162,7 +162,7 @@ adj_nbr_alloc (fib_protocol_t nh_proto,
|
||||
}
|
||||
|
||||
/*
|
||||
* adj_add_for_nbr
|
||||
* adj_nbr_add_or_lock
|
||||
*
|
||||
* Add an adjacency for the neighbour requested.
|
||||
*
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
* 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 <vnet/adj/adj.h>
|
||||
#include <vnet/adj/adj_internal.h>
|
||||
|
||||
/**
|
||||
* adj_rewrite_add_and_lock
|
||||
*
|
||||
* A rewrite sub-type has the rewrite string provided, but no key
|
||||
*/
|
||||
adj_index_t
|
||||
adj_rewrite_add_and_lock (fib_protocol_t nh_proto,
|
||||
vnet_link_t link_type,
|
||||
u32 sw_if_index,
|
||||
u8 *rewrite)
|
||||
{
|
||||
ip_adjacency_t *adj;
|
||||
|
||||
adj = adj_alloc(nh_proto);
|
||||
|
||||
adj->lookup_next_index = IP_LOOKUP_NEXT_REWRITE;
|
||||
memset(&adj->sub_type.nbr.next_hop, 0, sizeof(adj->sub_type.nbr.next_hop));
|
||||
adj->ia_link = link_type;
|
||||
adj->ia_nh_proto = nh_proto;
|
||||
adj->rewrite_header.sw_if_index = sw_if_index;
|
||||
|
||||
ASSERT(NULL != rewrite);
|
||||
|
||||
vnet_rewrite_for_sw_interface(vnet_get_main(),
|
||||
link_type,
|
||||
adj->rewrite_header.sw_if_index,
|
||||
adj_get_rewrite_node(link_type),
|
||||
rewrite,
|
||||
&adj->rewrite_header,
|
||||
sizeof (adj->rewrite_data));
|
||||
|
||||
adj_lock(adj_get_index(adj));
|
||||
|
||||
return (adj_get_index(adj));
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
/**
|
||||
* @brief
|
||||
* A rewrite adjacency has no key, and thus cannot be 'found' from the
|
||||
* FIB resolution code. the client therefore needs to maange these adjacencies
|
||||
*/
|
||||
|
||||
#ifndef __ADJ_REWRITE_H__
|
||||
#define __ADJ_REWRITE_H__
|
||||
|
||||
#include <vnet/adj/adj_types.h>
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* Add (and lock) a new or lock an existing neighbour adjacency
|
||||
*
|
||||
* @param nh_proto
|
||||
* The protocol for the next-hop address (v4 or v6)
|
||||
*
|
||||
* @param link_type
|
||||
* A description of the protocol of the packets that will forward
|
||||
* through this adj. On an ethernet interface this is the MAC header's
|
||||
* ether-type
|
||||
*
|
||||
* @param sw_if_index
|
||||
* The interface on which the peer resides
|
||||
*
|
||||
* @param rewrite
|
||||
* The rewrite to prepend to packets
|
||||
*/
|
||||
extern adj_index_t adj_rewrite_add_and_lock(fib_protocol_t nh_proto,
|
||||
vnet_link_t link_type,
|
||||
u32 sw_if_index,
|
||||
u8 *rewrite);
|
||||
|
||||
#endif
|
||||
@@ -19,6 +19,8 @@
|
||||
#include <vnet/pg/pg.h>
|
||||
#include <vnet/dhcpv6/proxy.h>
|
||||
#include <vnet/fib/ip6_fib.h>
|
||||
#include <vnet/mfib/mfib_table.h>
|
||||
#include <vnet/mfib/ip6_mfib.h>
|
||||
|
||||
static char * dhcpv6_proxy_error_strings[] = {
|
||||
#define dhcpv6_proxy_error(n,s) s,
|
||||
@@ -819,7 +821,7 @@ int dhcpv6_proxy_set_server_2 (ip6_address_t *addr, ip6_address_t *src_address,
|
||||
u32 server_fib_index = 0;
|
||||
u32 rx_fib_index = 0;
|
||||
|
||||
rx_fib_index = ip6_fib_table_find_or_create_and_lock(rx_fib_id);
|
||||
rx_fib_index = ip6_mfib_table_find_or_create_and_lock(rx_fib_id);
|
||||
server_fib_index = ip6_fib_table_find_or_create_and_lock(server_fib_id);
|
||||
|
||||
if (is_del)
|
||||
@@ -848,8 +850,10 @@ int dhcpv6_proxy_set_server_2 (ip6_address_t *addr, ip6_address_t *src_address,
|
||||
if (rx_fib_id == 0)
|
||||
{
|
||||
server = pool_elt_at_index (dm->dhcp6_servers, 0);
|
||||
|
||||
goto initialize_it;
|
||||
if (server->valid)
|
||||
goto reconfigure_it;
|
||||
else
|
||||
goto initialize_it;
|
||||
}
|
||||
|
||||
if (rx_fib_index < vec_len(dm->dhcp6_server_index_by_rx_fib_index))
|
||||
@@ -866,6 +870,42 @@ int dhcpv6_proxy_set_server_2 (ip6_address_t *addr, ip6_address_t *src_address,
|
||||
pool_get (dm->dhcp6_servers, server);
|
||||
|
||||
initialize_it:
|
||||
{
|
||||
const mfib_prefix_t all_dhcp_servers = {
|
||||
.fp_len = 128,
|
||||
.fp_proto = FIB_PROTOCOL_IP6,
|
||||
.fp_grp_addr = {
|
||||
.ip6 = dm->all_dhcpv6_server_relay_agent_address,
|
||||
}
|
||||
};
|
||||
const fib_route_path_t path_for_us = {
|
||||
.frp_proto = FIB_PROTOCOL_IP6,
|
||||
.frp_addr = zero_addr,
|
||||
.frp_sw_if_index = 0xffffffff,
|
||||
.frp_fib_index = ~0,
|
||||
.frp_weight = 0,
|
||||
.frp_flags = FIB_ROUTE_PATH_LOCAL,
|
||||
};
|
||||
mfib_table_entry_path_update(rx_fib_index,
|
||||
&all_dhcp_servers,
|
||||
MFIB_SOURCE_DHCP,
|
||||
&path_for_us,
|
||||
MFIB_ITF_FLAG_FORWARD);
|
||||
/*
|
||||
* Each interface that is enabled in this table, needs to be added
|
||||
* as an accepting interface, but this is not easily doable in VPP.
|
||||
* So we cheat. Add a flag to the entry that indicates accept form
|
||||
* any interface.
|
||||
* We will still only accept on v6 enabled interfaces, since the input
|
||||
* feature ensures this.
|
||||
*/
|
||||
mfib_table_entry_update(rx_fib_index,
|
||||
&all_dhcp_servers,
|
||||
MFIB_SOURCE_DHCP,
|
||||
MFIB_ENTRY_FLAG_ACCEPT_ALL_ITF);
|
||||
}
|
||||
|
||||
reconfigure_it:
|
||||
|
||||
copy_ip6_address(&server->dhcp6_server, addr);
|
||||
copy_ip6_address(&server->dhcp6_src_address, src_address);
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include <vnet/dpo/punt_dpo.h>
|
||||
#include <vnet/dpo/classify_dpo.h>
|
||||
#include <vnet/dpo/ip_null_dpo.h>
|
||||
#include <vnet/dpo/replicate_dpo.h>
|
||||
|
||||
/**
|
||||
* Array of char* names for the DPO types and protos
|
||||
@@ -449,6 +450,7 @@ dpo_module_init (vlib_main_t * vm)
|
||||
classify_dpo_module_init();
|
||||
lookup_dpo_module_init();
|
||||
ip_null_dpo_module_init();
|
||||
replicate_module_init();
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
+7
-1
@@ -100,15 +100,18 @@ typedef enum dpo_type_t_ {
|
||||
* @brief load-balancing over a choice of [un]equal cost paths
|
||||
*/
|
||||
DPO_LOAD_BALANCE,
|
||||
DPO_REPLICATE,
|
||||
DPO_ADJACENCY,
|
||||
DPO_ADJACENCY_INCOMPLETE,
|
||||
DPO_ADJACENCY_MIDCHAIN,
|
||||
DPO_ADJACENCY_GLEAN,
|
||||
DPO_ADJACENCY_MCAST,
|
||||
DPO_RECEIVE,
|
||||
DPO_LOOKUP,
|
||||
DPO_LISP_CP,
|
||||
DPO_CLASSIFY,
|
||||
DPO_MPLS_LABEL,
|
||||
DPO_MFIB_ENTRY,
|
||||
DPO_LAST,
|
||||
} __attribute__((packed)) dpo_type_t;
|
||||
|
||||
@@ -123,12 +126,15 @@ typedef enum dpo_type_t_ {
|
||||
[DPO_ADJACENCY_INCOMPLETE] = "dpo-adjacency-incomplete", \
|
||||
[DPO_ADJACENCY_MIDCHAIN] = "dpo-adjacency-midcahin", \
|
||||
[DPO_ADJACENCY_GLEAN] = "dpo-glean", \
|
||||
[DPO_ADJACENCY_MCAST] = "dpo-adj-mcast", \
|
||||
[DPO_RECEIVE] = "dpo-receive", \
|
||||
[DPO_LOOKUP] = "dpo-lookup", \
|
||||
[DPO_LOAD_BALANCE] = "dpo-load-balance", \
|
||||
[DPO_REPLICATE] = "dpo-replicate", \
|
||||
[DPO_LISP_CP] = "dpo-lisp-cp", \
|
||||
[DPO_CLASSIFY] = "dpo-classify", \
|
||||
[DPO_MPLS_LABEL] = "dpo-mpls-label" \
|
||||
[DPO_MPLS_LABEL] = "dpo-mpls-label", \
|
||||
[DPO_MFIB_ENTRY] = "dpo-mfib_entry" \
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -238,6 +238,17 @@ load_balance_is_drop (const dpo_id_t *dpo)
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
load_balance_set_fib_entry_flags (index_t lbi,
|
||||
fib_entry_flag_t flags)
|
||||
{
|
||||
load_balance_t *lb;
|
||||
|
||||
lb = load_balance_get(lbi);
|
||||
lb->lb_fib_entry_flags = flags;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
load_balance_set_urpf (index_t lbi,
|
||||
index_t urpf)
|
||||
@@ -683,7 +694,7 @@ load_balance_multipath_update (const dpo_id_t *dpo,
|
||||
buckets,
|
||||
n_buckets);
|
||||
|
||||
for (ii = old_n_buckets-n_buckets; ii < old_n_buckets; ii++)
|
||||
for (ii = n_buckets; ii < old_n_buckets; ii++)
|
||||
{
|
||||
dpo_reset(&buckets[ii]);
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include <vnet/ip/lookup.h>
|
||||
#include <vnet/dpo/dpo.h>
|
||||
#include <vnet/fib/fib_types.h>
|
||||
#include <vnet/fib/fib_entry.h>
|
||||
|
||||
/**
|
||||
* Load-balance main
|
||||
@@ -98,6 +99,11 @@ typedef struct load_balance_t_ {
|
||||
*/
|
||||
dpo_proto_t lb_proto;
|
||||
|
||||
/**
|
||||
* Flags from the load-balance's associated fib_entry_t
|
||||
*/
|
||||
fib_entry_flag_t lb_fib_entry_flags;
|
||||
|
||||
/**
|
||||
* The number of locks, which is approximately the number of users,
|
||||
* of this load-balance.
|
||||
@@ -167,6 +173,8 @@ extern void load_balance_set_bucket(index_t lbi,
|
||||
const dpo_id_t *next);
|
||||
extern void load_balance_set_urpf(index_t lbi,
|
||||
index_t urpf);
|
||||
extern void load_balance_set_fib_entry_flags(index_t lbi,
|
||||
fib_entry_flag_t flags);
|
||||
extern index_t load_balance_get_urpf(index_t lbi);
|
||||
|
||||
extern u8* format_load_balance(u8 * s, va_list * args);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __REPLICATE_DPO_H__
|
||||
#define __REPLICATE_DPO_H__
|
||||
|
||||
#include <vlib/vlib.h>
|
||||
#include <vnet/ip/lookup.h>
|
||||
#include <vnet/dpo/dpo.h>
|
||||
#include <vnet/dpo/load_balance.h>
|
||||
#include <vnet/fib/fib_types.h>
|
||||
|
||||
/**
|
||||
* replicate main
|
||||
*/
|
||||
typedef struct replicate_main_t_
|
||||
{
|
||||
vlib_combined_counter_main_t repm_counters;
|
||||
} replicate_main_t;
|
||||
|
||||
extern replicate_main_t replicate_main;
|
||||
|
||||
/**
|
||||
* The number of buckets that a load-balance object can have and still
|
||||
* fit in one cache-line
|
||||
*/
|
||||
#define REP_NUM_INLINE_BUCKETS 4
|
||||
|
||||
/**
|
||||
* The FIB DPO provieds;
|
||||
* - load-balancing over the next DPOs in the chain/graph
|
||||
* - per-route counters
|
||||
*/
|
||||
typedef struct replicate_t_ {
|
||||
/**
|
||||
* number of buckets in the load-balance. always a power of 2.
|
||||
*/
|
||||
u16 rep_n_buckets;
|
||||
|
||||
/**
|
||||
* The protocol of packets that traverse this REP.
|
||||
* need in combination with the flow hash config to determine how to hash.
|
||||
* u8.
|
||||
*/
|
||||
dpo_proto_t rep_proto;
|
||||
|
||||
/**
|
||||
* The number of locks, which is approximately the number of users,
|
||||
* of this load-balance.
|
||||
* Load-balance objects of via-entries are heavily shared by recursives,
|
||||
* so the lock count is a u32.
|
||||
*/
|
||||
u32 rep_locks;
|
||||
|
||||
/**
|
||||
* Vector of buckets containing the next DPOs, sized as repo_num
|
||||
*/
|
||||
dpo_id_t *rep_buckets;
|
||||
|
||||
/**
|
||||
* The rest of the cache line is used for buckets. In the common case
|
||||
* where there there are less than 4 buckets, then the buckets are
|
||||
* on the same cachlie and we save ourselves a pointer dereferance in
|
||||
* the data-path.
|
||||
*/
|
||||
dpo_id_t rep_buckets_inline[REP_NUM_INLINE_BUCKETS];
|
||||
} replicate_t;
|
||||
|
||||
STATIC_ASSERT(sizeof(replicate_t) <= CLIB_CACHE_LINE_BYTES,
|
||||
"A replicate object size exceeds one cachline");
|
||||
|
||||
/**
|
||||
* Flags controlling load-balance formatting/display
|
||||
*/
|
||||
typedef enum replicate_format_flags_t_ {
|
||||
REPLICATE_FORMAT_NONE,
|
||||
REPLICATE_FORMAT_DETAIL = (1 << 0),
|
||||
} replicate_format_flags_t;
|
||||
|
||||
extern index_t replicate_create(u32 num_buckets,
|
||||
dpo_proto_t rep_proto);
|
||||
extern void replicate_multipath_update(
|
||||
const dpo_id_t *dpo,
|
||||
load_balance_path_t *next_hops);
|
||||
|
||||
extern void replicate_set_bucket(index_t repi,
|
||||
u32 bucket,
|
||||
const dpo_id_t *next);
|
||||
|
||||
extern u8* format_replicate(u8 * s, va_list * args);
|
||||
|
||||
extern const dpo_id_t *replicate_get_bucket(index_t repi,
|
||||
u32 bucket);
|
||||
extern int replicate_is_drop(const dpo_id_t *dpo);
|
||||
|
||||
/**
|
||||
* The encapsulation breakages are for fast DP access
|
||||
*/
|
||||
extern replicate_t *replicate_pool;
|
||||
static inline replicate_t*
|
||||
replicate_get (index_t repi)
|
||||
{
|
||||
return (pool_elt_at_index(replicate_pool, repi));
|
||||
}
|
||||
|
||||
#define REP_HAS_INLINE_BUCKETS(_rep) \
|
||||
((_rep)->rep_n_buckets <= REP_NUM_INLINE_BUCKETS)
|
||||
|
||||
static inline const dpo_id_t *
|
||||
replicate_get_bucket_i (const replicate_t *rep,
|
||||
u32 bucket)
|
||||
{
|
||||
ASSERT(bucket < rep->rep_n_buckets);
|
||||
|
||||
if (PREDICT_TRUE(REP_HAS_INLINE_BUCKETS(rep)))
|
||||
{
|
||||
return (&rep->rep_buckets_inline[bucket]);
|
||||
}
|
||||
else
|
||||
{
|
||||
return (&rep->rep_buckets[bucket]);
|
||||
}
|
||||
}
|
||||
|
||||
extern void replicate_module_init(void);
|
||||
|
||||
#endif
|
||||
+63
-21
@@ -23,6 +23,7 @@
|
||||
#include <vppinfra/mhash.h>
|
||||
#include <vnet/fib/ip4_fib.h>
|
||||
#include <vnet/adj/adj_nbr.h>
|
||||
#include <vnet/adj/adj_mcast.h>
|
||||
#include <vnet/mpls/mpls.h>
|
||||
|
||||
/**
|
||||
@@ -438,33 +439,74 @@ arp_update_adjacency (vnet_main_t * vnm, u32 sw_if_index, u32 ai)
|
||||
arp_int = &am->ethernet_arp_by_sw_if_index[sw_if_index];
|
||||
e = arp_entry_find (arp_int, &adj->sub_type.nbr.next_hop.ip4);
|
||||
|
||||
if (NULL != e)
|
||||
{
|
||||
adj_nbr_walk_nh4 (sw_if_index,
|
||||
&e->ip4_address, arp_mk_complete_walk, e);
|
||||
}
|
||||
else
|
||||
switch (adj->lookup_next_index)
|
||||
{
|
||||
case IP_LOOKUP_NEXT_ARP:
|
||||
case IP_LOOKUP_NEXT_GLEAN:
|
||||
if (NULL != e)
|
||||
{
|
||||
adj_nbr_walk_nh4 (sw_if_index,
|
||||
&e->ip4_address, arp_mk_complete_walk, e);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* no matching ARP entry.
|
||||
* construct the rewrite required to for an ARP packet, and stick
|
||||
* that in the adj's pipe to smoke.
|
||||
*/
|
||||
adj_nbr_update_rewrite
|
||||
(ai,
|
||||
ADJ_NBR_REWRITE_FLAG_INCOMPLETE,
|
||||
ethernet_build_rewrite
|
||||
(vnm,
|
||||
sw_if_index,
|
||||
VNET_LINK_ARP,
|
||||
VNET_REWRITE_FOR_SW_INTERFACE_ADDRESS_BROADCAST));
|
||||
|
||||
/*
|
||||
* since the FIB has added this adj for a route, it makes sense it
|
||||
* may want to forward traffic sometime soon. Let's send a
|
||||
* speculative ARP. just one. If we were to do periodically that
|
||||
* wouldn't be bad either, but that's more code than i'm prepared to
|
||||
* write at this time for relatively little reward.
|
||||
*/
|
||||
arp_nbr_probe (adj);
|
||||
}
|
||||
break;
|
||||
case IP_LOOKUP_NEXT_MCAST:
|
||||
/*
|
||||
* no matching ARP entry.
|
||||
* construct the rewire required to for an ARP packet, and stick
|
||||
* that in the adj's pipe to smoke.
|
||||
* Construct a partial rewrite from the known ethernet mcast dest MAC
|
||||
*/
|
||||
adj_nbr_update_rewrite (ai,
|
||||
ADJ_NBR_REWRITE_FLAG_INCOMPLETE,
|
||||
ethernet_build_rewrite (vnm,
|
||||
sw_if_index,
|
||||
VNET_LINK_ARP,
|
||||
VNET_REWRITE_FOR_SW_INTERFACE_ADDRESS_BROADCAST));
|
||||
adj_mcast_update_rewrite
|
||||
(ai,
|
||||
ethernet_build_rewrite (vnm,
|
||||
sw_if_index,
|
||||
adj->ia_link,
|
||||
ethernet_ip4_mcast_dst_addr ()));
|
||||
|
||||
/*
|
||||
* since the FIB has added this adj for a route, it makes sense it may
|
||||
* want to forward traffic sometime soon. Let's send a speculative ARP.
|
||||
* just one. If we were to do periodically that wouldn't be bad either,
|
||||
* but that's more code than i'm prepared to write at this time for
|
||||
* relatively little reward.
|
||||
* Complete the remaining fields of the adj's rewrite to direct the
|
||||
* complete of the rewrite at switch time by copying in the IP
|
||||
* dst address's bytes.
|
||||
* Ofset is 11 bytes from the end of the MAC header - which is three
|
||||
* bytes into the desintation address. And we write 3 bytes.
|
||||
*/
|
||||
arp_nbr_probe (adj);
|
||||
adj->rewrite_header.dst_mcast_offset = 11;
|
||||
adj->rewrite_header.dst_mcast_n_bytes = 3;
|
||||
|
||||
break;
|
||||
|
||||
case IP_LOOKUP_NEXT_DROP:
|
||||
case IP_LOOKUP_NEXT_PUNT:
|
||||
case IP_LOOKUP_NEXT_LOCAL:
|
||||
case IP_LOOKUP_NEXT_REWRITE:
|
||||
case IP_LOOKUP_NEXT_LOAD_BALANCE:
|
||||
case IP_LOOKUP_NEXT_MIDCHAIN:
|
||||
case IP_LOOKUP_NEXT_ICMP_ERROR:
|
||||
case IP_LOOKUP_N_NEXT:
|
||||
ASSERT (0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -547,6 +547,8 @@ void ethernet_update_adjacency (vnet_main_t * vnm, u32 sw_if_index, u32 ai);
|
||||
u8 *ethernet_build_rewrite (vnet_main_t * vnm,
|
||||
u32 sw_if_index,
|
||||
vnet_link_t link_type, const void *dst_address);
|
||||
const u8 *ethernet_ip4_mcast_dst_addr (void);
|
||||
const u8 *ethernet_ip6_mcast_dst_addr (void);
|
||||
|
||||
extern vlib_node_registration_t ethernet_input_node;
|
||||
|
||||
|
||||
@@ -51,6 +51,26 @@
|
||||
* This file contains code to manage loopback interfaces.
|
||||
*/
|
||||
|
||||
const u8 *
|
||||
ethernet_ip4_mcast_dst_addr (void)
|
||||
{
|
||||
const static u8 ethernet_mcast_dst_mac[] = {
|
||||
0x1, 0x0, 0x5e, 0x0, 0x0, 0x0,
|
||||
};
|
||||
|
||||
return (ethernet_mcast_dst_mac);
|
||||
}
|
||||
|
||||
const u8 *
|
||||
ethernet_ip6_mcast_dst_addr (void)
|
||||
{
|
||||
const static u8 ethernet_mcast_dst_mac[] = {
|
||||
0x33, 0x33, 0x00, 0x0, 0x0, 0x0,
|
||||
};
|
||||
|
||||
return (ethernet_mcast_dst_mac);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief build a rewrite string to use for sending packets of type 'link_type'
|
||||
* to 'dst_address'
|
||||
|
||||
@@ -303,8 +303,8 @@ fib_attached_export_import (fib_entry_t *fib_entry,
|
||||
* may have realloc'd.
|
||||
*/
|
||||
fib_entry = fib_entry_get(fei);
|
||||
import->faei_export_sibling =
|
||||
fib_entry_cover_track(fib_entry_get(import->faei_export_entry), fei);
|
||||
import->faei_export_sibling =
|
||||
fib_entry_cover_track(fib_entry_get(import->faei_export_entry), fei);
|
||||
|
||||
fed = fib_entry_delegate_find_or_add(fib_entry,
|
||||
FIB_ENTRY_DELEGATE_ATTACHED_IMPORT);
|
||||
|
||||
@@ -220,7 +220,7 @@ typedef enum fib_entry_flag_t_ {
|
||||
FIB_ENTRY_FLAG_EXCLUSIVE = (1 << FIB_ENTRY_ATTRIBUTE_EXCLUSIVE),
|
||||
FIB_ENTRY_FLAG_LOCAL = (1 << FIB_ENTRY_ATTRIBUTE_LOCAL),
|
||||
FIB_ENTRY_FLAG_IMPORT = (1 << FIB_ENTRY_ATTRIBUTE_IMPORT),
|
||||
} fib_entry_flag_t;
|
||||
} __attribute__((packed)) fib_entry_flag_t;
|
||||
|
||||
/**
|
||||
* Flags for the source data
|
||||
|
||||
@@ -119,6 +119,9 @@ fib_entry_chain_type_to_delegate_type (fib_forward_chain_type_t fct)
|
||||
return (FIB_ENTRY_DELEGATE_CHAIN_MPLS_NON_EOS);
|
||||
case FIB_FORW_CHAIN_TYPE_ETHERNET:
|
||||
return (FIB_ENTRY_DELEGATE_CHAIN_ETHERNET);
|
||||
case FIB_FORW_CHAIN_TYPE_MCAST_IP4:
|
||||
case FIB_FORW_CHAIN_TYPE_MCAST_IP6:
|
||||
break;
|
||||
}
|
||||
ASSERT(0);
|
||||
return (FIB_ENTRY_DELEGATE_CHAIN_UNICAST_IP4);
|
||||
|
||||
@@ -313,6 +313,8 @@ fib_entry_src_collect_forwarding (fib_node_index_t pl_index,
|
||||
{
|
||||
case FIB_FORW_CHAIN_TYPE_UNICAST_IP4:
|
||||
case FIB_FORW_CHAIN_TYPE_UNICAST_IP6:
|
||||
case FIB_FORW_CHAIN_TYPE_MCAST_IP4:
|
||||
case FIB_FORW_CHAIN_TYPE_MCAST_IP6:
|
||||
/*
|
||||
* EOS traffic with no label to stack, we need the IP Adj
|
||||
*/
|
||||
@@ -458,6 +460,8 @@ fib_entry_src_mk_lb (fib_entry_t *fib_entry,
|
||||
{
|
||||
load_balance_set_urpf(dpo_lb->dpoi_index, ui);
|
||||
}
|
||||
load_balance_set_fib_entry_flags(dpo_lb->dpoi_index,
|
||||
fib_entry_get_flags_i(fib_entry));
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -31,6 +31,7 @@ typedef enum fib_node_type_t_ {
|
||||
*/
|
||||
FIB_NODE_TYPE_WALK,
|
||||
FIB_NODE_TYPE_ENTRY,
|
||||
FIB_NODE_TYPE_MFIB_ENTRY,
|
||||
FIB_NODE_TYPE_PATH_LIST,
|
||||
FIB_NODE_TYPE_PATH,
|
||||
FIB_NODE_TYPE_ADJ,
|
||||
@@ -51,6 +52,7 @@ typedef enum fib_node_type_t_ {
|
||||
|
||||
#define FIB_NODE_TYPES { \
|
||||
[FIB_NODE_TYPE_ENTRY] = "entry", \
|
||||
[FIB_NODE_TYPE_MFIB_ENTRY] = "mfib-entry", \
|
||||
[FIB_NODE_TYPE_WALK] = "walk", \
|
||||
[FIB_NODE_TYPE_PATH_LIST] = "path-list", \
|
||||
[FIB_NODE_TYPE_PATH] = "path", \
|
||||
|
||||
+62
-29
@@ -23,6 +23,7 @@
|
||||
#include <vnet/dpo/lookup_dpo.h>
|
||||
|
||||
#include <vnet/adj/adj.h>
|
||||
#include <vnet/adj/adj_mcast.h>
|
||||
|
||||
#include <vnet/fib/fib_path.h>
|
||||
#include <vnet/fib/fib_node.h>
|
||||
@@ -960,6 +961,8 @@ fib_path_route_flags_to_cfg_flags (const fib_route_path_t *rpath)
|
||||
cfg_flags |= FIB_PATH_CFG_FLAG_RESOLVE_HOST;
|
||||
if (rpath->frp_flags & FIB_ROUTE_PATH_RESOLVE_VIA_ATTACHED)
|
||||
cfg_flags |= FIB_PATH_CFG_FLAG_RESOLVE_ATTACHED;
|
||||
if (rpath->frp_flags & FIB_ROUTE_PATH_LOCAL)
|
||||
cfg_flags |= FIB_PATH_CFG_FLAG_LOCAL;
|
||||
|
||||
return (cfg_flags);
|
||||
}
|
||||
@@ -1003,28 +1006,25 @@ fib_path_create (fib_node_index_t pl_index,
|
||||
/*
|
||||
* deduce the path's tpye from the parementers and save what is needed.
|
||||
*/
|
||||
if (~0 != rpath->frp_sw_if_index)
|
||||
if (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_LOCAL)
|
||||
{
|
||||
if (flags & FIB_PATH_CFG_FLAG_LOCAL)
|
||||
{
|
||||
path->fp_type = FIB_PATH_TYPE_RECEIVE;
|
||||
path->receive.fp_interface = rpath->frp_sw_if_index;
|
||||
path->receive.fp_addr = rpath->frp_addr;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ip46_address_is_zero(&rpath->frp_addr))
|
||||
{
|
||||
path->fp_type = FIB_PATH_TYPE_ATTACHED;
|
||||
path->attached.fp_interface = rpath->frp_sw_if_index;
|
||||
}
|
||||
else
|
||||
{
|
||||
path->fp_type = FIB_PATH_TYPE_ATTACHED_NEXT_HOP;
|
||||
path->attached_next_hop.fp_interface = rpath->frp_sw_if_index;
|
||||
path->attached_next_hop.fp_nh = rpath->frp_addr;
|
||||
}
|
||||
}
|
||||
path->fp_type = FIB_PATH_TYPE_RECEIVE;
|
||||
path->receive.fp_interface = rpath->frp_sw_if_index;
|
||||
path->receive.fp_addr = rpath->frp_addr;
|
||||
}
|
||||
else if (~0 != rpath->frp_sw_if_index)
|
||||
{
|
||||
if (ip46_address_is_zero(&rpath->frp_addr))
|
||||
{
|
||||
path->fp_type = FIB_PATH_TYPE_ATTACHED;
|
||||
path->attached.fp_interface = rpath->frp_sw_if_index;
|
||||
}
|
||||
else
|
||||
{
|
||||
path->fp_type = FIB_PATH_TYPE_ATTACHED_NEXT_HOP;
|
||||
path->attached_next_hop.fp_interface = rpath->frp_sw_if_index;
|
||||
path->attached_next_hop.fp_nh = rpath->frp_addr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1199,7 +1199,7 @@ fib_path_cmp_i (const fib_path_t *path1,
|
||||
{
|
||||
res = (path1->fp_type - path2->fp_type);
|
||||
}
|
||||
if (path1->fp_nh_proto != path2->fp_nh_proto)
|
||||
else if (path1->fp_nh_proto != path2->fp_nh_proto)
|
||||
{
|
||||
res = (path1->fp_nh_proto - path2->fp_nh_proto);
|
||||
}
|
||||
@@ -1770,8 +1770,11 @@ fib_path_contribute_forwarding (fib_node_index_t path_index,
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
case FIB_FORW_CHAIN_TYPE_MCAST_IP4:
|
||||
case FIB_FORW_CHAIN_TYPE_MCAST_IP6:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case FIB_PATH_TYPE_RECURSIVE:
|
||||
switch (fct)
|
||||
{
|
||||
@@ -1781,13 +1784,15 @@ fib_path_contribute_forwarding (fib_node_index_t path_index,
|
||||
case FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS:
|
||||
fib_path_recursive_adj_update(path, fct, dpo);
|
||||
break;
|
||||
case FIB_FORW_CHAIN_TYPE_MCAST_IP4:
|
||||
case FIB_FORW_CHAIN_TYPE_MCAST_IP6:
|
||||
case FIB_FORW_CHAIN_TYPE_ETHERNET:
|
||||
ASSERT(0);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case FIB_PATH_TYPE_DEAG:
|
||||
switch (fct)
|
||||
switch (fct)
|
||||
{
|
||||
case FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS:
|
||||
lookup_dpo_add_or_lock_w_table_id(MPLS_FIB_DEFAULT_TABLE_ID,
|
||||
@@ -1800,7 +1805,9 @@ fib_path_contribute_forwarding (fib_node_index_t path_index,
|
||||
case FIB_FORW_CHAIN_TYPE_UNICAST_IP6:
|
||||
case FIB_FORW_CHAIN_TYPE_MPLS_EOS:
|
||||
dpo_copy(dpo, &path->fp_dpo);
|
||||
break;
|
||||
break;
|
||||
case FIB_FORW_CHAIN_TYPE_MCAST_IP4:
|
||||
case FIB_FORW_CHAIN_TYPE_MCAST_IP6:
|
||||
case FIB_FORW_CHAIN_TYPE_ETHERNET:
|
||||
ASSERT(0);
|
||||
break;
|
||||
@@ -1810,12 +1817,38 @@ fib_path_contribute_forwarding (fib_node_index_t path_index,
|
||||
dpo_copy(dpo, &path->exclusive.fp_ex_dpo);
|
||||
break;
|
||||
case FIB_PATH_TYPE_ATTACHED:
|
||||
case FIB_PATH_TYPE_RECEIVE:
|
||||
case FIB_PATH_TYPE_SPECIAL:
|
||||
ASSERT(0);
|
||||
switch (fct)
|
||||
{
|
||||
case FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS:
|
||||
case FIB_FORW_CHAIN_TYPE_UNICAST_IP4:
|
||||
case FIB_FORW_CHAIN_TYPE_UNICAST_IP6:
|
||||
case FIB_FORW_CHAIN_TYPE_MPLS_EOS:
|
||||
case FIB_FORW_CHAIN_TYPE_ETHERNET:
|
||||
break;
|
||||
case FIB_FORW_CHAIN_TYPE_MCAST_IP4:
|
||||
case FIB_FORW_CHAIN_TYPE_MCAST_IP6:
|
||||
{
|
||||
adj_index_t ai;
|
||||
|
||||
/*
|
||||
* Create the adj needed for sending IP multicast traffic
|
||||
*/
|
||||
ai = adj_mcast_add_or_lock(path->fp_nh_proto,
|
||||
fib_forw_chain_type_to_link_type(fct),
|
||||
path->attached.fp_interface);
|
||||
dpo_set(dpo, DPO_ADJACENCY_MCAST,
|
||||
fib_forw_chain_type_to_dpo_proto(fct),
|
||||
ai);
|
||||
adj_unlock(ai);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case FIB_PATH_TYPE_RECEIVE:
|
||||
case FIB_PATH_TYPE_SPECIAL:
|
||||
dpo_copy(dpo, &path->fp_dpo);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -585,8 +585,11 @@ fib_path_list_resolve (fib_path_list_t *path_list)
|
||||
path_list = fib_path_list_get(path_list_index);
|
||||
|
||||
FIB_PATH_LIST_DBG(path_list, "resovled");
|
||||
fib_path_list_mk_urpf(path_list);
|
||||
|
||||
if (!(path_list->fpl_flags & FIB_PATH_LIST_FLAG_NO_URPF))
|
||||
{
|
||||
fib_path_list_mk_urpf(path_list);
|
||||
}
|
||||
return (path_list);
|
||||
}
|
||||
|
||||
@@ -1025,14 +1028,14 @@ fib_path_list_copy_and_path_remove (fib_node_index_t orig_path_list_index,
|
||||
*/
|
||||
void
|
||||
fib_path_list_contribute_forwarding (fib_node_index_t path_list_index,
|
||||
fib_forward_chain_type_t type,
|
||||
fib_forward_chain_type_t fct,
|
||||
dpo_id_t *dpo)
|
||||
{
|
||||
fib_path_list_t *path_list;
|
||||
|
||||
path_list = fib_path_list_get(path_list_index);
|
||||
|
||||
fib_path_list_mk_lb(path_list, type, dpo);
|
||||
fib_path_list_mk_lb(path_list, fct, dpo);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -60,6 +60,10 @@ typedef enum fib_path_list_attribute_t_ {
|
||||
* looped path-list. one path looped implies the whole list is
|
||||
*/
|
||||
FIB_PATH_LIST_ATTRIBUTE_LOOPED,
|
||||
/**
|
||||
* no uRPF - do not generate unicast RPF list for this path-list
|
||||
*/
|
||||
FIB_PATH_LIST_ATTRIBUTE_NO_URPF,
|
||||
/**
|
||||
* Marher. Add new flags before this one, and then update it.
|
||||
*/
|
||||
@@ -74,6 +78,7 @@ typedef enum fib_path_list_flags_t_ {
|
||||
FIB_PATH_LIST_FLAG_EXCLUSIVE = (1 << FIB_PATH_LIST_ATTRIBUTE_EXCLUSIVE),
|
||||
FIB_PATH_LIST_FLAG_RESOLVED = (1 << FIB_PATH_LIST_ATTRIBUTE_RESOLVED),
|
||||
FIB_PATH_LIST_FLAG_LOOPED = (1 << FIB_PATH_LIST_ATTRIBUTE_LOOPED),
|
||||
FIB_PATH_LIST_FLAG_NO_URPF = (1 << FIB_PATH_LIST_ATTRIBUTE_NO_URPF),
|
||||
} fib_path_list_flags_t;
|
||||
|
||||
#define FIB_PATH_LIST_ATTRIBUTES { \
|
||||
@@ -83,6 +88,7 @@ typedef enum fib_path_list_flags_t_ {
|
||||
[FIB_PATH_LIST_ATTRIBUTE_EXCLUSIVE] = "exclusive", \
|
||||
[FIB_PATH_LIST_ATTRIBUTE_LOCAL] = "local", \
|
||||
[FIB_PATH_LIST_ATTRIBUTE_LOOPED] = "looped", \
|
||||
[FIB_PATH_LIST_ATTRIBUTE_NO_URPF] = "no-uRPF", \
|
||||
}
|
||||
|
||||
#define FOR_EACH_PATH_LIST_ATTRIBUTE(_item) \
|
||||
|
||||
@@ -1043,6 +1043,26 @@ fib_table_destroy (fib_table_t *fib_table)
|
||||
break;
|
||||
}
|
||||
}
|
||||
void
|
||||
fib_table_walk (u32 fib_index,
|
||||
fib_protocol_t proto,
|
||||
fib_table_walk_fn_t fn,
|
||||
void *ctx)
|
||||
{
|
||||
switch (proto)
|
||||
{
|
||||
case FIB_PROTOCOL_IP4:
|
||||
ip4_fib_table_walk(ip4_fib_get(fib_index), fn, ctx);
|
||||
break;
|
||||
case FIB_PROTOCOL_IP6:
|
||||
ip6_fib_table_walk(fib_index, fn, ctx);
|
||||
break;
|
||||
case FIB_PROTOCOL_MPLS:
|
||||
mpls_fib_table_walk(mpls_fib_get(fib_index), fn, ctx);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
fib_table_unlock (u32 fib_index,
|
||||
@@ -1094,11 +1114,56 @@ format_fib_table_name (u8* s, va_list ap)
|
||||
return (s);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Table flush context. Store the indicies of matching FIB entries
|
||||
* that need to be removed.
|
||||
*/
|
||||
typedef struct fib_table_flush_ctx_t_
|
||||
{
|
||||
/**
|
||||
* The list of entries to flush
|
||||
*/
|
||||
fib_node_index_t *ftf_entries;
|
||||
|
||||
/**
|
||||
* The source we are flushing
|
||||
*/
|
||||
fib_source_t ftf_source;
|
||||
} fib_table_flush_ctx_t;
|
||||
|
||||
static int
|
||||
fib_table_flush_cb (fib_node_index_t fib_entry_index,
|
||||
void *arg)
|
||||
{
|
||||
fib_table_flush_ctx_t *ctx = arg;
|
||||
|
||||
if (fib_entry_is_sourced(fib_entry_index, ctx->ftf_source))
|
||||
{
|
||||
vec_add1(ctx->ftf_entries, fib_entry_index);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
fib_table_flush (u32 fib_index,
|
||||
fib_protocol_t proto,
|
||||
fib_source_t source)
|
||||
{
|
||||
// FIXME
|
||||
ASSERT(0);
|
||||
fib_node_index_t *fib_entry_index;
|
||||
fib_table_flush_ctx_t ctx = {
|
||||
.ftf_entries = NULL,
|
||||
.ftf_source = source,
|
||||
};
|
||||
|
||||
fib_table_walk(fib_index, proto,
|
||||
fib_table_flush_cb,
|
||||
&ctx);
|
||||
|
||||
vec_foreach(fib_entry_index, ctx.ftf_entries)
|
||||
{
|
||||
fib_entry_delete(*fib_entry_index, source);
|
||||
}
|
||||
|
||||
vec_free(ctx.ftf_entries);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user