BIER
- see draft-ietf-bier-mpls-encapsulation-10 - midpoint, head and tail functions - supported payload protocols; IPv4 and IPv6 only. Change-Id: I59d7363bb6fdfdce8e4016a68a9c8f5a5e5791cb Signed-off-by: Neale Ranns <nranns@cisco.com>
This commit is contained in:
committed by
Damjan Marion
parent
a2ff7b8cfc
commit
d792d9c01e
@@ -5180,6 +5180,8 @@ _(ip_mroute_add_del_reply) \
|
||||
_(mpls_route_add_del_reply) \
|
||||
_(mpls_table_add_del_reply) \
|
||||
_(mpls_ip_bind_unbind_reply) \
|
||||
_(bier_route_add_del_reply) \
|
||||
_(bier_table_add_del_reply) \
|
||||
_(proxy_arp_add_del_reply) \
|
||||
_(proxy_arp_intfc_enable_disable_reply) \
|
||||
_(sw_interface_set_unnumbered_reply) \
|
||||
@@ -5383,6 +5385,8 @@ _(IP_MROUTE_ADD_DEL_REPLY, ip_mroute_add_del_reply) \
|
||||
_(MPLS_TABLE_ADD_DEL_REPLY, mpls_table_add_del_reply) \
|
||||
_(MPLS_ROUTE_ADD_DEL_REPLY, mpls_route_add_del_reply) \
|
||||
_(MPLS_IP_BIND_UNBIND_REPLY, mpls_ip_bind_unbind_reply) \
|
||||
_(BIER_ROUTE_ADD_DEL_REPLY, bier_route_add_del_reply) \
|
||||
_(BIER_TABLE_ADD_DEL_REPLY, bier_table_add_del_reply) \
|
||||
_(PROXY_ARP_ADD_DEL_REPLY, proxy_arp_add_del_reply) \
|
||||
_(PROXY_ARP_INTFC_ENABLE_DISABLE_REPLY, \
|
||||
proxy_arp_intfc_enable_disable_reply) \
|
||||
@@ -8547,6 +8551,154 @@ api_mpls_ip_bind_unbind (vat_main_t * vam)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
api_bier_table_add_del (vat_main_t * vam)
|
||||
{
|
||||
unformat_input_t *i = vam->input;
|
||||
vl_api_bier_table_add_del_t *mp;
|
||||
u8 is_add = 1;
|
||||
u32 set = 0, sub_domain = 0, hdr_len = 3;
|
||||
mpls_label_t local_label = MPLS_LABEL_INVALID;
|
||||
int ret;
|
||||
|
||||
/* Parse args required to build the message */
|
||||
while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
|
||||
{
|
||||
if (unformat (i, "sub-domain %d", &sub_domain))
|
||||
;
|
||||
else if (unformat (i, "set %d", &set))
|
||||
;
|
||||
else if (unformat (i, "label %d", &local_label))
|
||||
;
|
||||
else if (unformat (i, "hdr-len %d", &hdr_len))
|
||||
;
|
||||
else if (unformat (i, "add"))
|
||||
is_add = 1;
|
||||
else if (unformat (i, "del"))
|
||||
is_add = 0;
|
||||
else
|
||||
{
|
||||
clib_warning ("parse error '%U'", format_unformat_error, i);
|
||||
return -99;
|
||||
}
|
||||
}
|
||||
|
||||
if (MPLS_LABEL_INVALID == local_label)
|
||||
{
|
||||
errmsg ("missing label\n");
|
||||
return -99;
|
||||
}
|
||||
|
||||
/* Construct the API message */
|
||||
M (BIER_TABLE_ADD_DEL, mp);
|
||||
|
||||
mp->bt_is_add = is_add;
|
||||
mp->bt_label = ntohl (local_label);
|
||||
mp->bt_tbl_id.bt_set = set;
|
||||
mp->bt_tbl_id.bt_sub_domain = sub_domain;
|
||||
mp->bt_tbl_id.bt_hdr_len_id = hdr_len;
|
||||
|
||||
/* send it... */
|
||||
S (mp);
|
||||
|
||||
/* Wait for a reply... */
|
||||
W (ret);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
api_bier_route_add_del (vat_main_t * vam)
|
||||
{
|
||||
unformat_input_t *i = vam->input;
|
||||
vl_api_bier_route_add_del_t *mp;
|
||||
u8 is_add = 1;
|
||||
u32 set = 0, sub_domain = 0, hdr_len = 3, bp = 0;
|
||||
ip4_address_t v4_next_hop_address;
|
||||
ip6_address_t v6_next_hop_address;
|
||||
u8 next_hop_set = 0;
|
||||
u8 next_hop_proto_is_ip4 = 1;
|
||||
mpls_label_t next_hop_out_label = MPLS_LABEL_INVALID;
|
||||
int ret;
|
||||
|
||||
/* Parse args required to build the message */
|
||||
while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
|
||||
{
|
||||
if (unformat (i, "%U", unformat_ip4_address, &v4_next_hop_address))
|
||||
{
|
||||
next_hop_proto_is_ip4 = 1;
|
||||
next_hop_set = 1;
|
||||
}
|
||||
else if (unformat (i, "%U", unformat_ip6_address, &v6_next_hop_address))
|
||||
{
|
||||
next_hop_proto_is_ip4 = 0;
|
||||
next_hop_set = 1;
|
||||
}
|
||||
if (unformat (i, "sub-domain %d", &sub_domain))
|
||||
;
|
||||
else if (unformat (i, "set %d", &set))
|
||||
;
|
||||
else if (unformat (i, "hdr-len %d", &hdr_len))
|
||||
;
|
||||
else if (unformat (i, "bp %d", &bp))
|
||||
;
|
||||
else if (unformat (i, "add"))
|
||||
is_add = 1;
|
||||
else if (unformat (i, "del"))
|
||||
is_add = 0;
|
||||
else if (unformat (i, "out-label %d", &next_hop_out_label))
|
||||
;
|
||||
else
|
||||
{
|
||||
clib_warning ("parse error '%U'", format_unformat_error, i);
|
||||
return -99;
|
||||
}
|
||||
}
|
||||
|
||||
if (!next_hop_set || (MPLS_LABEL_INVALID == next_hop_out_label))
|
||||
{
|
||||
errmsg ("next hop / label set\n");
|
||||
return -99;
|
||||
}
|
||||
if (0 == bp)
|
||||
{
|
||||
errmsg ("bit=position not set\n");
|
||||
return -99;
|
||||
}
|
||||
|
||||
/* Construct the API message */
|
||||
M2 (BIER_ROUTE_ADD_DEL, mp, sizeof (vl_api_fib_path3_t));
|
||||
|
||||
mp->br_is_add = is_add;
|
||||
mp->br_tbl_id.bt_set = set;
|
||||
mp->br_tbl_id.bt_sub_domain = sub_domain;
|
||||
mp->br_tbl_id.bt_hdr_len_id = hdr_len;
|
||||
mp->br_bp = ntohs (bp);
|
||||
mp->br_n_paths = 1;
|
||||
mp->br_paths[0].n_labels = 1;
|
||||
mp->br_paths[0].label_stack[0] = ntohl (next_hop_out_label);
|
||||
mp->br_paths[0].afi = (next_hop_proto_is_ip4 ? 0 : 1);
|
||||
|
||||
if (next_hop_proto_is_ip4)
|
||||
{
|
||||
clib_memcpy (mp->br_paths[0].next_hop,
|
||||
&v4_next_hop_address, sizeof (v4_next_hop_address));
|
||||
}
|
||||
else
|
||||
{
|
||||
clib_memcpy (mp->br_paths[0].next_hop,
|
||||
&v6_next_hop_address, sizeof (v6_next_hop_address));
|
||||
}
|
||||
|
||||
/* send it... */
|
||||
S (mp);
|
||||
|
||||
/* Wait for a reply... */
|
||||
W (ret);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
api_proxy_arp_add_del (vat_main_t * vam)
|
||||
{
|
||||
@@ -22238,6 +22390,12 @@ _(mpls_ip_bind_unbind, \
|
||||
_(mpls_tunnel_add_del, \
|
||||
" via <addr> [table-id <n>]\n" \
|
||||
"sw_if_index <id>] [l2] [del]") \
|
||||
_(bier_table_add_del, \
|
||||
"<label> <sub-domain> <set> <bsl> [del]") \
|
||||
_(bier_route_add_del, \
|
||||
"<bit-position> <sub-domain> <set> <bsl> via <addr> [table-id <n>]\n" \
|
||||
"[<intfc> | sw_if_index <id>]" \
|
||||
"[weight <n>] [del] [multipath]") \
|
||||
_(proxy_arp_add_del, \
|
||||
"<lo-ip4-addr> - <hi-ip4-addr> [vrf <n>] [del]") \
|
||||
_(proxy_arp_intfc_enable_disable, \
|
||||
|
||||
+34
@@ -1111,6 +1111,40 @@ libvnet_la_SOURCES += \
|
||||
vnet/util/radix.c \
|
||||
vnet/util/trajectory.c
|
||||
|
||||
########################################
|
||||
# BIER
|
||||
########################################
|
||||
|
||||
libvnet_la_SOURCES += \
|
||||
vnet/bier/bier_bit_string.c \
|
||||
vnet/bier/bier_entry.c \
|
||||
vnet/bier/bier_fmask.c \
|
||||
vnet/bier/bier_fmask_db.c \
|
||||
vnet/bier/bier_input.c \
|
||||
vnet/bier/bier_lookup.c \
|
||||
vnet/bier/bier_output.c \
|
||||
vnet/bier/bier_table.c \
|
||||
vnet/bier/bier_types.c \
|
||||
vnet/bier/bier_test.c \
|
||||
vnet/bier/bier_api.c \
|
||||
vnet/bier/bier_drop.c \
|
||||
vnet/bier/bier_update.c \
|
||||
vnet/bier/bier_imp_node.c \
|
||||
vnet/bier/bier_imp.c \
|
||||
vnet/bier/bier_disp_entry.c \
|
||||
vnet/bier/bier_disp_lookup_node.c \
|
||||
vnet/bier/bier_disp_dispatch_node.c \
|
||||
vnet/bier/bier_disp_table.c
|
||||
|
||||
nobase_include_HEADERS += \
|
||||
vnet/bier/bier_types.h \
|
||||
vnet/bier/bier_entry.h \
|
||||
vnet/bier/bier_update.h \
|
||||
vnet/bier/bier.api.h \
|
||||
vnet/bier/bier_table.h
|
||||
|
||||
API_FILES += vnet/bier/bier.api
|
||||
|
||||
########################################
|
||||
# Plugin client library
|
||||
########################################
|
||||
|
||||
@@ -0,0 +1,268 @@
|
||||
/*
|
||||
* 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 vpp BIER control-plane API messages which are generally
|
||||
called through a shared memory interface.
|
||||
*/
|
||||
vl_api_version 1.0.0
|
||||
|
||||
/** \brief BIER Table Indentifier
|
||||
@param bt_set
|
||||
@param bt_sub_domain
|
||||
@param bt_bit_header_length
|
||||
*/
|
||||
typeonly define bier_table_id
|
||||
{
|
||||
u8 bt_set;
|
||||
u8 bt_sub_domain;
|
||||
u8 bt_hdr_len_id;
|
||||
};
|
||||
|
||||
/** \brief BIER Table Add / del route
|
||||
@param client_index - opaque cookie to identify the sender
|
||||
@param context - sender context, to match reply w/ request
|
||||
@param bt_tbl_id - The BIER table-id the route is added in
|
||||
@param bt_mpls_label - The MPLS label for the table
|
||||
@param bt_is_add - Is this a route add or delete
|
||||
*/
|
||||
autoreply define bier_table_add_del
|
||||
{
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
vl_api_bier_table_id_t bt_tbl_id;
|
||||
u32 bt_label;
|
||||
u8 bt_is_add;
|
||||
};
|
||||
|
||||
define bier_table_dump
|
||||
{
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
};
|
||||
|
||||
define bier_table_details
|
||||
{
|
||||
u32 context;
|
||||
u32 bt_label;
|
||||
vl_api_bier_table_id_t bt_tbl_id;
|
||||
};
|
||||
|
||||
/** \brief FIB path
|
||||
@param sw_if_index - index of the interface
|
||||
@param weight - The weight, for UCMP
|
||||
@param preference - The preference of the path. lowest preference is prefered
|
||||
@param is_local - local if non-zero, else remote
|
||||
@param is_drop - Drop the packet
|
||||
@param is_unreach - Drop the packet and rate limit send ICMP unreachable
|
||||
@param is_prohibit - Drop the packet and rate limit send ICMP prohibited
|
||||
@param afi - the afi of the next hop, IP46_TYPE_IP4=1, IP46_TYPE_IP6=2
|
||||
@param next_hop[16] - the next hop address
|
||||
|
||||
WARNING: this type is replicated, pending cleanup completion
|
||||
*/
|
||||
typeonly define fib_path3
|
||||
{
|
||||
u32 sw_if_index;
|
||||
u32 table_id;
|
||||
u8 weight;
|
||||
u8 preference;
|
||||
u8 is_local;
|
||||
u8 is_drop;
|
||||
u8 is_unreach;
|
||||
u8 is_prohibit;
|
||||
u8 afi;
|
||||
u8 next_hop[16];
|
||||
u32 rpf_id;
|
||||
u8 n_labels;
|
||||
u32 label_stack[16];
|
||||
};
|
||||
|
||||
/** \brief BIER Route Add / del route
|
||||
@param client_index - opaque cookie to identify the sender
|
||||
@param context - sender context, to match reply w/ request
|
||||
@param br_bp - The Bit-position value
|
||||
@param br_tbl_id - The BIER table-id the route is added in
|
||||
@param br_is_add - Is this a route add or delete
|
||||
@param br_is_replace - Are the paths specfied replacing those already
|
||||
present or are they to be combined.
|
||||
@param br_n_paths - The number of paths
|
||||
@param br_paths - The array of paths
|
||||
*/
|
||||
autoreply define bier_route_add_del
|
||||
{
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
u16 br_bp;
|
||||
u8 br_is_add;
|
||||
u8 br_is_replace;
|
||||
vl_api_bier_table_id_t br_tbl_id;
|
||||
u8 br_n_paths;
|
||||
vl_api_fib_path3_t br_paths[br_n_paths];
|
||||
};
|
||||
|
||||
define bier_route_dump
|
||||
{
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
vl_api_bier_table_id_t br_tbl_id;
|
||||
};
|
||||
|
||||
define bier_route_details
|
||||
{
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
u16 br_bp;
|
||||
vl_api_bier_table_id_t br_tbl_id;
|
||||
u32 br_n_paths;
|
||||
vl_api_fib_path3_t br_paths[br_n_paths];
|
||||
};
|
||||
|
||||
/** \brief BIER Imposition Add
|
||||
@param client_index - opaque cookie to identify the sender
|
||||
@param context - sender context, to match reply w/ request
|
||||
@param bi_tbl_id - The BIER table-id used to forward post encap
|
||||
@param bi_src - The source Bit-position in the encap.
|
||||
@param bi_is_add - Is this a route add or delete
|
||||
@param bi_n_bytes - The number of bytes in the following bit-string
|
||||
@param bi_bytes - The bit-string represented as a byte array
|
||||
*/
|
||||
define bier_imp_add
|
||||
{
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
vl_api_bier_table_id_t bi_tbl_id;
|
||||
u16 bi_src;
|
||||
u8 bi_is_add;
|
||||
u8 bi_n_bytes;
|
||||
u8 bi_bytes[bi_n_bytes];
|
||||
};
|
||||
|
||||
/** \brief Reply for BIER route add / del request
|
||||
@param context - returned sender context, to match reply w/ request
|
||||
@param retval - return code
|
||||
@param bi_index - The index of the created imposition object.
|
||||
*/
|
||||
define bier_imp_add_reply
|
||||
{
|
||||
u32 context;
|
||||
i32 retval;
|
||||
u32 bi_index;
|
||||
};
|
||||
|
||||
/** \brief BIER Imposition Del
|
||||
@param client_index - opaque cookie to identify the sender
|
||||
@param context - sender context, to match reply w/ request
|
||||
@param bi_index - The index of the imposition object (as returned
|
||||
from the ADD)
|
||||
*/
|
||||
autoreply define bier_imp_del
|
||||
{
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
u32 bi_index;
|
||||
};
|
||||
|
||||
define bier_imp_dump
|
||||
{
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
};
|
||||
|
||||
define bier_imp_details
|
||||
{
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
vl_api_bier_table_id_t bi_tbl_id;
|
||||
u16 bi_src;
|
||||
u8 bi_n_bytes;
|
||||
u8 bi_bytes[bi_n_bytes];
|
||||
};
|
||||
|
||||
/** \brief BIER Disposition Table Add / del route
|
||||
@param client_index - opaque cookie to identify the sender
|
||||
@param context - sender context, to match reply w/ request
|
||||
@param bt_tbl_id - The BIER Disposition table-id.
|
||||
*/
|
||||
autoreply define bier_disp_table_add_del
|
||||
{
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
u32 bdt_tbl_id;
|
||||
u8 bdt_is_add;
|
||||
};
|
||||
|
||||
define bier_disp_table_dump
|
||||
{
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
};
|
||||
|
||||
define bier_disp_table_details
|
||||
{
|
||||
u32 context;
|
||||
u32 bdt_tbl_id;
|
||||
};
|
||||
|
||||
/** \brief BIER Disposition Entry Add / del
|
||||
@param client_index - opaque cookie to identify the sender
|
||||
@param context - sender context, to match reply w/ request
|
||||
@param bde_bp - The Bit-position value for the entry
|
||||
@param bde_tbl_id - The BIER dispositiontable-id the route is added in
|
||||
@param bde_next_hop_sw_if_index - the nextop interface
|
||||
@param bde_is_add - Is this a route add or delete
|
||||
@param bde_payload_proto - The payload protocol for which the next-hop
|
||||
is added
|
||||
@param bde_next_hop_table_id - The table ID for the next-hop
|
||||
@param bde_next_hop_proto_is_ip4 - The next-hop is IPV4
|
||||
@param bde_next_hop[16] - the nextop address.
|
||||
Set this to all 0s for dispostion.
|
||||
*/
|
||||
autoreply define bier_disp_entry_add_del
|
||||
{
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
u16 bde_bp;
|
||||
u32 bde_tbl_id;
|
||||
u8 bde_is_add;
|
||||
u8 bde_payload_proto;
|
||||
u8 bde_n_paths;
|
||||
vl_api_fib_path3_t bde_paths[bde_n_paths];
|
||||
};
|
||||
|
||||
define bier_disp_entry_dump
|
||||
{
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
u32 bde_tbl_id;
|
||||
};
|
||||
|
||||
define bier_disp_entry_details
|
||||
{
|
||||
u32 context;
|
||||
u16 bde_bp;
|
||||
u32 bde_tbl_id;
|
||||
u8 bde_is_add;
|
||||
u8 bde_payload_proto;
|
||||
u8 bde_n_paths;
|
||||
vl_api_fib_path3_t bde_paths[bde_n_paths];
|
||||
};
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* eval: (c-set-style "gnu")
|
||||
* End:
|
||||
*/
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* 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/vnet.h>
|
||||
|
||||
#include <vnet/bier/bier_types.h>
|
||||
#include <vnet/bier/bier_bit_string.h>
|
||||
|
||||
/*
|
||||
* the first bit in the first byte is bit position 1.
|
||||
* bit position 0 is not valid
|
||||
*/
|
||||
#define BIER_GET_STRING_POS(_bp, _byte, _bit, _str) \
|
||||
{ \
|
||||
_bp--; \
|
||||
_byte = ((BIER_BBS_LEN_TO_BUCKETS((_str)->bbs_len) - 1 ) - \
|
||||
(_bp / BIER_BIT_MASK_BITS_PER_BUCKET)); \
|
||||
_bit = _bp % BIER_BIT_MASK_BITS_PER_BUCKET; \
|
||||
}
|
||||
|
||||
static inline int
|
||||
bier_bit_pos_is_valid (bier_bp_t bp, const bier_bit_string_t *bbs)
|
||||
{
|
||||
if (!((bp <= BIER_BBS_LEN_TO_BITS((bbs)->bbs_len)) &&
|
||||
(bp >= 1))) {
|
||||
return (0);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Validate a bit poistion
|
||||
*/
|
||||
#define BIER_BIT_POS_IS_VALID(_bp, _str) \
|
||||
{ \
|
||||
if (!bier_bit_pos_is_valid(_bp, _str)) return; \
|
||||
}
|
||||
|
||||
void
|
||||
bier_bit_string_set_bit (bier_bit_string_t *bit_string,
|
||||
bier_bp_t bp)
|
||||
{
|
||||
bier_bit_mask_bucket_t bmask;
|
||||
uint16_t byte_pos, bit_pos;
|
||||
|
||||
BIER_BIT_POS_IS_VALID(bp, bit_string);
|
||||
BIER_GET_STRING_POS(bp, byte_pos, bit_pos, bit_string);
|
||||
|
||||
bmask = ((bier_bit_mask_bucket_t)1 << bit_pos);
|
||||
bit_string->bbs_buckets[byte_pos] |= bmask;
|
||||
}
|
||||
|
||||
void
|
||||
bier_bit_string_clear_bit (bier_bit_string_t *bit_string,
|
||||
bier_bp_t bp)
|
||||
{
|
||||
uint16_t byte_pos, bit_pos;
|
||||
|
||||
BIER_BIT_POS_IS_VALID(bp, bit_string);
|
||||
BIER_GET_STRING_POS(bp, byte_pos, bit_pos, bit_string);
|
||||
|
||||
bit_string->bbs_buckets[byte_pos] &= ~(1 << bit_pos);
|
||||
}
|
||||
|
||||
u8 *
|
||||
format_bier_bit_string (u8 * string,
|
||||
va_list * args)
|
||||
{
|
||||
bier_bit_string_t *bs = va_arg(*args, bier_bit_string_t *);
|
||||
int leading_marker = 0;
|
||||
int suppress_zero = 0;
|
||||
u16 index;
|
||||
u32 *ptr;
|
||||
|
||||
ptr = (u32 *)bs->bbs_buckets;
|
||||
|
||||
string = format(string, "%d#", (8 * bs->bbs_len));
|
||||
|
||||
for (index = 0; index < (bs->bbs_len/4); index++) {
|
||||
if (!ptr[index]) {
|
||||
if (!leading_marker) {
|
||||
leading_marker = 1;
|
||||
suppress_zero = 1;
|
||||
string = format(string, ":");
|
||||
continue;
|
||||
}
|
||||
if (suppress_zero) continue;
|
||||
} else {
|
||||
suppress_zero = 0;
|
||||
}
|
||||
|
||||
string = format(string, "%s%X", index ? ":" : "",
|
||||
clib_net_to_host_u32(ptr[index]));
|
||||
}
|
||||
|
||||
return (string);
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* 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 __BIER_BIT_STRING_H__
|
||||
#define __BIER_BIT_STRING_H__
|
||||
|
||||
#include <vppinfra/byte_order.h>
|
||||
#include <vppinfra/format.h>
|
||||
|
||||
#include <vnet/bier/bier_types.h>
|
||||
|
||||
#define BIER_BBS_LEN_TO_BUCKETS(_len) (_len)
|
||||
#define BIER_BBS_LEN_TO_BITS(_len) (_len * 8)
|
||||
#define BIER_BBS_LEN_TO_INTS(_len) ((_len) / sizeof(int))
|
||||
#define BIER_BIT_MASK_BITS_PER_INT (sizeof(int) * 8)
|
||||
|
||||
/*
|
||||
* bier_find_first_bit_set
|
||||
*
|
||||
* find the position of the first bit set in a long
|
||||
*/
|
||||
static inline int
|
||||
bier_find_first_bit_string_set (int mask)
|
||||
{
|
||||
return (__builtin_ffs(clib_net_to_host_u32(mask)));
|
||||
}
|
||||
|
||||
extern void bier_bit_string_set_bit(bier_bit_string_t *mask,
|
||||
bier_bp_t bp);
|
||||
|
||||
|
||||
extern void bier_bit_string_clear_bit(bier_bit_string_t *mask,
|
||||
bier_bp_t bp);
|
||||
|
||||
|
||||
extern u8 *format_bier_bit_string(u8 * s, va_list * args);
|
||||
|
||||
#define BIER_BBS_NUM_INT_BUKCETS(_bbs) \
|
||||
(BIER_BBS_LEN_TO_BUCKETS(_bbs->bbs_len) / sizeof(int))
|
||||
|
||||
always_inline int
|
||||
bier_bit_string_is_zero (const bier_bit_string_t *src)
|
||||
{
|
||||
uint16_t index;
|
||||
|
||||
for (index = 0;
|
||||
index < BIER_BBS_NUM_INT_BUKCETS(src);
|
||||
index++) {
|
||||
if (((int*)src->bbs_buckets)[index] != 0) {
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
always_inline void
|
||||
bier_bit_string_clear_string (const bier_bit_string_t *src,
|
||||
bier_bit_string_t *dest)
|
||||
{
|
||||
uint16_t index;
|
||||
|
||||
ASSERT(src->bbs_len == dest->bbs_len);
|
||||
|
||||
for (index = 0;
|
||||
index < BIER_BBS_NUM_INT_BUKCETS(src);
|
||||
index++) {
|
||||
((int*)dest->bbs_buckets)[index] &= ~(((int*)src->bbs_buckets)[index]);
|
||||
}
|
||||
}
|
||||
|
||||
always_inline void
|
||||
bier_bit_string_logical_and_string (const bier_bit_string_t *src,
|
||||
bier_bit_string_t *dest)
|
||||
{
|
||||
uint16_t index;
|
||||
|
||||
ASSERT(src->bbs_len == dest->bbs_len);
|
||||
|
||||
for (index = 0;
|
||||
index < BIER_BBS_NUM_INT_BUKCETS(src);
|
||||
index++) {
|
||||
((int*)dest->bbs_buckets)[index] &= ((int*)src->bbs_buckets)[index];
|
||||
}
|
||||
}
|
||||
|
||||
always_inline void
|
||||
bier_bit_string_init (bier_bit_string_t *bbs,
|
||||
bier_hdr_len_id_t len,
|
||||
bier_bit_mask_bucket_t *buckets)
|
||||
{
|
||||
bbs->bbs_len = bier_hdr_len_id_to_num_bytes(len);
|
||||
bbs->bbs_buckets = buckets;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* 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/bier/bier_disp_entry.h>
|
||||
#include <vnet/bier/bier_hdr_inlines.h>
|
||||
|
||||
/**
|
||||
* @brief A struct to hold tracing information for the MPLS label imposition
|
||||
* node.
|
||||
*/
|
||||
typedef struct bier_disp_dispatch_trace_t_
|
||||
{
|
||||
/**
|
||||
* BIER payload protocol used to dispatch
|
||||
*/
|
||||
bier_hdr_proto_id_t pproto;
|
||||
|
||||
/**
|
||||
* RPF-ID packet is tagged with
|
||||
*/
|
||||
u32 rpf_id;
|
||||
} bier_disp_dispatch_trace_t;
|
||||
|
||||
always_inline uword
|
||||
bier_disp_dispatch_inline (vlib_main_t * vm,
|
||||
vlib_node_runtime_t * node,
|
||||
vlib_frame_t * from_frame)
|
||||
{
|
||||
u32 n_left_from, next_index, * from, * to_next;
|
||||
|
||||
from = vlib_frame_vector_args (from_frame);
|
||||
n_left_from = from_frame->n_vectors;
|
||||
|
||||
next_index = node->cached_next_index;
|
||||
|
||||
while (n_left_from > 0)
|
||||
{
|
||||
u32 n_left_to_next;
|
||||
|
||||
vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
|
||||
|
||||
while (n_left_from > 0 && n_left_to_next > 0)
|
||||
{
|
||||
bier_hdr_proto_id_t pproto0;
|
||||
bier_disp_entry_t *bde0;
|
||||
u32 next0, bi0, bdei0;
|
||||
const dpo_id_t *dpo0;
|
||||
vlib_buffer_t * b0;
|
||||
bier_hdr_t *hdr0;
|
||||
u32 entropy0;
|
||||
|
||||
bi0 = from[0];
|
||||
to_next[0] = bi0;
|
||||
from += 1;
|
||||
to_next += 1;
|
||||
n_left_from -= 1;
|
||||
n_left_to_next -= 1;
|
||||
|
||||
b0 = vlib_get_buffer (vm, bi0);
|
||||
bdei0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
|
||||
hdr0 = vlib_buffer_get_current(b0);
|
||||
bde0 = bier_disp_entry_get(bdei0);
|
||||
|
||||
/*
|
||||
* header is in network order - flip it, we are about to
|
||||
* consume it anyway
|
||||
*/
|
||||
bier_hdr_ntoh(hdr0);
|
||||
pproto0 = bier_hdr_get_proto_id(hdr0);
|
||||
entropy0 = bier_hdr_get_entropy(hdr0);
|
||||
|
||||
/*
|
||||
* strip the header and copy the entropy value into
|
||||
* the packets flow-hash field
|
||||
* DSCP mumble mumble...
|
||||
*/
|
||||
vlib_buffer_advance(b0, (vnet_buffer(b0)->bier.n_bytes +
|
||||
sizeof(*hdr0)));
|
||||
vnet_buffer(b0)->ip.flow_hash = entropy0;
|
||||
|
||||
/*
|
||||
* use the payload proto to dispatch to the
|
||||
* correct stacked DPO.
|
||||
*/
|
||||
dpo0 = &bde0->bde_fwd[pproto0].bde_dpo;
|
||||
next0 = dpo0->dpoi_next_node;
|
||||
vnet_buffer(b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
|
||||
vnet_buffer(b0)->ip.rpf_id = bde0->bde_fwd[pproto0].bde_rpf_id;
|
||||
|
||||
if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
|
||||
{
|
||||
bier_disp_dispatch_trace_t *tr =
|
||||
vlib_add_trace (vm, node, b0, sizeof (*tr));
|
||||
tr->pproto = pproto0;
|
||||
tr->rpf_id = vnet_buffer(b0)->ip.rpf_id;
|
||||
}
|
||||
|
||||
vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
|
||||
n_left_to_next, bi0, next0);
|
||||
}
|
||||
vlib_put_next_frame (vm, node, next_index, n_left_to_next);
|
||||
}
|
||||
return from_frame->n_vectors;
|
||||
}
|
||||
|
||||
static u8 *
|
||||
format_bier_disp_dispatch_trace (u8 * s, va_list * args)
|
||||
{
|
||||
CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
|
||||
CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
|
||||
bier_disp_dispatch_trace_t * t;
|
||||
|
||||
t = va_arg (*args, bier_disp_dispatch_trace_t *);
|
||||
s = format (s, "%U", format_bier_hdr_proto, t->pproto);
|
||||
|
||||
return (s);
|
||||
}
|
||||
|
||||
static uword
|
||||
bier_disp_dispatch (vlib_main_t * vm,
|
||||
vlib_node_runtime_t * node,
|
||||
vlib_frame_t * frame)
|
||||
{
|
||||
return (bier_disp_dispatch_inline(vm, node, frame));
|
||||
}
|
||||
|
||||
VLIB_REGISTER_NODE (bier_disp_dispatch_node) = {
|
||||
.function = bier_disp_dispatch,
|
||||
.name = "bier-disp-dispatch",
|
||||
.vector_size = sizeof (u32),
|
||||
|
||||
.format_trace = format_bier_disp_dispatch_trace,
|
||||
.n_next_nodes = 1,
|
||||
.next_nodes = {
|
||||
[0] = "bier-drop",
|
||||
}
|
||||
};
|
||||
VLIB_NODE_FUNCTION_MULTIARCH (bier_disp_dispatch_node, bier_disp_dispatch)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
/**
|
||||
* bier_dispositon : The BIER dispositon object
|
||||
*
|
||||
* A BIER dispositon object is used to pop the BIER header for for-us
|
||||
* packets and steer the packet down the payload protocol specific graph
|
||||
*/
|
||||
|
||||
#ifndef __BIER_DISP_ENTRY_H__
|
||||
#define __BIER_DISP_ENTRY_H__
|
||||
|
||||
#include <vnet/bier/bier_types.h>
|
||||
#include <vnet/fib/fib_types.h>
|
||||
#include <vnet/dpo/dpo.h>
|
||||
|
||||
/**
|
||||
* The BIER dispositon object
|
||||
*/
|
||||
typedef struct bier_disp_entry_t_ {
|
||||
/**
|
||||
* The DPO contirubted from the per-payload protocol parents
|
||||
* on cachline 1.
|
||||
*/
|
||||
struct
|
||||
{
|
||||
dpo_id_t bde_dpo;
|
||||
u32 bde_rpf_id;
|
||||
} bde_fwd[BIER_HDR_N_PROTO];
|
||||
|
||||
/**
|
||||
* number of locks
|
||||
*/
|
||||
u32 bde_locks;
|
||||
|
||||
/**
|
||||
* The path-lists used by per-payload protocol parents.
|
||||
* We don't add the disp entry to the graph as a sibling
|
||||
* since there is nothing we can do with the updates to
|
||||
* forwarding.
|
||||
*/
|
||||
fib_node_index_t bde_pl[BIER_HDR_N_PROTO];
|
||||
} bier_disp_entry_t;
|
||||
|
||||
extern index_t bier_disp_entry_add_or_lock(void);
|
||||
extern void bier_disp_entry_path_add(index_t bdei,
|
||||
bier_hdr_proto_id_t pproto,
|
||||
const fib_route_path_t *rpaths);
|
||||
extern int bier_disp_entry_path_remove(index_t bdei,
|
||||
bier_hdr_proto_id_t pproto,
|
||||
const fib_route_path_t *rpaths);
|
||||
|
||||
extern void bier_disp_entry_unlock(index_t bdi);
|
||||
extern void bier_disp_entry_lock(index_t bdi);
|
||||
|
||||
extern u8* format_bier_disp_entry(u8* s, va_list *ap);
|
||||
|
||||
extern void bier_disp_entry_contribute_forwarding(index_t bdi,
|
||||
dpo_id_t *dpo);
|
||||
|
||||
extern bier_disp_entry_t *bier_disp_entry_pool;
|
||||
|
||||
always_inline bier_disp_entry_t*
|
||||
bier_disp_entry_get (index_t bdi)
|
||||
{
|
||||
return (pool_elt_at_index(bier_disp_entry_pool, bdi));
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* 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/bier/bier_disp_table.h>
|
||||
#include <vnet/bier/bier_hdr_inlines.h>
|
||||
|
||||
/**
|
||||
* @brief A struct to hold tracing information for the MPLS label imposition
|
||||
* node.
|
||||
*/
|
||||
typedef struct bier_disp_lookup_trace_t_
|
||||
{
|
||||
/**
|
||||
* BIER source BP used in the lookup - host order
|
||||
*/
|
||||
bier_bp_t bp;
|
||||
/**
|
||||
* BIER disp table
|
||||
*/
|
||||
index_t bdti;
|
||||
} bier_disp_lookup_trace_t;
|
||||
|
||||
/**
|
||||
* Next nodes from BIER disposition lookup
|
||||
*/
|
||||
typedef enum bier_disp_lookup_next_t_
|
||||
{
|
||||
BIER_DISP_LOOKUP_NEXT_DROP,
|
||||
BIER_DISP_LOOKUP_NEXT_DISPATCH,
|
||||
} bier_disp_lookup_next_t;
|
||||
#define BIER_DISP_LOOKUP_N_NEXT (BIER_DISP_LOOKUP_NEXT_DISPATCH+1)
|
||||
|
||||
always_inline uword
|
||||
bier_disp_lookup_inline (vlib_main_t * vm,
|
||||
vlib_node_runtime_t * node,
|
||||
vlib_frame_t * from_frame)
|
||||
{
|
||||
u32 n_left_from, next_index, * from, * to_next;
|
||||
|
||||
from = vlib_frame_vector_args (from_frame);
|
||||
n_left_from = from_frame->n_vectors;
|
||||
|
||||
next_index = node->cached_next_index;
|
||||
|
||||
while (n_left_from > 0)
|
||||
{
|
||||
u32 n_left_to_next;
|
||||
|
||||
vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
|
||||
|
||||
while (n_left_from > 0 && n_left_to_next > 0)
|
||||
{
|
||||
const bier_hdr_t *hdr0;
|
||||
vlib_buffer_t * b0;
|
||||
u32 bdei0, bdti0;
|
||||
u32 next0, bi0;
|
||||
|
||||
bi0 = from[0];
|
||||
to_next[0] = bi0;
|
||||
from += 1;
|
||||
to_next += 1;
|
||||
n_left_from -= 1;
|
||||
n_left_to_next -= 1;
|
||||
|
||||
b0 = vlib_get_buffer (vm, bi0);
|
||||
|
||||
bdti0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
|
||||
hdr0 = vlib_buffer_get_current(b0);
|
||||
|
||||
/*
|
||||
* lookup - source is in network order.
|
||||
*/
|
||||
bdei0 = bier_disp_table_lookup(bdti0, bier_hdr_get_src_id(hdr0));
|
||||
|
||||
if (PREDICT_FALSE(INDEX_INVALID == bdei0))
|
||||
{
|
||||
next0 = BIER_DISP_LOOKUP_NEXT_DROP;
|
||||
}
|
||||
else
|
||||
{
|
||||
next0 = BIER_DISP_LOOKUP_NEXT_DISPATCH;
|
||||
}
|
||||
|
||||
vnet_buffer(b0)->ip.adj_index[VLIB_TX] = bdei0;
|
||||
|
||||
if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
|
||||
{
|
||||
bier_disp_lookup_trace_t *tr =
|
||||
vlib_add_trace (vm, node, b0, sizeof (*tr));
|
||||
tr->bp = clib_net_to_host_u16(bier_hdr_get_src_id(hdr0));
|
||||
tr->bdti = bdti0;
|
||||
}
|
||||
|
||||
vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
|
||||
n_left_to_next, bi0, next0);
|
||||
}
|
||||
vlib_put_next_frame (vm, node, next_index, n_left_to_next);
|
||||
}
|
||||
return from_frame->n_vectors;
|
||||
}
|
||||
|
||||
static u8 *
|
||||
format_bier_disp_lookup_trace (u8 * s, va_list * args)
|
||||
{
|
||||
CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
|
||||
CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
|
||||
bier_disp_lookup_trace_t * t;
|
||||
|
||||
t = va_arg (*args, bier_disp_lookup_trace_t *);
|
||||
s = format (s, "tbl:%d src:%d", t->bdti, t->bp);
|
||||
|
||||
return (s);
|
||||
}
|
||||
|
||||
static uword
|
||||
bier_disp_lookup (vlib_main_t * vm,
|
||||
vlib_node_runtime_t * node,
|
||||
vlib_frame_t * frame)
|
||||
{
|
||||
return (bier_disp_lookup_inline(vm, node, frame));
|
||||
}
|
||||
|
||||
VLIB_REGISTER_NODE (bier_disp_lookup_node) = {
|
||||
.function = bier_disp_lookup,
|
||||
.name = "bier-disp-lookup",
|
||||
.vector_size = sizeof (u32),
|
||||
|
||||
.format_trace = format_bier_disp_lookup_trace,
|
||||
.n_next_nodes = BIER_DISP_LOOKUP_N_NEXT,
|
||||
.next_nodes = {
|
||||
[BIER_DISP_LOOKUP_NEXT_DROP] = "bier-drop",
|
||||
[BIER_DISP_LOOKUP_NEXT_DISPATCH] = "bier-disp-dispatch",
|
||||
}
|
||||
};
|
||||
VLIB_NODE_FUNCTION_MULTIARCH (bier_disp_lookup_node, bier_disp_lookup)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* 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 __BIER_DISP_TABLE_H__
|
||||
#define __BIER_DISP_TABLE_H__
|
||||
|
||||
#include <vnet/ip/ip.h>
|
||||
#include <vnet/adj/adj.h>
|
||||
#include <vnet/dpo/replicate_dpo.h>
|
||||
|
||||
#include <vnet/bier/bier_types.h>
|
||||
#include <vnet/bier/bier_disp_entry.h>
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* A protocol Independent IP multicast FIB table
|
||||
*/
|
||||
typedef struct bier_disp_table_t_
|
||||
{
|
||||
/**
|
||||
* number of locks on the table
|
||||
*/
|
||||
u16 bdt_locks;
|
||||
|
||||
/**
|
||||
* Table ID (hash key) for this FIB.
|
||||
*/
|
||||
u32 bdt_table_id;
|
||||
|
||||
/**
|
||||
* The lookup DB based on sender BP. Value is the index of the
|
||||
* BIER disp object.
|
||||
*/
|
||||
index_t bdt_db[BIER_BP_MAX];
|
||||
} bier_disp_table_t;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* Format the description/name of the table
|
||||
*/
|
||||
extern u8* format_bier_disp_table(u8* s, va_list *ap);
|
||||
|
||||
extern void bier_disp_table_entry_path_add(u32 table_id,
|
||||
bier_bp_t src,
|
||||
bier_hdr_proto_id_t payload_proto,
|
||||
const fib_route_path_t *rpath);
|
||||
|
||||
extern void bier_disp_table_entry_path_remove(u32 table_id,
|
||||
bier_bp_t src,
|
||||
bier_hdr_proto_id_t payload_proto,
|
||||
const fib_route_path_t *paths);
|
||||
|
||||
extern index_t bier_disp_table_find(u32 table_id);
|
||||
|
||||
|
||||
extern index_t bier_disp_table_add_or_lock(u32 table_id);
|
||||
extern void bier_disp_table_unlock_w_table_id(u32 table_id);
|
||||
|
||||
extern void bier_disp_table_unlock(index_t bdti);
|
||||
extern void bier_disp_table_lock(index_t bdti);
|
||||
extern void bier_disp_table_contribute_forwarding(index_t bdti,
|
||||
dpo_id_t *dpo);
|
||||
|
||||
/**
|
||||
* Types and functions to walk all the entries in one BIER Table
|
||||
*/
|
||||
typedef void (*bier_disp_table_walk_fn_t)(const bier_disp_table_t *bdt,
|
||||
const bier_disp_entry_t *bde,
|
||||
u16 bp,
|
||||
void *ctx);
|
||||
extern void bier_disp_table_walk(u32 table_id,
|
||||
bier_disp_table_walk_fn_t fn,
|
||||
void *ctx);
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* Get a pointer to a FIB table
|
||||
*/
|
||||
extern bier_disp_table_t *bier_disp_table_pool;
|
||||
|
||||
static inline bier_disp_table_t *
|
||||
bier_disp_table_get (index_t bdti)
|
||||
{
|
||||
return (pool_elt_at_index(bier_disp_table_pool, bdti));
|
||||
}
|
||||
|
||||
static inline index_t
|
||||
bier_disp_table_lookup (index_t bdti,
|
||||
bier_bp_t src)
|
||||
{
|
||||
bier_disp_table_t *bdt;
|
||||
|
||||
bdt = bier_disp_table_get(bdti);
|
||||
|
||||
return (bdt->bdt_db[src]);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* 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/buffer.h>
|
||||
#include <vlib/vlib.h>
|
||||
#include <vnet/dpo/dpo.h>
|
||||
|
||||
#include <vnet/bier/bier_hdr_inlines.h>
|
||||
|
||||
typedef struct bier_drop_trace_t_
|
||||
{
|
||||
index_t dpi;
|
||||
} bier_drop_trace_t;
|
||||
|
||||
static void
|
||||
bier_drop_trace (vlib_main_t * vm,
|
||||
vlib_node_runtime_t * node,
|
||||
vlib_frame_t * frame)
|
||||
{
|
||||
u32 *from, n_left;
|
||||
|
||||
n_left = frame->n_vectors;
|
||||
from = vlib_frame_vector_args (frame);
|
||||
while (n_left >= 1)
|
||||
{
|
||||
u32 bi0;
|
||||
vlib_buffer_t *b0;
|
||||
bier_drop_trace_t *t0;
|
||||
|
||||
bi0 = from[0];
|
||||
|
||||
b0 = vlib_get_buffer (vm, bi0);
|
||||
|
||||
if (b0->flags & VLIB_BUFFER_IS_TRACED)
|
||||
{
|
||||
t0 = vlib_add_trace (vm, node, b0, sizeof(*t0));
|
||||
|
||||
t0->dpi = vnet_buffer (b0)->ip.adj_index[VLIB_TX];
|
||||
}
|
||||
from += 1;
|
||||
n_left -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
static uword
|
||||
bier_drop (vlib_main_t * vm,
|
||||
vlib_node_runtime_t * node,
|
||||
vlib_frame_t * frame)
|
||||
{
|
||||
u32 *buffers = vlib_frame_vector_args (frame);
|
||||
uword n_packets = frame->n_vectors;
|
||||
|
||||
vlib_error_drop_buffers (vm, node, buffers,
|
||||
/* stride */ 1,
|
||||
n_packets,
|
||||
/* next */ 0,
|
||||
0, // bier_input_node.index,
|
||||
0);
|
||||
|
||||
if (node->flags & VLIB_NODE_FLAG_TRACE)
|
||||
bier_drop_trace (vm, node, frame);
|
||||
|
||||
return n_packets;
|
||||
}
|
||||
|
||||
static u8 *
|
||||
format_bier_drop_trace (u8 * s, va_list * args)
|
||||
{
|
||||
CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
|
||||
CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
|
||||
bier_drop_trace_t *t = va_arg (*args, bier_drop_trace_t *);
|
||||
|
||||
s = format (s, "dpo-idx %d", t->dpi);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
VLIB_REGISTER_NODE (bier_drop_node, static) =
|
||||
{
|
||||
.function = bier_drop,.
|
||||
name = "bier-drop",
|
||||
.vector_size = sizeof (u32),
|
||||
.format_trace = format_bier_drop_trace,
|
||||
.n_next_nodes = 1,
|
||||
.next_nodes = {
|
||||
[0] = "error-drop",
|
||||
},
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
/**
|
||||
* bier_entry : The BIER entry
|
||||
*
|
||||
* The interface to the BIER entry is through a bier_entry_t* rather
|
||||
* than an index. This is becuase the BIER table allocates the entries
|
||||
* in a contiguous array once and only once when the table is created.
|
||||
* this is done for forwarding performance. The entry is thus not subject
|
||||
* to realloc, and does not need to be malloc'd when a route to that
|
||||
* bit-position is first learned.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __BIER_ENTRY_H__
|
||||
#define __BIER_ENTRY_H__
|
||||
|
||||
#include <vlib/vlib.h>
|
||||
#include <vnet/fib/fib_node.h>
|
||||
#include <vnet/bier/bier_types.h>
|
||||
|
||||
/**
|
||||
* Forward declarations
|
||||
*/
|
||||
struct bier_route_update_t_;
|
||||
struct bier_fmask_db_t_;
|
||||
|
||||
/**
|
||||
* The BIER entry
|
||||
*
|
||||
* the BIER entry is the representation of a BIER forwarding egress router (BFER)
|
||||
* (or the egress PE) that is assigned a bit position.
|
||||
*/
|
||||
typedef struct bier_entry_t_ {
|
||||
/**
|
||||
* linkage into the FIB graph
|
||||
*/
|
||||
fib_node_t be_node;
|
||||
|
||||
/**
|
||||
* The index of the BIER table in which this entry resides
|
||||
*/
|
||||
index_t be_bti;
|
||||
|
||||
/**
|
||||
* the bit position this entry represents.
|
||||
* this is the key table insertion
|
||||
*/
|
||||
bier_bp_t be_bp;
|
||||
|
||||
/**
|
||||
* the FIB path-list this entry resolves through.
|
||||
* the path-list is itself resoved on the entry's fmasks
|
||||
*/
|
||||
fib_node_index_t be_path_list;
|
||||
/**
|
||||
* sibling index on the path list
|
||||
*/
|
||||
fib_node_index_t be_sibling_index;
|
||||
} bier_entry_t;
|
||||
|
||||
extern index_t bier_entry_create(index_t bti,
|
||||
bier_bp_t bp);
|
||||
extern void bier_entry_delete(index_t bei);
|
||||
|
||||
extern void bier_entry_path_add(index_t bei,
|
||||
const fib_route_path_t *brp);
|
||||
|
||||
extern int bier_entry_path_remove(index_t bei,
|
||||
const fib_route_path_t *brp);
|
||||
|
||||
extern u8* format_bier_entry(u8* s, va_list *ap);
|
||||
|
||||
extern void bier_entry_contribute_forwarding(index_t bei,
|
||||
dpo_id_t *dpo);
|
||||
|
||||
extern bier_entry_t *bier_entry_pool;
|
||||
always_inline bier_entry_t* bier_entry_get(index_t bei)
|
||||
{
|
||||
return (&bier_entry_pool[bei]);
|
||||
}
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
* 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 bier_fmask : The BIER fmask
|
||||
*
|
||||
* The BIER fmask contains the bitString that is applied to packets that
|
||||
* egress towards the next-hop. As such the fmask is part of the rewrite
|
||||
* (adj) for that next-hop. It it thus an extension of the next-hop and in
|
||||
* no way associated with the bit-position(s) that are reachable through it.
|
||||
* Fmasks are thus shared by bit-positions that egress throught the same
|
||||
* nh (BFR-NBR).
|
||||
* Deag fmasks are also shread in the event that a router has local
|
||||
* bit-positions. This is necessary to prevent the router recieving two copies
|
||||
* of each packet. Consequently it also means that they share the same
|
||||
* disposition data for the global data.
|
||||
*/
|
||||
|
||||
#ifndef __BIER_FMASK_H__
|
||||
#define __BIER_FMASK_H__
|
||||
|
||||
#include <vlib/vlib.h>
|
||||
|
||||
#include <vnet/fib/fib_node.h>
|
||||
#include <vnet/mpls/packet.h>
|
||||
#include <vnet/dpo/dpo.h>
|
||||
|
||||
#include <vnet/bier/bier_types.h>
|
||||
#include <vnet/bier/bier_fmask_db.h>
|
||||
|
||||
/**
|
||||
* A struct that represents the reference counting of the bits
|
||||
*/
|
||||
typedef struct bier_fmask_bits_t_ {
|
||||
/**
|
||||
* each bit in the mask needs to be reference counted
|
||||
* and set/cleared on the 0->1 and 1->0 transitions.
|
||||
*/
|
||||
bier_bit_string_t bfmb_input_reset_string;
|
||||
u32 *bfmb_refs;
|
||||
|
||||
/**
|
||||
* The total number of references to bits set on this mask
|
||||
* in effect a count of the number of children.
|
||||
*/
|
||||
uint32_t bfmb_count;
|
||||
} bier_fmask_bits_t;
|
||||
|
||||
/**
|
||||
* Flags on fmask
|
||||
*/
|
||||
typedef enum bier_fmask_attributes_t_
|
||||
{
|
||||
BIER_FMASK_ATTR_FIRST,
|
||||
BIER_FMASK_ATTR_FORWARDING = BIER_FMASK_ATTR_FIRST,
|
||||
BIER_FMASK_ATTR_DISP,
|
||||
BIER_FMASK_ATTR_LAST = BIER_FMASK_ATTR_DISP,
|
||||
} bier_fmask_attributes_t;
|
||||
|
||||
#define BIER_FMASK_ATTR_NAMES { \
|
||||
[BIER_FMASK_ATTR_FORWARDING] = "forwarding", \
|
||||
[BIER_FMASK_ATTR_DISP] = "disposition", \
|
||||
}
|
||||
|
||||
#define FOR_EACH_BIER_FMASK_ATTR(_item) \
|
||||
for (_item = BIER_FMASK_ATTR_FIRST; \
|
||||
_item <= BIER_FMASK_ATTR_LAST; \
|
||||
_item++)
|
||||
|
||||
typedef enum bier_fmask_flags_t_
|
||||
{
|
||||
BIER_FMASK_FLAG_FORWARDING = (1 << BIER_FMASK_ATTR_FORWARDING),
|
||||
BIER_FMASK_FLAG_DISP = (1 << BIER_FMASK_ATTR_DISP),
|
||||
} bier_fmask_flags_t;
|
||||
|
||||
/**
|
||||
* An outgoing BIER mask. aka forwarding bit mask (in the RFCs)
|
||||
*
|
||||
* This mask's function is two-fold
|
||||
* 1 - it is logical-AND with the input packet header to produce the
|
||||
* output packet header
|
||||
* 2 - it is logical NAND with the input packet header to modify the bit-mask
|
||||
* for the next lookup
|
||||
*/
|
||||
typedef struct bier_fmask_t_ {
|
||||
/**
|
||||
* The BIER fmask is a child of a FIB entry in the FIB graph.
|
||||
*/
|
||||
fib_node_t bfm_node;
|
||||
|
||||
/**
|
||||
* operational/state flags on the fmask
|
||||
*/
|
||||
bier_fmask_flags_t bfm_flags;
|
||||
|
||||
/**
|
||||
* The bits, and their ref counts, that are set on this mask
|
||||
* This mask changes as BIER entries link to and from this fmask
|
||||
*/
|
||||
bier_fmask_bits_t bfm_bits;
|
||||
|
||||
struct
|
||||
{
|
||||
/**
|
||||
* The key to this fmask - used for store/lookup in the DB
|
||||
*/
|
||||
bier_fmask_id_t bfm_id;
|
||||
|
||||
/**
|
||||
* The BIER Table this Fmask is used in
|
||||
*/
|
||||
index_t bfm_fib_index;
|
||||
};
|
||||
|
||||
union
|
||||
{
|
||||
/**
|
||||
* For forwarding via a next-hop
|
||||
*/
|
||||
struct
|
||||
{
|
||||
/**
|
||||
* The parent fib entry
|
||||
*/
|
||||
fib_node_index_t bfm_fei;
|
||||
/**
|
||||
* The MPLS label to paint on the header during forwarding
|
||||
*/
|
||||
mpls_label_t bfm_label;
|
||||
};
|
||||
|
||||
/**
|
||||
* For disposition
|
||||
*/
|
||||
struct
|
||||
{
|
||||
/**
|
||||
* The parent disposition table object
|
||||
*/
|
||||
index_t bfm_disp;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* the index of this fmask in the parent's child list.
|
||||
*/
|
||||
u32 bfm_sibling;
|
||||
|
||||
/**
|
||||
* The index into the adj table for the adj that
|
||||
* this fmask resolves via
|
||||
*/
|
||||
dpo_id_t bfm_dpo;
|
||||
} bier_fmask_t;
|
||||
|
||||
extern void bier_fmask_link(index_t bfmi, bier_bp_t bp);
|
||||
extern void bier_fmask_unlink(index_t bfmi, bier_bp_t bp);
|
||||
extern void bier_fmask_unlock(index_t bfmi);
|
||||
extern void bier_fmask_lock(index_t bfmi);
|
||||
|
||||
extern index_t bier_fmask_create_and_lock(const bier_fmask_id_t *fmid,
|
||||
index_t bti,
|
||||
const fib_route_path_t *rpath);
|
||||
|
||||
extern u8* format_bier_fmask(u8 *s, va_list *ap);
|
||||
|
||||
extern void bier_fmask_contribute_forwarding(index_t bfmi,
|
||||
dpo_id_t *dpo);
|
||||
|
||||
extern u32 bier_fmask_child_add (fib_node_index_t fib_entry_index,
|
||||
fib_node_type_t child_type,
|
||||
fib_node_index_t child_index);
|
||||
extern void bier_fmask_child_remove (fib_node_index_t fib_entry_index,
|
||||
u32 sibling_index);
|
||||
|
||||
/*
|
||||
* provided for fast data-path access
|
||||
*/
|
||||
bier_fmask_t *bier_fmask_pool;
|
||||
|
||||
static inline bier_fmask_t *
|
||||
bier_fmask_get (u32 index)
|
||||
{
|
||||
return (pool_elt_at_index(bier_fmask_pool, index));
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* 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/bier/bier_fmask_db.h>
|
||||
#include <vnet/bier/bier_fmask.h>
|
||||
|
||||
/**
|
||||
* Global Table of fmask objects
|
||||
* The key into this table includes the table's key and the fmask's key,
|
||||
* so there could be a DB per-table. But it is more efficient
|
||||
* at forwarding time to extract the fmask from a single global table
|
||||
* which is hot in dcache.
|
||||
*
|
||||
* The table's key is part of this DB key, since the fmasks therein build up
|
||||
* their forwarding mask based on the routes that resolve through
|
||||
* it, so cross polination would be bad.
|
||||
*/
|
||||
typedef struct bier_fmask_db_t_ {
|
||||
/**
|
||||
* hash table for underlying storage
|
||||
*/
|
||||
mhash_t bfdb_hash;
|
||||
|
||||
/**
|
||||
* Pool for memory
|
||||
*/
|
||||
struct bier_fmask_t_ *bfdb_pool;
|
||||
} bier_fmask_db_t;
|
||||
|
||||
/**
|
||||
* The key used in the fmask DB to compare fmask objects.
|
||||
* There is one global DB, so we need to use the table's ID and the fmasks ID
|
||||
*/
|
||||
typedef struct bier_fmask_db_key_t_ {
|
||||
bier_fmask_id_t bfmdbk_fm_id;
|
||||
index_t bfmdbk_tbl_id;
|
||||
} bier_fmask_db_key_t;
|
||||
// TODO packed?
|
||||
|
||||
/**
|
||||
* Single fmask DB
|
||||
*/
|
||||
static bier_fmask_db_t bier_fmask_db;
|
||||
|
||||
|
||||
u32
|
||||
bier_fmask_get_index (const bier_fmask_t *bfm)
|
||||
{
|
||||
return (bfm - bier_fmask_db.bfdb_pool);
|
||||
}
|
||||
|
||||
u32
|
||||
bier_fmask_db_find_or_create_and_lock (index_t bti,
|
||||
const bier_fmask_id_t *fmid,
|
||||
const fib_route_path_t *rpath)
|
||||
{
|
||||
bier_fmask_db_key_t key;
|
||||
u32 index;
|
||||
uword *p;
|
||||
|
||||
/*
|
||||
* there be padding in that thar key, and it's
|
||||
* used as a memcmp in the mhash.
|
||||
*/
|
||||
memset(&key, 0, sizeof(key));
|
||||
key.bfmdbk_tbl_id = bti;
|
||||
key.bfmdbk_fm_id = *fmid;
|
||||
|
||||
index = INDEX_INVALID;
|
||||
p = mhash_get (&bier_fmask_db.bfdb_hash, &key);
|
||||
|
||||
if (NULL == p)
|
||||
{
|
||||
/*
|
||||
* adding a new fmask object
|
||||
*/
|
||||
index = bier_fmask_create_and_lock(fmid, bti, rpath);
|
||||
|
||||
mhash_set (&bier_fmask_db.bfdb_hash, &key, index, 0 /*old_value*/);
|
||||
}
|
||||
else
|
||||
{
|
||||
index = p[0];
|
||||
bier_fmask_lock(index);
|
||||
}
|
||||
|
||||
return (index);
|
||||
}
|
||||
|
||||
u32
|
||||
bier_fmask_db_find (index_t bti,
|
||||
const bier_fmask_id_t *fmid)
|
||||
{
|
||||
bier_fmask_db_key_t key;
|
||||
u32 index;
|
||||
uword *p;
|
||||
|
||||
/*
|
||||
* there be padding in that thar key, and it's
|
||||
* used as a memcmp in the mhash.
|
||||
*/
|
||||
memset(&key, 0, sizeof(key));
|
||||
key.bfmdbk_tbl_id = bti;
|
||||
key.bfmdbk_fm_id = *fmid;
|
||||
|
||||
index = INDEX_INVALID;
|
||||
p = mhash_get(&bier_fmask_db.bfdb_hash, &key);
|
||||
|
||||
if (NULL != p)
|
||||
{
|
||||
index = p[0];
|
||||
}
|
||||
|
||||
return (index);
|
||||
}
|
||||
|
||||
void
|
||||
bier_fmask_db_remove (index_t bti,
|
||||
const bier_fmask_id_t *fmid)
|
||||
{
|
||||
bier_fmask_db_key_t key = {
|
||||
.bfmdbk_tbl_id = bti,
|
||||
.bfmdbk_fm_id = *fmid,
|
||||
};
|
||||
uword *p;
|
||||
|
||||
p = mhash_get (&bier_fmask_db.bfdb_hash, &key);
|
||||
|
||||
if (NULL == p) {
|
||||
/*
|
||||
* remove a non-exitant entry - oops
|
||||
*/
|
||||
ASSERT (!"remove non-existant fmask");
|
||||
} else {
|
||||
mhash_unset (&(bier_fmask_db.bfdb_hash), &key, 0);
|
||||
}
|
||||
}
|
||||
|
||||
clib_error_t *
|
||||
bier_fmask_db_module_init (vlib_main_t *vm)
|
||||
{
|
||||
mhash_init (&bier_fmask_db.bfdb_hash,
|
||||
sizeof(uword),
|
||||
sizeof(bier_fmask_db_key_t));
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
VLIB_INIT_FUNCTION (bier_fmask_db_module_init);
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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 bier_fmask_db : The BIER fmask Database
|
||||
*/
|
||||
|
||||
#ifndef __BIER_FMASK_DB_H__
|
||||
#define __BIER_FMASK_DB_H__
|
||||
|
||||
#include <vnet/ip/ip.h>
|
||||
|
||||
#include <vnet/bier/bier_types.h>
|
||||
|
||||
/**
|
||||
* Foward declarations
|
||||
*/
|
||||
struct bier_fmask_t_;
|
||||
|
||||
typedef enum bier_hdr_type_t_ {
|
||||
BIER_HDR_IN_IP6,
|
||||
BIER_HDR_O_MPLS,
|
||||
} bier_hdr_type_t;
|
||||
|
||||
typedef struct bier_fmask_id_t_ {
|
||||
/**
|
||||
* Type of BIER header this fmask supports
|
||||
*/
|
||||
bier_hdr_type_t bfmi_hdr_type;
|
||||
|
||||
/**
|
||||
* next-hop of the peer
|
||||
*/
|
||||
ip46_address_t bfmi_nh;
|
||||
} bier_fmask_id_t;
|
||||
|
||||
extern u32
|
||||
bier_fmask_db_find_or_create_and_lock(index_t bti,
|
||||
const bier_fmask_id_t *fmid,
|
||||
const fib_route_path_t *rpath);
|
||||
|
||||
extern u32
|
||||
bier_fmask_db_find(index_t bti,
|
||||
const bier_fmask_id_t *fmid);
|
||||
|
||||
extern void
|
||||
bier_fmask_db_remove(index_t bti,
|
||||
const bier_fmask_id_t *fmid);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,217 @@
|
||||
/*
|
||||
* 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 The BIER inline functions acting on the bier header
|
||||
*/
|
||||
|
||||
#ifndef __BIER_HDR_INLINES_H__
|
||||
#define __BIER_HDR_INLINES_H__
|
||||
|
||||
#include <vppinfra/byte_order.h>
|
||||
#include <vppinfra/string.h>
|
||||
|
||||
#include <vnet/bier/bier_types.h>
|
||||
#include <vnet/bier/bier_bit_string.h>
|
||||
#include <vnet/ip/ip6_packet.h>
|
||||
|
||||
/**
|
||||
* Mask and shift values for the fields incorporated
|
||||
* into the header's first word
|
||||
*/
|
||||
#define BIER_HDR_1ST_NIBBLE_MASK 0xf0000000
|
||||
#define BIER_HDR_VERSION_FIELD_MASK 0x0f000000
|
||||
#define BIER_HDR_LEN_FIELD_MASK 0x00f00000
|
||||
#define BIER_HDR_ENTROPY_FIELD_MASK 0x000fffff
|
||||
|
||||
#define BIER_HDR_1ST_NIBBLE_SHIFT 28
|
||||
#define BIER_HDR_VERSION_FIELD_SHIFT 24
|
||||
#define BIER_HDR_LEN_FIELD_SHIFT 20
|
||||
#define BIER_HDR_ENTROPY_FIELD_SHIFT 0
|
||||
|
||||
#define BIER_HDR_1ST_NIBBLE_VALUE 0x5
|
||||
|
||||
/**
|
||||
* Mask and shift values for fields in the headers trainling word
|
||||
*/
|
||||
#define BIER_HDR_PROTO_FIELD_MASK 0x003f
|
||||
#define BIER_HDR_OAM_FIELD_MASK 0xc000
|
||||
#define BIER_HDR_DSCP_FIELD_MASK 0x0fc0
|
||||
#define BIER_HDR_DSCP_FIELD_SHIFT 6
|
||||
#define BIER_HDR_PROTO_FIELD_SHIFT 0
|
||||
#define BIER_HDR_OAM_FIELD_SHIFT 14
|
||||
|
||||
static inline bier_hdr_version_t
|
||||
bier_hdr_get_version (const bier_hdr_t *bier_hdr)
|
||||
{
|
||||
return ((bier_hdr->bh_first_word &
|
||||
BIER_HDR_VERSION_FIELD_MASK) >>
|
||||
BIER_HDR_VERSION_FIELD_SHIFT);
|
||||
}
|
||||
|
||||
static inline bier_hdr_len_id_t
|
||||
bier_hdr_get_len_id (const bier_hdr_t *bier_hdr)
|
||||
{
|
||||
return ((bier_hdr->bh_first_word &
|
||||
BIER_HDR_LEN_FIELD_MASK) >>
|
||||
BIER_HDR_LEN_FIELD_SHIFT);
|
||||
}
|
||||
|
||||
static inline bier_hdr_entropy_t
|
||||
bier_hdr_get_entropy (const bier_hdr_t *bier_hdr)
|
||||
{
|
||||
return ((bier_hdr->bh_first_word &
|
||||
BIER_HDR_ENTROPY_FIELD_MASK) >>
|
||||
BIER_HDR_ENTROPY_FIELD_SHIFT);
|
||||
}
|
||||
|
||||
static inline void
|
||||
bier_hdr_1st_nibble (bier_hdr_t *hdr)
|
||||
{
|
||||
hdr->bh_first_word &= ~(BIER_HDR_1ST_NIBBLE_MASK);
|
||||
hdr->bh_first_word |= (BIER_HDR_1ST_NIBBLE_VALUE <<
|
||||
BIER_HDR_1ST_NIBBLE_SHIFT);
|
||||
}
|
||||
|
||||
static inline u8
|
||||
bier_hdr_get_1st_nibble (bier_hdr_t *hdr)
|
||||
{
|
||||
return ((hdr->bh_first_word & BIER_HDR_1ST_NIBBLE_MASK) >>
|
||||
BIER_HDR_1ST_NIBBLE_SHIFT);
|
||||
}
|
||||
|
||||
static inline void
|
||||
bier_hdr_set_version (bier_hdr_t *hdr,
|
||||
bier_hdr_version_t version)
|
||||
{
|
||||
hdr->bh_first_word &= ~(BIER_HDR_VERSION_FIELD_MASK);
|
||||
hdr->bh_first_word |= (version << BIER_HDR_VERSION_FIELD_SHIFT);
|
||||
}
|
||||
|
||||
static inline void
|
||||
bier_hdr_set_len_id (bier_hdr_t *hdr,
|
||||
bier_hdr_len_id_t len)
|
||||
{
|
||||
hdr->bh_first_word &= ~(BIER_HDR_LEN_FIELD_MASK);
|
||||
hdr->bh_first_word |= (len << BIER_HDR_LEN_FIELD_SHIFT);
|
||||
}
|
||||
|
||||
static inline void
|
||||
bier_hdr_set_entropy (bier_hdr_t *hdr,
|
||||
bier_hdr_entropy_t entropy)
|
||||
{
|
||||
entropy = entropy & BIER_HDR_ENTROPY_FIELD_MASK;
|
||||
hdr->bh_first_word &= ~(BIER_HDR_ENTROPY_FIELD_MASK);
|
||||
hdr->bh_first_word |= (entropy << BIER_HDR_ENTROPY_FIELD_SHIFT);
|
||||
}
|
||||
|
||||
#define BIER_HDR_FIRST_WORD(version, len, entropy) \
|
||||
((BIER_HDR_1ST_NIBBLE_VALUE << \
|
||||
BIER_HDR_1ST_NIBBLE_SHIFT) | \
|
||||
(version << BIER_HDR_VERSION_FIELD_SHIFT) | \
|
||||
(len << BIER_HDR_LEN_FIELD_SHIFT) | \
|
||||
((entropy & BIER_HDR_ENTROPY_FIELD_MASK) \
|
||||
<< BIER_HDR_ENTROPY_FIELD_SHIFT))
|
||||
|
||||
static inline void
|
||||
bier_hdr_ntoh (bier_hdr_t *bier_hdr)
|
||||
{
|
||||
bier_hdr->bh_first_word = clib_net_to_host_u32(bier_hdr->bh_first_word);
|
||||
bier_hdr->bh_oam_dscp_proto = clib_net_to_host_u16(bier_hdr->bh_oam_dscp_proto);
|
||||
bier_hdr->bh_bfr_id = clib_net_to_host_u16(bier_hdr->bh_bfr_id);
|
||||
}
|
||||
|
||||
static inline void
|
||||
bier_hdr_hton (bier_hdr_t *bier_hdr)
|
||||
{
|
||||
bier_hdr->bh_first_word = clib_host_to_net_u32(bier_hdr->bh_first_word);
|
||||
bier_hdr->bh_oam_dscp_proto = clib_host_to_net_u16(bier_hdr->bh_oam_dscp_proto);
|
||||
bier_hdr->bh_bfr_id = clib_host_to_net_u16(bier_hdr->bh_bfr_id);
|
||||
}
|
||||
|
||||
static inline bier_hdr_src_id_t
|
||||
bier_hdr_get_src_id (const bier_hdr_t *bier_hdr)
|
||||
{
|
||||
return (bier_hdr->bh_bfr_id);
|
||||
}
|
||||
|
||||
static inline void
|
||||
bier_hdr_set_src_id (bier_hdr_t *bier_hdr,
|
||||
bier_hdr_src_id_t src_id)
|
||||
{
|
||||
bier_hdr->bh_bfr_id = src_id;
|
||||
}
|
||||
static inline void
|
||||
bier_hdr_set_proto_id (bier_hdr_t *bier_hdr,
|
||||
bier_hdr_proto_id_t proto)
|
||||
{
|
||||
bier_hdr->bh_oam_dscp_proto &= ~(BIER_HDR_PROTO_FIELD_MASK);
|
||||
bier_hdr->bh_oam_dscp_proto |= (proto << BIER_HDR_PROTO_FIELD_SHIFT);
|
||||
}
|
||||
|
||||
static inline bier_hdr_proto_id_t
|
||||
bier_hdr_get_proto_id (const bier_hdr_t *bier_hdr)
|
||||
{
|
||||
return ((bier_hdr->bh_oam_dscp_proto & BIER_HDR_PROTO_FIELD_MASK) >>
|
||||
BIER_HDR_PROTO_FIELD_SHIFT);
|
||||
}
|
||||
|
||||
static inline void
|
||||
bier_hdr_clear (bier_hdr_t *bier_hdr)
|
||||
{
|
||||
memset(&bier_hdr->bh_bit_string, 0,
|
||||
bier_hdr_len_id_to_num_buckets(
|
||||
bier_hdr_get_len_id(bier_hdr)));
|
||||
}
|
||||
|
||||
static inline void
|
||||
bier_hdr_init (bier_hdr_t *bier_hdr,
|
||||
bier_hdr_version_t version,
|
||||
bier_hdr_proto_id_t proto,
|
||||
bier_hdr_len_id_t len,
|
||||
bier_hdr_entropy_t entropy,
|
||||
bier_bp_t src)
|
||||
{
|
||||
bier_hdr_1st_nibble(bier_hdr);
|
||||
bier_hdr_set_version(bier_hdr, version);
|
||||
bier_hdr_set_len_id(bier_hdr, len);
|
||||
bier_hdr_set_entropy(bier_hdr, entropy);
|
||||
bier_hdr_set_proto_id(bier_hdr, proto);
|
||||
bier_hdr_set_src_id(bier_hdr, src);
|
||||
bier_hdr_clear(bier_hdr);
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
bier_hdr_str_num_bytes (const bier_hdr_t *bier_hdr)
|
||||
{
|
||||
return (bier_hdr_len_id_to_num_bytes(
|
||||
bier_hdr_get_len_id(bier_hdr)));
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
bier_hdr_num_bytes (const bier_hdr_t *bier_hdr)
|
||||
{
|
||||
return (sizeof(bier_hdr_t) +
|
||||
bier_hdr_str_num_bytes(bier_hdr));
|
||||
}
|
||||
|
||||
static inline void
|
||||
bier_bit_string_init_from_hdr (bier_hdr_t *bier_hdr,
|
||||
bier_bit_string_t *bit_string)
|
||||
{
|
||||
bit_string->bbs_len = bier_hdr_str_num_bytes(bier_hdr);
|
||||
bit_string->bbs_buckets = bier_hdr->bh_bit_string;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,288 @@
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
/**
|
||||
* bier_imposition : The BIER imposition object
|
||||
*
|
||||
* A BIER imposition object is present in the IP mcast output list
|
||||
* and represents the imposition of a BIER bitmask. After BIER header
|
||||
* imposition the packet is forward within the appropriate/specifid
|
||||
* BIER table
|
||||
*/
|
||||
|
||||
#include <vnet/bier/bier_imp.h>
|
||||
#include <vnet/bier/bier_table.h>
|
||||
#include <vnet/bier/bier_hdr_inlines.h>
|
||||
#include <vnet/fib/fib_node.h>
|
||||
#include <vnet/mpls/mpls_types.h>
|
||||
|
||||
/**
|
||||
* The memory pool of all imp objects
|
||||
*/
|
||||
bier_imp_t *bier_imp_pool;
|
||||
|
||||
/**
|
||||
* When constructing the BIER imp ID from an index and BSL, shift
|
||||
* the BSL this far
|
||||
*/
|
||||
#define BIER_IMP_ID_HLEN_SHIFT 24
|
||||
|
||||
static void
|
||||
bier_imp_lock_i (bier_imp_t *bi)
|
||||
{
|
||||
bi->bi_locks++;
|
||||
}
|
||||
|
||||
void
|
||||
bier_imp_lock (index_t bii)
|
||||
{
|
||||
bier_imp_lock_i(bier_imp_get(bii));
|
||||
}
|
||||
|
||||
static index_t
|
||||
bier_imp_get_index(bier_imp_t *bi)
|
||||
{
|
||||
return (bi - bier_imp_pool);
|
||||
}
|
||||
|
||||
index_t
|
||||
bier_imp_add_or_lock (const bier_table_id_t *bti,
|
||||
bier_bp_t sender,
|
||||
const bier_bit_string_t *bs)
|
||||
{
|
||||
bier_imp_t *bi = NULL;
|
||||
fib_protocol_t fproto;
|
||||
index_t btii;
|
||||
|
||||
pool_get_aligned(bier_imp_pool, bi, CLIB_CACHE_LINE_BYTES);
|
||||
|
||||
bi->bi_tbl = *bti;
|
||||
btii = bier_table_add_or_lock(bti, MPLS_LABEL_INVALID);
|
||||
|
||||
/*
|
||||
* init the BIER header we will paint on in the data plane
|
||||
*/
|
||||
bier_hdr_init(&bi->bi_hdr,
|
||||
BIER_HDR_VERSION_1,
|
||||
BIER_HDR_PROTO_INVALID, // filled in later
|
||||
bti->bti_hdr_len,
|
||||
0, // entropy
|
||||
sender);
|
||||
bier_hdr_hton(&bi->bi_hdr);
|
||||
clib_memcpy(&bi->bi_bits, bs->bbs_buckets, bs->bbs_len);
|
||||
|
||||
bier_imp_lock_i(bi);
|
||||
|
||||
/*
|
||||
* get and stack on the forwarding info from the table
|
||||
*/
|
||||
FOR_EACH_FIB_IP_PROTOCOL(fproto)
|
||||
{
|
||||
/*
|
||||
* initialise to invalid first, lest we pick up garbage
|
||||
* from the pool alloc
|
||||
*/
|
||||
dpo_id_t dpo = DPO_INVALID;
|
||||
bi->bi_dpo[fproto] = dpo;
|
||||
|
||||
bier_table_contribute_forwarding(btii, &dpo);
|
||||
dpo_stack(DPO_BIER_IMP, fib_proto_to_dpo(fproto),
|
||||
&bi->bi_dpo[fproto],
|
||||
&dpo);
|
||||
dpo_reset(&dpo);
|
||||
}
|
||||
|
||||
return (bier_imp_get_index(bi));
|
||||
}
|
||||
|
||||
void
|
||||
bier_imp_unlock (index_t bii)
|
||||
{
|
||||
fib_protocol_t fproto;
|
||||
bier_imp_t *bi;
|
||||
|
||||
if (INDEX_INVALID == bii)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bi = bier_imp_get(bii);
|
||||
|
||||
bi->bi_locks--;
|
||||
|
||||
if (0 == bi->bi_locks)
|
||||
{
|
||||
bier_table_unlock(&bi->bi_tbl);
|
||||
|
||||
FOR_EACH_FIB_IP_PROTOCOL(fproto)
|
||||
{
|
||||
dpo_reset(&bi->bi_dpo[fproto]);
|
||||
}
|
||||
pool_put(bier_imp_pool, bi);
|
||||
}
|
||||
}
|
||||
|
||||
u8*
|
||||
format_bier_imp (u8* s, va_list *args)
|
||||
{
|
||||
index_t bii = va_arg (*args, index_t);
|
||||
u32 indent = va_arg(*args, u32);
|
||||
bier_show_flags_t flags = va_arg(*args, bier_show_flags_t);
|
||||
bier_imp_t *bi;
|
||||
|
||||
bi = bier_imp_get(bii);
|
||||
|
||||
s = format(s, "bier-imp:[%d]: tbl:[%U] hdr:[%U]",
|
||||
bier_imp_get_index(bi),
|
||||
format_bier_table_id, &bi->bi_tbl,
|
||||
format_bier_hdr, &bi->bi_hdr);
|
||||
|
||||
if (BIER_SHOW_DETAIL & flags)
|
||||
{
|
||||
bier_bit_string_t bbs;
|
||||
bier_hdr_t copy;
|
||||
|
||||
copy = bi->bi_hdr;
|
||||
bier_hdr_ntoh(©);
|
||||
bier_bit_string_init(&bbs,
|
||||
bier_hdr_get_len_id(©),
|
||||
bi->bi_bits.bits);
|
||||
|
||||
s = format(s, "\n%U%U",
|
||||
format_white_space, indent,
|
||||
format_bier_bit_string, &bbs);
|
||||
s = format(s, "\n%U%U",
|
||||
format_white_space, indent,
|
||||
format_dpo_id, &bi->bi_dpo, indent+2);
|
||||
}
|
||||
|
||||
return (s);
|
||||
}
|
||||
|
||||
void
|
||||
bier_imp_contribute_forwarding (index_t bii,
|
||||
dpo_proto_t proto,
|
||||
dpo_id_t *dpo)
|
||||
{
|
||||
dpo_set(dpo, DPO_BIER_IMP, proto, bii);
|
||||
}
|
||||
|
||||
const static char* const bier_imp_ip4_nodes[] =
|
||||
{
|
||||
"bier-imp-ip4",
|
||||
NULL,
|
||||
};
|
||||
const static char* const bier_imp_ip6_nodes[] =
|
||||
{
|
||||
"bier-imp-ip6",
|
||||
NULL,
|
||||
};
|
||||
|
||||
const static char* const * const bier_imp_nodes[DPO_PROTO_NUM] =
|
||||
{
|
||||
[DPO_PROTO_IP4] = bier_imp_ip4_nodes,
|
||||
[DPO_PROTO_IP6] = bier_imp_ip6_nodes,
|
||||
};
|
||||
|
||||
static void
|
||||
bier_imp_dpo_lock (dpo_id_t *dpo)
|
||||
{
|
||||
bier_imp_lock(dpo->dpoi_index);
|
||||
}
|
||||
|
||||
static void
|
||||
bier_imp_dpo_unlock (dpo_id_t *dpo)
|
||||
{
|
||||
bier_imp_unlock(dpo->dpoi_index);
|
||||
}
|
||||
|
||||
static void
|
||||
bier_imp_dpo_mem_show (void)
|
||||
{
|
||||
fib_show_memory_usage("BIER imposition",
|
||||
pool_elts(bier_imp_pool),
|
||||
pool_len(bier_imp_pool),
|
||||
sizeof(bier_imp_t));
|
||||
}
|
||||
|
||||
static u8*
|
||||
format_bier_imp_dpo (u8* s, va_list *ap)
|
||||
{
|
||||
index_t index = va_arg(*ap, index_t);
|
||||
u32 indent = va_arg(*ap, u32);
|
||||
|
||||
s = format(s, "%U", format_bier_imp, index, indent, BIER_SHOW_DETAIL);
|
||||
|
||||
return (s);
|
||||
}
|
||||
|
||||
const static dpo_vft_t bier_imp_vft = {
|
||||
.dv_lock = bier_imp_dpo_lock,
|
||||
.dv_unlock = bier_imp_dpo_unlock,
|
||||
.dv_format = format_bier_imp_dpo,
|
||||
.dv_mem_show = bier_imp_dpo_mem_show,
|
||||
};
|
||||
|
||||
clib_error_t *
|
||||
bier_imp_db_module_init (vlib_main_t *vm)
|
||||
{
|
||||
dpo_register(DPO_BIER_IMP, &bier_imp_vft, bier_imp_nodes);
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
VLIB_INIT_FUNCTION (bier_imp_db_module_init);
|
||||
|
||||
static clib_error_t *
|
||||
show_bier_imp (vlib_main_t * vm,
|
||||
unformat_input_t * input,
|
||||
vlib_cli_command_t * cmd)
|
||||
{
|
||||
bier_imp_t *bi;
|
||||
index_t bii;
|
||||
|
||||
bii = INDEX_INVALID;
|
||||
|
||||
while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
|
||||
if (unformat (input, "%d", &bii))
|
||||
;
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (INDEX_INVALID == bii)
|
||||
{
|
||||
pool_foreach(bi, bier_imp_pool,
|
||||
({
|
||||
vlib_cli_output(vm, "%U", format_bier_imp,
|
||||
bier_imp_get_index(bi),
|
||||
1,
|
||||
BIER_SHOW_BRIEF);
|
||||
}));
|
||||
}
|
||||
else
|
||||
{
|
||||
vlib_cli_output(vm, "%U", format_bier_imp, bii, 1,
|
||||
BIER_SHOW_DETAIL);
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
VLIB_CLI_COMMAND (show_bier_imp_node, static) = {
|
||||
.path = "show bier imp",
|
||||
.short_help = "show bier imp [index]",
|
||||
.function = show_bier_imp,
|
||||
};
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
/**
|
||||
* bier_imposition : The BIER imposition object
|
||||
*
|
||||
* A BIER imposition object is present in the IP mcast output list
|
||||
* and represents the imposition of a BIER bitmask. After BIER header
|
||||
* imposition the packet is forward within the appropriate/specifid
|
||||
* BIER table
|
||||
*/
|
||||
|
||||
#ifndef __BIER_IMPOSITION_H__
|
||||
#define __BIER_IMPOSITION_H__
|
||||
|
||||
#include <vnet/bier/bier_types.h>
|
||||
#include <vnet/fib/fib_types.h>
|
||||
#include <vnet/dpo/dpo.h>
|
||||
|
||||
/**
|
||||
* The BIER imposition object
|
||||
*/
|
||||
typedef struct bier_imp_t_ {
|
||||
/**
|
||||
* The BIER table into which to forward the post imposed packet
|
||||
*/
|
||||
bier_table_id_t bi_tbl;
|
||||
|
||||
/**
|
||||
* number of locks
|
||||
*/
|
||||
u32 bi_locks;
|
||||
|
||||
/**
|
||||
* The DPO contirubted from the resolving BIER table.
|
||||
* One per-IP protocol. This allows us to share a BIER imposition
|
||||
* object for a IPv4 and IPv6 mfib path.
|
||||
*/
|
||||
dpo_id_t bi_dpo[FIB_PROTOCOL_IP_MAX];
|
||||
|
||||
/**
|
||||
* The Header to impose.
|
||||
*/
|
||||
bier_hdr_t bi_hdr;
|
||||
|
||||
/**
|
||||
* The bit string.
|
||||
* This is a memory v. speed tradeoff. We inline here the
|
||||
* largest header type so as the bitstring is on the same
|
||||
* cacheline as the header.
|
||||
*/
|
||||
bier_bit_mask_4096_t bi_bits;
|
||||
} bier_imp_t;
|
||||
|
||||
extern index_t bier_imp_add_or_lock(const bier_table_id_t *bt,
|
||||
bier_bp_t sender,
|
||||
const bier_bit_string_t *bs);
|
||||
|
||||
extern void bier_imp_unlock(index_t bii);
|
||||
extern void bier_imp_lock(index_t bii);
|
||||
|
||||
extern u8* format_bier_imp(u8* s, va_list *ap);
|
||||
|
||||
extern void bier_imp_contribute_forwarding(index_t bii,
|
||||
dpo_proto_t proto,
|
||||
dpo_id_t *dpo);
|
||||
|
||||
extern bier_imp_t *bier_imp_pool;
|
||||
|
||||
always_inline bier_imp_t*
|
||||
bier_imp_get (index_t bii)
|
||||
{
|
||||
return (pool_elt_at_index(bier_imp_pool, bii));
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,217 @@
|
||||
/*
|
||||
* 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/bier/bier_imp.h>
|
||||
#include <vnet/bier/bier_hdr_inlines.h>
|
||||
#include <vnet/ip/ip.h>
|
||||
|
||||
/**
|
||||
* @brief A struct to hold tracing information for the BIER imposition
|
||||
* node.
|
||||
*/
|
||||
typedef struct bier_imp_trace_t_
|
||||
{
|
||||
/**
|
||||
* BIER imposition object hit
|
||||
*/
|
||||
index_t imp;
|
||||
|
||||
/**
|
||||
* BIER hdr applied
|
||||
*/
|
||||
bier_hdr_t hdr;
|
||||
} bier_imp_trace_t;
|
||||
|
||||
always_inline uword
|
||||
bier_imp_dpo_inline (vlib_main_t * vm,
|
||||
vlib_node_runtime_t * node,
|
||||
vlib_frame_t * from_frame,
|
||||
fib_protocol_t fproto,
|
||||
bier_hdr_proto_id_t bproto)
|
||||
{
|
||||
u32 n_left_from, next_index, * from, * to_next;
|
||||
|
||||
from = vlib_frame_vector_args (from_frame);
|
||||
n_left_from = from_frame->n_vectors;
|
||||
|
||||
next_index = node->cached_next_index;
|
||||
|
||||
while (n_left_from > 0)
|
||||
{
|
||||
u32 n_left_to_next;
|
||||
|
||||
vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
|
||||
|
||||
while (n_left_from > 0 && n_left_to_next > 0)
|
||||
{
|
||||
vlib_buffer_t * b0;
|
||||
bier_imp_t *bimp0;
|
||||
bier_hdr_t *hdr0;
|
||||
u32 bi0, bii0;
|
||||
u32 next0;
|
||||
|
||||
bi0 = from[0];
|
||||
to_next[0] = bi0;
|
||||
from += 1;
|
||||
to_next += 1;
|
||||
n_left_from -= 1;
|
||||
n_left_to_next -= 1;
|
||||
|
||||
b0 = vlib_get_buffer (vm, bi0);
|
||||
|
||||
bii0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
|
||||
bimp0 = bier_imp_get(bii0);
|
||||
|
||||
if (FIB_PROTOCOL_IP4 == fproto)
|
||||
{
|
||||
/*
|
||||
* decrement the TTL on ingress to the BIER domain
|
||||
*/
|
||||
ip4_header_t * ip0 = vlib_buffer_get_current(b0);
|
||||
u32 checksum0;
|
||||
|
||||
checksum0 = ip0->checksum + clib_host_to_net_u16 (0x0100);
|
||||
checksum0 += checksum0 >= 0xffff;
|
||||
|
||||
ip0->checksum = checksum0;
|
||||
ip0->ttl -= 1;
|
||||
|
||||
/*
|
||||
* calculate an entropy
|
||||
*/
|
||||
if (0 == vnet_buffer(b0)->ip.flow_hash)
|
||||
{
|
||||
vnet_buffer(b0)->ip.flow_hash =
|
||||
ip4_compute_flow_hash (ip0, IP_FLOW_HASH_DEFAULT);
|
||||
}
|
||||
}
|
||||
if (FIB_PROTOCOL_IP6 == fproto)
|
||||
{
|
||||
/*
|
||||
* decrement the TTL on ingress to the BIER domain
|
||||
*/
|
||||
ip6_header_t * ip0 = vlib_buffer_get_current(b0);
|
||||
|
||||
ip0->hop_limit -= 1;
|
||||
|
||||
/*
|
||||
* calculate an entropy
|
||||
*/
|
||||
if (0 == vnet_buffer(b0)->ip.flow_hash)
|
||||
{
|
||||
vnet_buffer(b0)->ip.flow_hash =
|
||||
ip6_compute_flow_hash (ip0, IP_FLOW_HASH_DEFAULT);
|
||||
}
|
||||
}
|
||||
|
||||
/* Paint the BIER header */
|
||||
vlib_buffer_advance(b0, -(sizeof(bier_hdr_t) +
|
||||
bier_hdr_len_id_to_num_bytes(bimp0->bi_tbl.bti_hdr_len)));
|
||||
hdr0 = vlib_buffer_get_current(b0);
|
||||
clib_memcpy(hdr0, &bimp0->bi_hdr,
|
||||
(sizeof(bier_hdr_t) +
|
||||
bier_hdr_len_id_to_num_bytes(bimp0->bi_tbl.bti_hdr_len)));
|
||||
/*
|
||||
* Fixup the entropy and protocol, both of which have a
|
||||
* zero value post the paint job
|
||||
*/
|
||||
hdr0->bh_oam_dscp_proto |=
|
||||
clib_host_to_net_u16(bproto << BIER_HDR_PROTO_FIELD_SHIFT);
|
||||
hdr0->bh_first_word |=
|
||||
clib_host_to_net_u32((vnet_buffer(b0)->ip.flow_hash &
|
||||
BIER_HDR_ENTROPY_FIELD_MASK) <<
|
||||
BIER_HDR_ENTROPY_FIELD_SHIFT);
|
||||
|
||||
/* next node */
|
||||
next0 = bimp0->bi_dpo[fproto].dpoi_next_node;
|
||||
vnet_buffer(b0)->ip.adj_index[VLIB_TX] =
|
||||
bimp0->bi_dpo[fproto].dpoi_index;
|
||||
|
||||
if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
|
||||
{
|
||||
bier_imp_trace_t *tr =
|
||||
vlib_add_trace (vm, node, b0, sizeof (*tr));
|
||||
tr->imp = bii0;
|
||||
tr->hdr = *hdr0;
|
||||
}
|
||||
|
||||
vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
|
||||
n_left_to_next, bi0, next0);
|
||||
}
|
||||
vlib_put_next_frame (vm, node, next_index, n_left_to_next);
|
||||
}
|
||||
return from_frame->n_vectors;
|
||||
}
|
||||
|
||||
static u8 *
|
||||
format_bier_imp_trace (u8 * s, va_list * args)
|
||||
{
|
||||
CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
|
||||
CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
|
||||
bier_imp_trace_t * t;
|
||||
u32 indent;
|
||||
|
||||
t = va_arg (*args, bier_imp_trace_t *);
|
||||
indent = format_get_indent (s);
|
||||
|
||||
s = format (s, "%U", format_bier_imp, t->imp, indent, BIER_SHOW_BRIEF);
|
||||
return (s);
|
||||
}
|
||||
|
||||
static uword
|
||||
bier_imp_ip4 (vlib_main_t * vm,
|
||||
vlib_node_runtime_t * node,
|
||||
vlib_frame_t * frame)
|
||||
{
|
||||
return (bier_imp_dpo_inline(vm, node, frame,
|
||||
FIB_PROTOCOL_IP4,
|
||||
BIER_HDR_PROTO_IPV4));
|
||||
}
|
||||
|
||||
VLIB_REGISTER_NODE (bier_imp_ip4_node) = {
|
||||
.function = bier_imp_ip4,
|
||||
.name = "bier-imp-ip4",
|
||||
.vector_size = sizeof (u32),
|
||||
|
||||
.format_trace = format_bier_imp_trace,
|
||||
.n_next_nodes = 1,
|
||||
.next_nodes = {
|
||||
[0] = "error-drop",
|
||||
}
|
||||
};
|
||||
VLIB_NODE_FUNCTION_MULTIARCH (bier_imp_ip4_node, bier_imp_ip4)
|
||||
|
||||
static uword
|
||||
bier_imp_ip6 (vlib_main_t * vm,
|
||||
vlib_node_runtime_t * node,
|
||||
vlib_frame_t * frame)
|
||||
{
|
||||
return (bier_imp_dpo_inline(vm, node, frame,
|
||||
FIB_PROTOCOL_IP6,
|
||||
BIER_HDR_PROTO_IPV6));
|
||||
}
|
||||
|
||||
VLIB_REGISTER_NODE (bier_imp_ip6_node) = {
|
||||
.function = bier_imp_ip6,
|
||||
.name = "bier-imp-ip6",
|
||||
.vector_size = sizeof (u32),
|
||||
|
||||
.format_trace = format_bier_imp_trace,
|
||||
.n_next_nodes = 1,
|
||||
.next_nodes = {
|
||||
[0] = "error-drop",
|
||||
}
|
||||
};
|
||||
VLIB_NODE_FUNCTION_MULTIARCH (bier_imp_ip6_node, bier_imp_ip6)
|
||||
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* 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/buffer.h>
|
||||
|
||||
#include <vnet/bier/bier_table.h>
|
||||
#include <vnet/bier/bier_hdr_inlines.h>
|
||||
|
||||
typedef enum {
|
||||
#define bier_error(n,s) BIER_INPUT_ERROR_##n,
|
||||
#include <vnet/bier/bier_input_error.def>
|
||||
#undef bier_error
|
||||
BIER_INPUT_N_ERROR,
|
||||
} bier_input_error_t;
|
||||
|
||||
static char * bier_error_strings[] = {
|
||||
#define bier_error(n,s) s,
|
||||
#include <vnet/bier/bier_input_error.def>
|
||||
#undef bier_error
|
||||
};
|
||||
|
||||
typedef enum bier_input_next_t_ {
|
||||
BIER_INPUT_NEXT_BIER_LOOKUP,
|
||||
BIER_INPUT_NEXT_DROP,
|
||||
BIER_INPUT_N_NEXT,
|
||||
} bier_input_next_t;
|
||||
|
||||
vlib_node_registration_t bier_input_node;
|
||||
|
||||
/**
|
||||
* @brief Packet trace recoed for a BIER output
|
||||
*/
|
||||
typedef struct bier_input_trace_t_
|
||||
{
|
||||
u32 next_index;
|
||||
u32 bt_index;
|
||||
} bier_input_trace_t;
|
||||
|
||||
static int
|
||||
bier_hdr_validate (bier_hdr_t *bier_hdr,
|
||||
bier_hdr_len_id_t expected_length)
|
||||
{
|
||||
/*
|
||||
* checks:
|
||||
* - the version field must be 1
|
||||
* - the header length matches the length expected
|
||||
*/
|
||||
if (PREDICT_FALSE((BIER_HDR_VERSION_1 != bier_hdr_get_version(bier_hdr)) ||
|
||||
(expected_length != bier_hdr_get_len_id(bier_hdr)))) {
|
||||
return (0);
|
||||
}
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
static uword
|
||||
bier_input (vlib_main_t * vm,
|
||||
vlib_node_runtime_t * node,
|
||||
vlib_frame_t * from_frame)
|
||||
{
|
||||
u32 n_left_from, next_index, * from, * to_next;
|
||||
|
||||
from = vlib_frame_vector_args (from_frame);
|
||||
n_left_from = from_frame->n_vectors;
|
||||
|
||||
/*
|
||||
* objection your honour! speculation!
|
||||
*/
|
||||
next_index = node->cached_next_index;
|
||||
|
||||
while (n_left_from > 0)
|
||||
{
|
||||
u32 n_left_to_next;
|
||||
|
||||
vlib_get_next_frame (vm, node, next_index,
|
||||
to_next, n_left_to_next);
|
||||
|
||||
while (n_left_from > 0 && n_left_to_next > 0)
|
||||
{
|
||||
const bier_table_t *bt0;
|
||||
vlib_buffer_t * b0;
|
||||
bier_hdr_t * bh0;
|
||||
u32 bi0, next0;
|
||||
u32 bt_index0;
|
||||
|
||||
bi0 = from[0];
|
||||
to_next[0] = bi0;
|
||||
from += 1;
|
||||
to_next += 1;
|
||||
n_left_from -= 1;
|
||||
n_left_to_next -= 1;
|
||||
|
||||
b0 = vlib_get_buffer (vm, bi0);
|
||||
bh0 = vlib_buffer_get_current (b0);
|
||||
bier_hdr_ntoh(bh0);
|
||||
|
||||
/*
|
||||
* In the MPLS decap node we squirelled away the
|
||||
* index for the BIER table as the tx adjacency
|
||||
*/
|
||||
bt_index0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
|
||||
bt0 = bier_table_get(bt_index0);
|
||||
|
||||
if (PREDICT_TRUE(bier_hdr_validate(bh0, bt0->bt_id.bti_hdr_len)))
|
||||
{
|
||||
next0 = BIER_INPUT_NEXT_BIER_LOOKUP;
|
||||
} else {
|
||||
next0 = BIER_INPUT_NEXT_DROP;
|
||||
b0->error = node->errors[BIER_INPUT_ERROR_INVALID_HEADER];
|
||||
}
|
||||
|
||||
if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
|
||||
{
|
||||
bier_input_trace_t *tr;
|
||||
|
||||
tr = vlib_add_trace (vm, node, b0, sizeof (*tr));
|
||||
tr->next_index = next0;
|
||||
tr->bt_index = bt_index0;
|
||||
}
|
||||
|
||||
vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
|
||||
to_next, n_left_to_next,
|
||||
bi0, next0);
|
||||
}
|
||||
|
||||
vlib_put_next_frame (vm, node, next_index, n_left_to_next);
|
||||
}
|
||||
|
||||
vlib_node_increment_counter (vm, bier_input_node.index,
|
||||
BIER_INPUT_ERROR_PKTS_VALID,
|
||||
from_frame->n_vectors);
|
||||
return (from_frame->n_vectors);
|
||||
}
|
||||
|
||||
static u8 *
|
||||
format_bier_input_trace (u8 * s, va_list * args)
|
||||
{
|
||||
CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
|
||||
CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
|
||||
bier_input_trace_t * t = va_arg (*args, bier_input_trace_t *);
|
||||
|
||||
s = format (s, " next [%d], BIER Table index %d",
|
||||
t->next_index, t->bt_index);
|
||||
return s;
|
||||
}
|
||||
|
||||
VLIB_REGISTER_NODE (bier_input_node) = {
|
||||
.function = bier_input,
|
||||
.name = "bier-input",
|
||||
/* Takes a vector of packets. */
|
||||
.vector_size = sizeof (u32),
|
||||
|
||||
.n_errors = BIER_INPUT_N_ERROR,
|
||||
.error_strings = bier_error_strings,
|
||||
|
||||
.n_next_nodes = BIER_INPUT_N_NEXT,
|
||||
.next_nodes = {
|
||||
[BIER_INPUT_NEXT_BIER_LOOKUP] = "bier-lookup",
|
||||
[BIER_INPUT_NEXT_DROP] = "bier-drop",
|
||||
},
|
||||
|
||||
.format_trace = format_bier_input_trace,
|
||||
};
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
bier_error (NONE, "no error")
|
||||
bier_error (TABLE_NOT_FOUND, "table not found")
|
||||
bier_error (INVALID_HEADER, "invalid header")
|
||||
bier_error (PKTS_VALID, "BIER input packets")
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
bier_error (NONE, "no error")
|
||||
bier_error (FMASK_UNRES, "fmask unresolved")
|
||||
bier_error (BUFFER_ALLOCATION_FAILURE, "Buffer Allocation Failure")
|
||||
@@ -0,0 +1,195 @@
|
||||
/*
|
||||
* 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/buffer.h>
|
||||
|
||||
#include <vnet/bier/bier_fmask.h>
|
||||
#include <vnet/bier/bier_hdr_inlines.h>
|
||||
#include <vlib/vlib.h>
|
||||
|
||||
static char * bier_output_error_strings[] = {
|
||||
#define bier_error(n,s) s,
|
||||
#include <vnet/bier/bier_output_error.def>
|
||||
#undef bier_error
|
||||
};
|
||||
|
||||
/*
|
||||
* Keep these values sematically the same as BIER output
|
||||
*/
|
||||
#define foreach_bier_output_next \
|
||||
_(DROP, "bier-drop")
|
||||
|
||||
typedef enum {
|
||||
#define _(s,n) BIER_OUTPUT_NEXT_##s,
|
||||
foreach_bier_output_next
|
||||
#undef _
|
||||
BIER_OUTPUT_N_NEXT,
|
||||
} bier_output_next_t;
|
||||
|
||||
typedef enum {
|
||||
#define bier_error(n,s) BIER_OUTPUT_ERROR_##n,
|
||||
#include <vnet/bier/bier_output_error.def>
|
||||
#undef bier_error
|
||||
BIER_OUTPUT_N_ERROR,
|
||||
} bier_output_error_t;
|
||||
|
||||
/**
|
||||
* Forward declaration
|
||||
*/
|
||||
vlib_node_registration_t bier_output_node;
|
||||
|
||||
/**
|
||||
* @brief Packet trace recoed for a BIER output
|
||||
*/
|
||||
typedef struct bier_output_trace_t_
|
||||
{
|
||||
u32 next_index;
|
||||
index_t bfm_index;
|
||||
} bier_output_trace_t;
|
||||
|
||||
static uword
|
||||
bier_output (vlib_main_t * vm,
|
||||
vlib_node_runtime_t * node,
|
||||
vlib_frame_t * from_frame)
|
||||
{
|
||||
u32 n_left_from, next_index, * from, * to_next;
|
||||
|
||||
from = vlib_frame_vector_args (from_frame);
|
||||
n_left_from = from_frame->n_vectors;
|
||||
|
||||
// vnet_buffer(b0)->sw_if_index[VLIB_TX] = d0->tx_fib_index;
|
||||
|
||||
/*
|
||||
* objection your honour! speculation!
|
||||
*/
|
||||
next_index = node->cached_next_index;
|
||||
|
||||
while (n_left_from > 0)
|
||||
{
|
||||
u32 n_left_to_next;
|
||||
|
||||
vlib_get_next_frame (vm, node, next_index,
|
||||
to_next, n_left_to_next);
|
||||
|
||||
while (n_left_from > 0 && n_left_to_next > 0)
|
||||
{
|
||||
bier_output_next_t next0;
|
||||
bier_bit_string_t bbs;
|
||||
vlib_buffer_t * b0;
|
||||
bier_fmask_t *bfm0;
|
||||
bier_hdr_t *bh0;
|
||||
u32 bi0, *h0;
|
||||
u32 bfmi0;
|
||||
|
||||
bi0 = from[0];
|
||||
to_next[0] = bi0;
|
||||
from += 1;
|
||||
to_next += 1;
|
||||
n_left_from -= 1;
|
||||
n_left_to_next -= 1;
|
||||
|
||||
b0 = vlib_get_buffer (vm, bi0);
|
||||
bh0 = vlib_buffer_get_current (b0);
|
||||
bier_bit_string_init_from_hdr(bh0, &bbs);
|
||||
|
||||
/*
|
||||
* In the BIER Lookup node we squirelled away the
|
||||
* BIER fmask index as the adj index
|
||||
*/
|
||||
bfmi0 = vnet_buffer (b0)->ip.adj_index[VLIB_TX];
|
||||
bfm0 = bier_fmask_get(bfmi0);
|
||||
|
||||
/*
|
||||
* perform the logical AND of the packet's mask with
|
||||
* that of the fmask objects, to reset the bits that
|
||||
* are only on the shortest path the the fmask NH.
|
||||
*/
|
||||
bier_bit_string_logical_and_string(
|
||||
&bfm0->bfm_bits.bfmb_input_reset_string,
|
||||
&bbs);
|
||||
|
||||
/*
|
||||
* this is the last time we touch the BIER header
|
||||
* so flip to network order
|
||||
*/
|
||||
bier_hdr_hton(bh0);
|
||||
|
||||
/*
|
||||
* paint the BIER peer's label
|
||||
*/
|
||||
if (!(bfm0->bfm_flags & BIER_FMASK_FLAG_DISP))
|
||||
{
|
||||
vlib_buffer_advance(b0, -(word)sizeof(mpls_label_t));
|
||||
h0 = vlib_buffer_get_current(b0);
|
||||
h0[0] = bfm0->bfm_label;
|
||||
}
|
||||
|
||||
/*
|
||||
* setup next graph node
|
||||
*/
|
||||
next0 = bfm0->bfm_dpo.dpoi_next_node;
|
||||
vnet_buffer(b0)->ip.adj_index[VLIB_TX] = bfm0->bfm_dpo.dpoi_index;
|
||||
|
||||
if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
|
||||
{
|
||||
bier_output_trace_t *tr;
|
||||
|
||||
tr = vlib_add_trace (vm, node, b0, sizeof (*tr));
|
||||
tr->next_index = next0;
|
||||
tr->bfm_index = bfmi0;
|
||||
}
|
||||
|
||||
vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
|
||||
to_next, n_left_to_next,
|
||||
bi0, next0);
|
||||
}
|
||||
|
||||
vlib_put_next_frame (vm, node, next_index, n_left_to_next);
|
||||
}
|
||||
|
||||
vlib_node_increment_counter (vm, bier_output_node.index,
|
||||
BIER_OUTPUT_ERROR_NONE,
|
||||
from_frame->n_vectors);
|
||||
return (from_frame->n_vectors);
|
||||
}
|
||||
|
||||
static u8 *
|
||||
format_bier_output_trace (u8 * s, va_list * args)
|
||||
{
|
||||
CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
|
||||
CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
|
||||
bier_output_trace_t * t = va_arg (*args, bier_output_trace_t *);
|
||||
|
||||
s = format (s, " next [%d], BFM index %d",
|
||||
t->next_index, t->bfm_index);
|
||||
return s;
|
||||
}
|
||||
|
||||
VLIB_REGISTER_NODE (bier_output_node) = {
|
||||
.function = bier_output,
|
||||
.name = "bier-output",
|
||||
/* Takes a vector of packets. */
|
||||
.vector_size = sizeof (u32),
|
||||
|
||||
.n_errors = BIER_OUTPUT_N_ERROR,
|
||||
.error_strings = bier_output_error_strings,
|
||||
|
||||
.n_next_nodes = BIER_OUTPUT_N_NEXT,
|
||||
.next_nodes = {
|
||||
[BIER_OUTPUT_NEXT_DROP] = "bier-drop",
|
||||
},
|
||||
|
||||
.format_trace = format_bier_output_trace,
|
||||
};
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
bier_error (NONE, "no error")
|
||||
bier_error (FMASK_UNRES, "fmask unresolved")
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user