summaryrefslogtreecommitdiffstats
path: root/src/vnet/mfib/ip6_mfib.c
AgeCommit message (Collapse)AuthorFilesLines
2021-10-21fib: respect mfib entry flags on create with pathsPaul Atkins1-0/+2
When an mfib entry was created with both paths and entry_flags then the entry flags were being ignored. If there are no paths then the flags were passed into mfib_table_entry_update, but in the case where the entry didn't exist and there were paths and flags, the entry was created within mfib_table_entry_paths_update() which used a default of MFIB_ENTRY_FLAG_NONE. Pass the flags through into the mfib_table_entry_paths_update fn. All existing callers other than the create case will now pass in MFIB_ENTRY_FLAG_NONE. Type: fix Signed-off-by: Paul Atkins <patkins@graphiant.com> Change-Id: I256375ba2fa863a62a88474ce1ea6bf2accdd456
2021-09-30fib: doc nitfixesNathan Skrzypczak1-5/+5
Type: improvement Change-Id: I29346c849a5e1ff3c2ea399671f9f50d075e9f18 Signed-off-by: Nathan Skrzypczak <nathan.skrzypczak@gmail.com>
2021-09-13interface: fix init fib_index_by_sw_if_indexNathan Skrzypczak1-1/+0
Type: fix The init of fib_index_by_sw_if_index wasn't setting default value to 0. Which we now need for setting interfaces unnumbered Change-Id: Ie5be9b5e5373ef055557a871ad4d1c45fbfc1dee Signed-off-by: Nathan Skrzypczak <nathan.skrzypczak@gmail.com>
2020-12-14misc: refactor clib_bitmap_foreach macroDamjan Marion1-3/+3
Type: refactor Change-Id: I077110e1a422722e20aa546a6f3224c06ab0cde5 Signed-off-by: Damjan Marion <damarion@cisco.com>
2020-12-14misc: move to new pool_foreach macrosDamjan Marion1-3/+3
Type: refactor Change-Id: Ie67dc579e88132ddb1ee4a34cb69f96920101772 Signed-off-by: Damjan Marion <damarion@cisco.com>
2020-10-19ip: Move the IP6 fib into ip6_[m]fib.cNeale Ranns1-7/+25
Type: improvement reduce the compile time by moving the bihash includes out of ip[46].h Signed-off-by: Neale Ranns <nranns@cisco.com> Change-Id: I6b9216e10aff1013071f9238b3e1ebbdd205bd80
2019-12-16vppinfra: bihash walk cb typedef and continue/stop controlsNeale Ranns1-1/+2
Type: feature Change-Id: I28f7a658be3f3beec9ea32635b60d1d3a10d9b06 Signed-off-by: Neale Ranns <nranns@cisco.com>
2019-11-26fib: Table ReplaceNeale Ranns1-5/+4
Type: feature from the API doc, a table replace is: " The use-case is that, for some unspecified reason, the control plane has a very different set of entries it wants in the table than VPP currently has. The CP would thus like to 'replace' VPP's current table only by specifying what the new set of entries shall be, i.e. it is not going to delete anything that already eixts. the CP delcartes the start of this procedure with this begin_replace API Call, and when it has populated all the entries it wants, it calls the below end_replace API. From this point on it is of coursce free to add and delete entries as usual. The underlying mechanism by which VPP implements this replace is purposefully left unspecified. " In the FIB, the algorithm is implemented using mark and sweep. Algorithm goes: 1) replace_begin: this marks all the entries in that table as 'stale' 2) download all the entries that should be in this table - this clears the stale flag on those entries 3) signal the table converged: ip_table_replace_end - this removes all entries that are still stale this procedure can be used when an agent first connects to VPP, as an alternative to dump and diff state reconciliation. Change-Id: I168edec10cf7670866076b129ebfe6149ea8222e Signed-off-by: Neale Ranns <nranns@cisco.com>
2019-06-18fib: fib api updatesNeale Ranns1-7/+7
Enhance the route add/del APIs to take a set of paths rather than just one. Most unicast routing protocols calcualte all the available paths in one run of the algorithm so updating all the paths at once is beneficial for the client. two knobs control the behaviour: is_multipath - if set the the set of paths passed will be added to those that already exist, otherwise the set will replace them. is_add - add or remove the set is_add=0, is_multipath=1 and an empty set, results in deleting the route. It is also considerably faster to add multiple paths at once, than one at a time: vat# ip_add_del_route 1.1.1.1/32 count 100000 multipath via 10.10.10.11 100000 routes in .572240 secs, 174751.80 routes/sec vat# ip_add_del_route 1.1.1.1/32 count 100000 multipath via 10.10.10.12 100000 routes in .528383 secs, 189256.54 routes/sec vat# ip_add_del_route 1.1.1.1/32 count 100000 multipath via 10.10.10.13 100000 routes in .757131 secs, 132077.52 routes/sec vat# ip_add_del_route 1.1.1.1/32 count 100000 multipath via 10.10.10.14 100000 routes in .878317 secs, 113854.12 routes/sec vat# ip_route_add_del 1.1.1.1/32 count 100000 multipath via 10.10.10.11 via 10.10.10.12 via 10.10.10.13 via 10.10.10.14 100000 routes in .900212 secs, 111084.93 routes/sec Change-Id: I416b93f7684745099c1adb0b33edac58c9339c1a Signed-off-by: Neale Ranns <neale.ranns@cisco.com> Signed-off-by: Ole Troan <ot@cisco.com> Signed-off-by: Paul Vinciguerra <pvinci@vinciconsulting.com>
2019-05-30FIB: correctly report IPv6 FIB Unicast and Multicast memory usage (VPP-1578)"Neale Ranns1-2/+7
and document scaling Change-Id: I65d8999e65616d77e525963c770d91e9b0d5e593 Signed-off-by: Neale Ranns <nranns@cisco.com>
2018-12-21MFIB: coverity fixesNeale Ranns1-1/+1
Change-Id: I5c1bc498f7299e175070eb288e40f8d037c9be3a Signed-off-by: Neale Ranns <nranns@cisco.com>
2018-12-18MFIB: recurse resolution through an MFIB entryNeale Ranns1-8/+54
Change-Id: I8dc261e40b8398c5c8ab6bb69ecebbd0176055d9 Signed-off-by: Neale Ranns <nranns@cisco.com>
2018-12-16IP6-MFIB: replace the radix tree with bihash (VPP-1526)Neale Ranns1-119/+139
Change-Id: I7a48890c075826fbd8c75436dfdc5ffff230a693 Signed-off-by: Neale Ranns <nranns@cisco.com>
2018-10-23c11 safe string handling supportDave Barach1-5/+5
Change-Id: Ied34720ca5a6e6e717eea4e86003e854031b6eab Signed-off-by: Dave Barach <dave@barachs.net>
2017-11-29Include allocated table memory in 'sh fib mem' outputNeale Ranns1-10/+20
DBGvpp# sh fib mem FIB memory Tables: SAFI Number Bytes IPv4 unicast 2 673066 IPv6 unicast 2 1054608 MPLS 1 4194312 IPv4 multicast 2 2322 IPv6 multicast 2 ??? Nodes: Name Size in-use /allocated totals Entry 96 20 / 20 1920/1920 Entry Source 32 0 / 0 0/0 Entry Path-Extensions 60 0 / 0 0/0 multicast-Entry 192 12 / 12 2304/2304 Path-list 40 28 / 28 1120/1120 uRPF-list 16 20 / 20 320/320 Path 72 28 / 28 2016/2016 Node-list elements 20 28 / 28 560/560 Node-list heads 8 30 / 30 240/240 Change-Id: I8c8f6f1c87502a40265bf4f302d0daef111a4a4e Signed-off-by: Neale Ranns <nranns@cisco.com>
2017-09-11FIB table add/delete APINeale Ranns1-5/+7
part 2; - this adds the code to create an IP and MPLS table via the API. - but the enforcement that the table must be created before it is used is still missing, this is so that CSIT can pass. Change-Id: Id124d884ade6cb7da947225200e3bb193454c555 Signed-off-by: Neale Ranns <nranns@cisco.com>
2017-08-08L2 over MPLSNeale Ranns1-3/+3
[support for VPWS/VPLS] - switch to using dpo_proto_t rather than fib_protocol_t in fib_paths so that we can describe L2 paths - VLIB nodes to handle pop/push of MPLS labels to L2 Change-Id: Id050d06a11fd2c9c1c81ce5a0654e6c5ae6afa6e Signed-off-by: Neale Ranns <nranns@cisco.com>
2017-05-19mfib CLI bugs (VPP-852)Neale Ranns1-5/+8
Change-Id: I1b71010e20742eee02693d672e24c85897e37759 Signed-off-by: Neale Ranns <nranns@cisco.com>
2017-04-07MPLS McastNeale Ranns1-0/+1
1 - interface-DPO Used in the Data-plane to change a packet's input interface 2 - MPLS multicast FIB entry Same as a unicast entry but it links to a replicate not a load-balance DPO 3 - Multicast MPLS tunnel Update MPLS tunnels to use a FIB path-list to describe the endpoint[s]. Use the path-list to generate the forwarding chain (DPOs) to link to . 4 - Resolve a path via a local label (of an mLDP LSP) For IP multicast entries to use an LSP in the replication list, we need to decribe the 'resolve-via-label' where the label is that of a multicast LSP. 5 - MPLS disposition path sets RPF-ID For a interface-less LSP (i.e. mLDP not RSVP-TE) at the tail of the LSP we still need to perform an RPF check. An MPLS disposition DPO performs the MPLS pop validation checks and sets the RPF-ID in the packet. 6 - RPF check with per-entry RPF-ID An RPF-ID is used instead of a real interface SW if index in the case the IP traffic arrives from an LSP that does not have an associated interface. Change-Id: Ib92e177be919147bafeb599729abf3d1abc2f4b3 Signed-off-by: Neale Ranns <nranns@cisco.com>
2017-02-25MFIB: changes to improve route add/delete performanceNeale Ranns1-1/+1
Change-Id: I063d85200d12b09545ae1c373c7fc69112ae3b34 Signed-off-by: Neale Ranns <nranns@cisco.com>
2017-02-20Python test IP and MPLS objects conform to infra.Neale Ranns1-10/+40
Add IP[46] MFIB dump. Change-Id: I4a2821f65e67a5416b291e4912c84f64989883b8 Signed-off-by: Neale Ranns <nranns@cisco.com>
2017-01-27IP Multicast FIB (mfib)Neale Ranns1-0/+663
- IPv[46] mfib tables with support for (*,G/m), (*,G) and (S,G) exact and longest prefix match - Replication represented via a new replicate DPO. - RPF configuration and data-plane checking - data-plane signals sent to listening control planes. The functions of multicast forwarding entries differ from their unicast conterparts, so we introduce a new mfib_table_t and mfib_entry_t objects. However, we re-use the fib_path_list to resolve and build the entry's output list. the fib_path_list provides the service to construct a replicate DPO for multicast. 'make tests' is added to with two new suites; TEST=mfib, this is invocation of the CLI command 'test mfib' which deals with many path add/remove, flag set/unset scenarios, TEST=ip-mcast, data-plane forwarding tests. Updated applications to use the new MIFB functions; - IPv6 NS/RA. - DHCPv6 unit tests for these are undated accordingly. Change-Id: I49ec37b01f1b170335a5697541c8fd30e6d3a961 Signed-off-by: Neale Ranns <nranns@cisco.com>
lass="cpf"><vpp/app/version.h> #include <vnet/ip/ip.h> #include <vlib/unix/unix.h> #include <vnet/adj/adj_mcast.h> #include <igmp/igmp.h> #include <igmp/igmp_pkt.h> #include <igmp/igmp_query.h> #include <igmp/igmp_report.h> #include <igmp/igmp_error.h> #include <limits.h> typedef enum { IGMP_INPUT_NEXT_DROP, IGMP_INPUT_NEXT_PARSE_QUERY, IGMP_INPUT_NEXT_PARSE_REPORT, IGMP_INPUT_N_NEXT, } igmp_input_next_t; typedef enum { IGMP_PARSE_QUERY_NEXT_DROP, IGMP_PARSE_QUERY_N_NEXT, } igmp_parse_query_next_t; typedef enum { IGMP_PARSE_REPORT_NEXT_DROP, IGMP_PARSE_REPORT_N_NEXT, } igmp_parse_report_next_t; char *igmp_error_strings[] = { #define _(sym,string) string, foreach_igmp_error #undef _ }; typedef struct { u32 next_index; u32 sw_if_index; u32 len; u8 packet_data[64]; } igmp_input_trace_t; static u8 * format_igmp_input_trace (u8 * s, va_list * va) { CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *); CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *); igmp_input_trace_t *t = va_arg (*va, igmp_input_trace_t *); s = format (s, "sw_if_index %u next-index %u", t->sw_if_index, t->next_index); s = format (s, "\n%U", format_igmp_header, t->packet_data, sizeof (t->packet_data)); return s; } static u8 * format_igmp_parse_report_trace (u8 * s, va_list * va) { CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *); CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *); igmp_input_trace_t *t = va_arg (*va, igmp_input_trace_t *); s = format (s, "sw_if_index %u next-index %u", t->sw_if_index, t->next_index); s = format (s, "\n%U", format_igmp_report_v3, t->packet_data, sizeof (t->packet_data)); return s; } static u8 * format_igmp_parse_query_trace (u8 * s, va_list * va) { CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *); CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *); igmp_input_trace_t *t = va_arg (*va, igmp_input_trace_t *); s = format (s, "sw_if_index %u next-input %u len %u", t->sw_if_index, t->next_index, t->len); s = format (s, "\n%U", format_igmp_query_v3, t->packet_data, sizeof (t->packet_data)); s = format (s, "\n%U", format_hex_bytes, t->packet_data, sizeof (t->packet_data)); return s; } static uword igmp_input (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) { igmp_parse_query_next_t next_index; u32 n_left_from, *from, *to_next; vlib_node_runtime_t *error_node; u8 error; error = IGMP_ERROR_NONE; error_node = node; from = vlib_frame_vector_args (frame); n_left_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) { igmp_header_t *igmp; u16 checksum, csum; vlib_buffer_t *b; ip4_header_t *ip; ip_csum_t sum; u32 bi, next; next = IGMP_INPUT_NEXT_DROP; bi = from[0]; to_next[0] = bi; from++; to_next++; n_left_from--; n_left_to_next--; b = vlib_get_buffer (vm, bi); ip = vlib_buffer_get_current (b); if (ip->protocol != IP_PROTOCOL_IGMP) { error = IGMP_ERROR_INVALID_PROTOCOL; next = IGMP_INPUT_NEXT_DROP; goto next_buffer; } vlib_buffer_advance (b, ip4_header_bytes (ip)); igmp = vlib_buffer_get_current (b); checksum = igmp->checksum; igmp->checksum = 0; sum = ip_incremental_checksum (0, igmp, clib_net_to_host_u16 (ip->length) - ip4_header_bytes (ip)); igmp->checksum = checksum; csum = ~ip_csum_fold (sum); if (checksum != csum) { error = IGMP_ERROR_BAD_CHECKSUM; next = IGMP_INPUT_NEXT_DROP; goto next_buffer; } if (!igmp_config_lookup (vnet_buffer (b)->sw_if_index[VLIB_RX])) { error = IGMP_ERROR_NOT_ENABLED; next = IGMP_INPUT_NEXT_DROP; goto next_buffer; } /* TODO: IGMPv2 and IGMPv1 */ switch (igmp->type) { case IGMP_TYPE_membership_query: next = IGMP_INPUT_NEXT_PARSE_QUERY; break; case IGMP_TYPE_membership_report_v3: next = IGMP_INPUT_NEXT_PARSE_REPORT; break; default: error = IGMP_ERROR_UNKNOWN_TYPE; next = IGMP_INPUT_NEXT_DROP; break; } next_buffer: b->error = error_node->errors[error]; if (node->flags & VLIB_NODE_FLAG_TRACE) { igmp_input_trace_t *tr; tr = vlib_add_trace (vm, node, b, sizeof (*tr)); tr->next_index = next; tr->sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX]; tr->len = vlib_buffer_length_in_chain (vm, b); clib_memcpy_fast (tr->packet_data, vlib_buffer_get_current (b), sizeof (tr->packet_data)); } vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, n_left_to_next, bi, next); } vlib_put_next_frame (vm, node, next_index, n_left_to_next); } return frame->n_vectors; } /* *INDENT-OFF* */ VLIB_REGISTER_NODE (igmp_input_node) = { .function = igmp_input, .name = "igmp-input", .vector_size = sizeof (u32), .format_buffer = format_igmp_header, .format_trace = format_igmp_input_trace, .n_errors = IGMP_N_ERROR, .error_strings = igmp_error_strings, .n_next_nodes = IGMP_INPUT_N_NEXT, .next_nodes = { [IGMP_INPUT_NEXT_DROP] = "error-drop", [IGMP_INPUT_NEXT_PARSE_QUERY] = "igmp-parse-query", [IGMP_INPUT_NEXT_PARSE_REPORT] = "igmp-parse-report", } }; /* *INDENT-ON* */ static uword igmp_parse_query (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) { u32 n_left_from, *from, *to_next; igmp_parse_query_next_t next_index; from = vlib_frame_vector_args (frame); n_left_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) { igmp_membership_query_v3_t *igmp; igmp_query_args_t *args; u32 bi, next, len; vlib_buffer_t *b; next = IGMP_PARSE_QUERY_NEXT_DROP; bi = from[0]; to_next[0] = bi; from++; to_next++; n_left_from--; n_left_to_next--; b = vlib_get_buffer (vm, bi); igmp = vlib_buffer_get_current (b); ASSERT (igmp->header.type == IGMP_TYPE_membership_query); len = igmp_membership_query_v3_length (igmp); if (node->flags & VLIB_NODE_FLAG_TRACE) { igmp_input_trace_t *tr; tr = vlib_add_trace (vm, node, b, sizeof (*tr)); tr->next_index = next; tr->sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX]; tr->len = len; clib_memcpy_fast (tr->packet_data, vlib_buffer_get_current (b), sizeof (tr->packet_data)); } /* * validate that the length on the packet on the wire corresponds * to at least the length of the calculated v3 query. * If there's extra, then it will be ignored. */ if (vlib_buffer_length_in_chain (vm, b) >= len) { /* * copy the contents of the query, and the interface, over * to the main thread for processing */ vlib_buffer_advance (b, -sizeof (u32)); args = vlib_buffer_get_current (b); args->sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX]; vl_api_rpc_call_main_thread (igmp_handle_query, (u8 *) args, sizeof (*args) + len); } else { /* * else a packet that is reporting more sources than it really * has; bin it */ b->error = node->errors[IGMP_ERROR_BAD_LENGTH]; } vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, n_left_to_next, bi, next); } vlib_put_next_frame (vm, node, next_index, n_left_to_next); } return frame->n_vectors; } /* *INDENT-OFF* */ VLIB_REGISTER_NODE (igmp_parse_query_node) = { .function = igmp_parse_query, .name = "igmp-parse-query", .vector_size = sizeof (u32), .format_buffer = format_igmp_query_v3, .format_trace = format_igmp_parse_query_trace, .n_errors = IGMP_N_ERROR, .error_strings = igmp_error_strings, .n_next_nodes = IGMP_PARSE_QUERY_N_NEXT, .next_nodes = { [IGMP_PARSE_QUERY_NEXT_DROP] = "error-drop", } }; /* *INDENT-ON* */ static uword igmp_parse_report (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) { u32 n_left_from, *from, *to_next; igmp_input_next_t next_index; vlib_node_runtime_t *error_node = vlib_node_get_runtime (vm, igmp_input_node.index); u8 error; from = vlib_frame_vector_args (frame); n_left_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) { igmp_membership_report_v3_t *igmp; igmp_report_args_t *args; u32 bi, next, len; vlib_buffer_t *b; next = IGMP_PARSE_REPORT_NEXT_DROP; bi = from[0]; to_next[0] = bi; from++; to_next++; n_left_from--; n_left_to_next--; b = vlib_get_buffer (vm, bi); error = IGMP_ERROR_NONE; b->error = error_node->errors[error]; igmp = vlib_buffer_get_current (b); len = igmp_membership_report_v3_length (igmp); ASSERT (igmp->header.type == IGMP_TYPE_membership_report_v3); if (node->flags & VLIB_NODE_FLAG_TRACE) { igmp_input_trace_t *tr; tr = vlib_add_trace (vm, node, b, sizeof (*tr)); tr->next_index = next; tr->len = len; tr->sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX]; clib_memcpy_fast (tr->packet_data, vlib_buffer_get_current (b), sizeof (tr->packet_data)); } /* * validate that the length on the packet on the wire * corresponds to the length on the calculated v3 query */ if (vlib_buffer_length_in_chain (vm, b) >= len) { /* * copy the contents of the query, and the interface, over * to the main thread for processing */ vlib_buffer_advance (b, -sizeof (u32)); args = vlib_buffer_get_current (b); args->sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX]; vl_api_rpc_call_main_thread (igmp_handle_report, (u8 *) args, sizeof (*args) + len); } else { /* * this is a packet with more groups/sources than the * header reports. bin it */ b->error = node->errors[IGMP_ERROR_BAD_LENGTH]; } vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, n_left_to_next, bi, next); } vlib_put_next_frame (vm, node, next_index, n_left_to_next); } return frame->n_vectors; } /* *INDENT-OFF* */ VLIB_REGISTER_NODE (igmp_parse_report_node) = { .function = igmp_parse_report, .name = "igmp-parse-report", .vector_size = sizeof (u32), .format_buffer = format_igmp_report_v3, .format_trace = format_igmp_parse_report_trace, .n_errors = IGMP_N_ERROR, .error_strings = igmp_error_strings, .n_next_nodes = IGMP_PARSE_REPORT_N_NEXT, .next_nodes = { [IGMP_PARSE_REPORT_NEXT_DROP] = "error-drop", } }; /* *INDENT-ON* */ static clib_error_t * igmp_input_init (vlib_main_t * vm) { ip4_register_protocol (IP_PROTOCOL_IGMP, igmp_input_node.index); IGMP_DBG ("input-initialized"); return (0); } /* *INDENT-OFF* */ VLIB_INIT_FUNCTION (igmp_input_init) = { .runs_after = VLIB_INITS("igmp_init"), }; /* *INDENT-ON* */ /* * fd.io coding-style-patch-verification: ON * * Local Variables: * eval: (c-set-style "gnu") * End: */