X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=vnet%2Fvnet%2Fip%2Fip6_forward.c;h=b5c795523caa800bd551f2f5517fad38b6920f86;hb=d7cb1b5f22948eba272e1a8844c75a2b87706fc4;hp=23f00885118660a1cfc00125831cf577d6075675;hpb=75fc854da7e92502581d83e31306b9912d3c53ff;p=vpp.git diff --git a/vnet/vnet/ip/ip6_forward.c b/vnet/vnet/ip/ip6_forward.c index 23f00885118..b5c795523ca 100644 --- a/vnet/vnet/ip/ip6_forward.c +++ b/vnet/vnet/ip/ip6_forward.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Cisco and/or its affiliates. + * 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: @@ -39,7 +39,7 @@ #include #include -#include /* for ethernet_header_t */ +#include /* for ethernet_header_t */ #include /* for srp_hw_interface_class */ #include #include @@ -49,22 +49,28 @@ #include +/** + * @file + * @brief IPv6 Forwarding. + * + * This file contains the source code for IPv6 forwarding. + */ + void ip6_forward_next_trace (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame, - vlib_rx_or_tx_t which_adj_index); + vlib_node_runtime_t * node, + vlib_frame_t * frame, + vlib_rx_or_tx_t which_adj_index); always_inline uword ip6_lookup_inline (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) + vlib_node_runtime_t * node, vlib_frame_t * frame) { - ip6_main_t * im = &ip6_main; - vlib_combined_counter_main_t * cm = &load_balance_main.lbm_to_counters; - u32 n_left_from, n_left_to_next, * from, * to_next; + ip6_main_t *im = &ip6_main; + vlib_combined_counter_main_t *cm = &load_balance_main.lbm_to_counters; + u32 n_left_from, n_left_to_next, *from, *to_next; ip_lookup_next_t next; - u32 cpu_index = os_get_cpu_number(); + u32 cpu_index = os_get_cpu_number (); from = vlib_frame_vector_args (frame); n_left_from = frame->n_vectors; @@ -72,24 +78,23 @@ ip6_lookup_inline (vlib_main_t * vm, while (n_left_from > 0) { - vlib_get_next_frame (vm, node, next, - to_next, n_left_to_next); + vlib_get_next_frame (vm, node, next, to_next, n_left_to_next); while (n_left_from >= 4 && n_left_to_next >= 2) { - vlib_buffer_t * p0, * p1; + vlib_buffer_t *p0, *p1; u32 pi0, pi1, lbi0, lbi1, wrong_next; ip_lookup_next_t next0, next1; - ip6_header_t * ip0, * ip1; - ip6_address_t * dst_addr0, * dst_addr1; - u32 fib_index0, fib_index1; - u32 flow_hash_config0, flow_hash_config1; + ip6_header_t *ip0, *ip1; + ip6_address_t *dst_addr0, *dst_addr1; + u32 fib_index0, fib_index1; + u32 flow_hash_config0, flow_hash_config1; const dpo_id_t *dpo0, *dpo1; const load_balance_t *lb0, *lb1; /* Prefetch next iteration. */ { - vlib_buffer_t * p2, * p3; + vlib_buffer_t *p2, *p3; p2 = vlib_get_buffer (vm, from[2]); p3 = vlib_get_buffer (vm, from[3]); @@ -112,13 +117,17 @@ ip6_lookup_inline (vlib_main_t * vm, dst_addr0 = &ip0->dst_address; dst_addr1 = &ip1->dst_address; - fib_index0 = vec_elt (im->fib_index_by_sw_if_index, vnet_buffer (p0)->sw_if_index[VLIB_RX]); - fib_index1 = vec_elt (im->fib_index_by_sw_if_index, vnet_buffer (p1)->sw_if_index[VLIB_RX]); + fib_index0 = + vec_elt (im->fib_index_by_sw_if_index, + vnet_buffer (p0)->sw_if_index[VLIB_RX]); + fib_index1 = + vec_elt (im->fib_index_by_sw_if_index, + vnet_buffer (p1)->sw_if_index[VLIB_RX]); - fib_index0 = (vnet_buffer(p0)->sw_if_index[VLIB_TX] == (u32)~0) ? - fib_index0 : vnet_buffer(p0)->sw_if_index[VLIB_TX]; - fib_index1 = (vnet_buffer(p1)->sw_if_index[VLIB_TX] == (u32)~0) ? - fib_index1 : vnet_buffer(p1)->sw_if_index[VLIB_TX]; + fib_index0 = (vnet_buffer (p0)->sw_if_index[VLIB_TX] == (u32) ~ 0) ? + fib_index0 : vnet_buffer (p0)->sw_if_index[VLIB_TX]; + fib_index1 = (vnet_buffer (p1)->sw_if_index[VLIB_TX] == (u32) ~ 0) ? + fib_index1 : vnet_buffer (p1)->sw_if_index[VLIB_TX]; lbi0 = ip6_fib_table_fwding_lookup (im, fib_index0, dst_addr0); lbi1 = ip6_fib_table_fwding_lookup (im, fib_index1, dst_addr1); @@ -126,64 +135,64 @@ ip6_lookup_inline (vlib_main_t * vm, lb0 = load_balance_get (lbi0); lb1 = load_balance_get (lbi1); - vnet_buffer (p0)->ip.flow_hash = - vnet_buffer(p1)->ip.flow_hash = 0; - - if (PREDICT_FALSE(lb0->lb_n_buckets > 1)) - { - flow_hash_config0 = lb0->lb_hash_config; - vnet_buffer (p0)->ip.flow_hash = - ip6_compute_flow_hash (ip0, flow_hash_config0); - } - if (PREDICT_FALSE(lb1->lb_n_buckets > 1)) - { - flow_hash_config1 = lb1->lb_hash_config; - vnet_buffer (p1)->ip.flow_hash = - ip6_compute_flow_hash (ip1, flow_hash_config1); - } + vnet_buffer (p0)->ip.flow_hash = vnet_buffer (p1)->ip.flow_hash = 0; + + if (PREDICT_FALSE (lb0->lb_n_buckets > 1)) + { + flow_hash_config0 = lb0->lb_hash_config; + vnet_buffer (p0)->ip.flow_hash = + ip6_compute_flow_hash (ip0, flow_hash_config0); + } + if (PREDICT_FALSE (lb1->lb_n_buckets > 1)) + { + flow_hash_config1 = lb1->lb_hash_config; + vnet_buffer (p1)->ip.flow_hash = + ip6_compute_flow_hash (ip1, flow_hash_config1); + } ASSERT (lb0->lb_n_buckets > 0); ASSERT (lb1->lb_n_buckets > 0); ASSERT (is_pow2 (lb0->lb_n_buckets)); ASSERT (is_pow2 (lb1->lb_n_buckets)); - dpo0 = load_balance_get_bucket_i(lb0, - (vnet_buffer (p0)->ip.flow_hash & - lb0->lb_n_buckets_minus_1)); - dpo1 = load_balance_get_bucket_i(lb1, - (vnet_buffer (p1)->ip.flow_hash & - lb1->lb_n_buckets_minus_1)); + dpo0 = load_balance_get_bucket_i (lb0, + (vnet_buffer (p0)->ip.flow_hash & + lb0->lb_n_buckets_minus_1)); + dpo1 = load_balance_get_bucket_i (lb1, + (vnet_buffer (p1)->ip.flow_hash & + lb1->lb_n_buckets_minus_1)); next0 = dpo0->dpoi_next_node; next1 = dpo1->dpoi_next_node; /* Only process the HBH Option Header if explicitly configured to do so */ - next0 = ((ip0->protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS) && - im->hbh_enabled) ? - (ip_lookup_next_t) IP6_LOOKUP_NEXT_HOP_BY_HOP : - next0; - next1 = ((ip1->protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS) && - im->hbh_enabled) ? - (ip_lookup_next_t) IP6_LOOKUP_NEXT_HOP_BY_HOP : - next1; - + if (PREDICT_FALSE + (ip0->protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS)) + { + next0 = (dpo_is_adj (dpo0) && im->hbh_enabled) ? + (ip_lookup_next_t) IP6_LOOKUP_NEXT_HOP_BY_HOP : next0; + } + if (PREDICT_FALSE + (ip1->protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS)) + { + next1 = (dpo_is_adj (dpo1) && im->hbh_enabled) ? + (ip_lookup_next_t) IP6_LOOKUP_NEXT_HOP_BY_HOP : next1; + } vnet_buffer (p0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index; vnet_buffer (p1)->ip.adj_index[VLIB_TX] = dpo1->dpoi_index; vlib_increment_combined_counter - (cm, cpu_index, lbi0, 1, - vlib_buffer_length_in_chain (vm, p0)); + (cm, cpu_index, lbi0, 1, vlib_buffer_length_in_chain (vm, p0)); vlib_increment_combined_counter - (cm, cpu_index, lbi1, 1, - vlib_buffer_length_in_chain (vm, p1)); + (cm, cpu_index, lbi1, 1, vlib_buffer_length_in_chain (vm, p1)); from += 2; to_next += 2; n_left_to_next -= 2; n_left_from -= 2; - wrong_next = (next0 != next) + 2*(next1 != next); + wrong_next = (next0 != next) + 2 * (next1 != next); if (PREDICT_FALSE (wrong_next != 0)) - { + { switch (wrong_next) { case 1: @@ -212,7 +221,8 @@ ip6_lookup_inline (vlib_main_t * vm, /* A B B */ vlib_put_next_frame (vm, node, next, n_left_to_next); next = next1; - vlib_get_next_frame (vm, node, next, to_next, n_left_to_next); + vlib_get_next_frame (vm, node, next, to_next, + n_left_to_next); } } } @@ -220,13 +230,13 @@ ip6_lookup_inline (vlib_main_t * vm, while (n_left_from > 0 && n_left_to_next > 0) { - vlib_buffer_t * p0; - ip6_header_t * ip0; + vlib_buffer_t *p0; + ip6_header_t *ip0; u32 pi0, lbi0; ip_lookup_next_t next0; - load_balance_t * lb0; - ip6_address_t * dst_addr0; - u32 fib_index0, flow_hash_config0; + load_balance_t *lb0; + ip6_address_t *dst_addr0; + u32 fib_index0, flow_hash_config0; const dpo_id_t *dpo0; pi0 = from[0]; @@ -238,43 +248,46 @@ ip6_lookup_inline (vlib_main_t * vm, dst_addr0 = &ip0->dst_address; - fib_index0 = vec_elt (im->fib_index_by_sw_if_index, vnet_buffer (p0)->sw_if_index[VLIB_RX]); - fib_index0 = (vnet_buffer(p0)->sw_if_index[VLIB_TX] == (u32)~0) ? - fib_index0 : vnet_buffer(p0)->sw_if_index[VLIB_TX]; + fib_index0 = + vec_elt (im->fib_index_by_sw_if_index, + vnet_buffer (p0)->sw_if_index[VLIB_RX]); + fib_index0 = + (vnet_buffer (p0)->sw_if_index[VLIB_TX] == + (u32) ~ 0) ? fib_index0 : vnet_buffer (p0)->sw_if_index[VLIB_TX]; - flow_hash_config0 = - ip6_fib_get (fib_index0)->flow_hash_config; + flow_hash_config0 = ip6_fib_get (fib_index0)->flow_hash_config; lbi0 = ip6_fib_table_fwding_lookup (im, fib_index0, dst_addr0); lb0 = load_balance_get (lbi0); - vnet_buffer (p0)->ip.flow_hash = 0; + vnet_buffer (p0)->ip.flow_hash = 0; - if (PREDICT_FALSE(lb0->lb_n_buckets > 1)) - { - flow_hash_config0 = lb0->lb_hash_config; - vnet_buffer (p0)->ip.flow_hash = - ip6_compute_flow_hash (ip0, flow_hash_config0); - } + if (PREDICT_FALSE (lb0->lb_n_buckets > 1)) + { + flow_hash_config0 = lb0->lb_hash_config; + vnet_buffer (p0)->ip.flow_hash = + ip6_compute_flow_hash (ip0, flow_hash_config0); + } ASSERT (lb0->lb_n_buckets > 0); ASSERT (is_pow2 (lb0->lb_n_buckets)); - dpo0 = load_balance_get_bucket_i(lb0, - (vnet_buffer (p0)->ip.flow_hash & - lb0->lb_n_buckets_minus_1)); + dpo0 = load_balance_get_bucket_i (lb0, + (vnet_buffer (p0)->ip.flow_hash & + lb0->lb_n_buckets_minus_1)); next0 = dpo0->dpoi_next_node; - /* Only process the HBH Option Header if explicitly configured to do so */ - next0 = ((ip0->protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS) && - im->hbh_enabled) ? - (ip_lookup_next_t) IP6_LOOKUP_NEXT_HOP_BY_HOP : - next0; + /* Only process the HBH Option Header if explicitly configured to do so */ + if (PREDICT_FALSE + (ip0->protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS)) + { + next0 = (dpo_is_adj (dpo0) && im->hbh_enabled) ? + (ip_lookup_next_t) IP6_LOOKUP_NEXT_HOP_BY_HOP : next0; + } vnet_buffer (p0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index; vlib_increment_combined_counter - (cm, cpu_index, lbi0, 1, - vlib_buffer_length_in_chain (vm, p0)); + (cm, cpu_index, lbi0, 1, vlib_buffer_length_in_chain (vm, p0)); from += 1; to_next += 1; @@ -286,8 +299,7 @@ ip6_lookup_inline (vlib_main_t * vm, n_left_to_next += 1; vlib_put_next_frame (vm, node, next, n_left_to_next); next = next0; - vlib_get_next_frame (vm, node, next, - to_next, n_left_to_next); + vlib_get_next_frame (vm, node, next, to_next, n_left_to_next); to_next[0] = pi0; to_next += 1; n_left_to_next -= 1; @@ -298,7 +310,7 @@ ip6_lookup_inline (vlib_main_t * vm, } if (node->flags & VLIB_NODE_FLAG_TRACE) - ip6_forward_next_trace(vm, node, frame, VLIB_TX); + ip6_forward_next_trace (vm, node, frame, VLIB_TX); return frame->n_vectors; } @@ -308,107 +320,77 @@ ip6_add_interface_routes (vnet_main_t * vnm, u32 sw_if_index, ip6_main_t * im, u32 fib_index, ip_interface_address_t * a) { - ip_lookup_main_t * lm = &im->lookup_main; - ip6_address_t * address = ip_interface_address_get_address (lm, a); + ip_lookup_main_t *lm = &im->lookup_main; + ip6_address_t *address = ip_interface_address_get_address (lm, a); fib_prefix_t pfx = { - .fp_len = a->address_length, - .fp_proto = FIB_PROTOCOL_IP6, - .fp_addr.ip6 = *address, + .fp_len = a->address_length, + .fp_proto = FIB_PROTOCOL_IP6, + .fp_addr.ip6 = *address, }; a->neighbor_probe_adj_index = ~0; if (a->address_length < 128) - { + { fib_node_index_t fei; - fei = fib_table_entry_update_one_path(fib_index, - &pfx, - FIB_SOURCE_INTERFACE, - (FIB_ENTRY_FLAG_CONNECTED | - FIB_ENTRY_FLAG_ATTACHED), - FIB_PROTOCOL_IP6, - NULL, /* No next-hop address */ - sw_if_index, - ~0, // invalid FIB index - 1, - MPLS_LABEL_INVALID, - FIB_ROUTE_PATH_FLAG_NONE); - a->neighbor_probe_adj_index = fib_entry_get_adj(fei); - } + fei = fib_table_entry_update_one_path (fib_index, &pfx, FIB_SOURCE_INTERFACE, (FIB_ENTRY_FLAG_CONNECTED | FIB_ENTRY_FLAG_ATTACHED), FIB_PROTOCOL_IP6, NULL, /* No next-hop address */ + sw_if_index, ~0, // invalid FIB index + 1, NULL, // no label stack + FIB_ROUTE_PATH_FLAG_NONE); + a->neighbor_probe_adj_index = fib_entry_get_adj (fei); + } pfx.fp_len = 128; if (sw_if_index < vec_len (lm->classify_table_index_by_sw_if_index)) - { + { u32 classify_table_index = - lm->classify_table_index_by_sw_if_index [sw_if_index]; - if (classify_table_index != (u32) ~0) - { - dpo_id_t dpo = DPO_NULL; - - dpo_set(&dpo, - DPO_CLASSIFY, - DPO_PROTO_IP4, - classify_dpo_create(FIB_PROTOCOL_IP6, - classify_table_index)); - - fib_table_entry_special_dpo_add(fib_index, - &pfx, - FIB_SOURCE_CLASSIFY, - FIB_ENTRY_FLAG_NONE, - &dpo); - dpo_reset(&dpo); - } - } + lm->classify_table_index_by_sw_if_index[sw_if_index]; + if (classify_table_index != (u32) ~ 0) + { + dpo_id_t dpo = DPO_INVALID; + + dpo_set (&dpo, + DPO_CLASSIFY, + DPO_PROTO_IP6, + classify_dpo_create (DPO_PROTO_IP6, classify_table_index)); + + fib_table_entry_special_dpo_add (fib_index, + &pfx, + FIB_SOURCE_CLASSIFY, + FIB_ENTRY_FLAG_NONE, &dpo); + dpo_reset (&dpo); + } + } - fib_table_entry_update_one_path(fib_index, - &pfx, - FIB_SOURCE_INTERFACE, - (FIB_ENTRY_FLAG_CONNECTED | - FIB_ENTRY_FLAG_LOCAL), - FIB_PROTOCOL_IP6, - &pfx.fp_addr, - sw_if_index, - ~0, // invalid FIB index - 1, - MPLS_LABEL_INVALID, - FIB_ROUTE_PATH_FLAG_NONE); + fib_table_entry_update_one_path (fib_index, &pfx, FIB_SOURCE_INTERFACE, (FIB_ENTRY_FLAG_CONNECTED | FIB_ENTRY_FLAG_LOCAL), FIB_PROTOCOL_IP6, &pfx.fp_addr, sw_if_index, ~0, // invalid FIB index + 1, NULL, FIB_ROUTE_PATH_FLAG_NONE); } static void ip6_del_interface_routes (ip6_main_t * im, u32 fib_index, - ip6_address_t * address, - u32 address_length) + ip6_address_t * address, u32 address_length) { - fib_prefix_t pfx = { - .fp_len = address_length, - .fp_proto = FIB_PROTOCOL_IP6, - .fp_addr.ip6 = *address, - }; + fib_prefix_t pfx = { + .fp_len = address_length, + .fp_proto = FIB_PROTOCOL_IP6, + .fp_addr.ip6 = *address, + }; - if (pfx.fp_len < 128) + if (pfx.fp_len < 128) { - fib_table_entry_delete(fib_index, - &pfx, - FIB_SOURCE_INTERFACE); + fib_table_entry_delete (fib_index, &pfx, FIB_SOURCE_INTERFACE); } - pfx.fp_len = 128; - fib_table_entry_delete(fib_index, - &pfx, - FIB_SOURCE_INTERFACE); + pfx.fp_len = 128; + fib_table_entry_delete (fib_index, &pfx, FIB_SOURCE_INTERFACE); } void -ip6_sw_interface_enable_disable (u32 sw_if_index, - u32 is_enable) +ip6_sw_interface_enable_disable (u32 sw_if_index, u32 is_enable) { - vlib_main_t * vm = vlib_get_main(); - ip6_main_t * im = &ip6_main; - ip_lookup_main_t * lm = &im->lookup_main; - u32 ci, cast; - u32 lookup_feature_index; + ip6_main_t *im = &ip6_main; vec_validate_init_empty (im->ip_enabled_by_sw_if_index, sw_if_index, 0); @@ -418,55 +400,34 @@ ip6_sw_interface_enable_disable (u32 sw_if_index, if (is_enable) { if (1 != ++im->ip_enabled_by_sw_if_index[sw_if_index]) - return; + return; } else { - ASSERT(im->ip_enabled_by_sw_if_index[sw_if_index] > 0); + ASSERT (im->ip_enabled_by_sw_if_index[sw_if_index] > 0); if (0 != --im->ip_enabled_by_sw_if_index[sw_if_index]) - return; + return; } - for (cast = 0; cast <= VNET_IP_RX_MULTICAST_FEAT; cast++) - { - ip_config_main_t * cm = &lm->feature_config_mains[cast]; - vnet_config_main_t * vcm = &cm->config_main; + vnet_feature_enable_disable ("ip6-unicast", "ip6-lookup", sw_if_index, + is_enable, 0, 0); - vec_validate_init_empty (cm->config_index_by_sw_if_index, sw_if_index, ~0); - ci = cm->config_index_by_sw_if_index[sw_if_index]; + vnet_feature_enable_disable ("ip6-multicast", "ip6-lookup", sw_if_index, + is_enable, 0, 0); - if (cast == VNET_IP_RX_UNICAST_FEAT) - lookup_feature_index = im->ip6_unicast_rx_feature_lookup; - else - lookup_feature_index = im->ip6_multicast_rx_feature_lookup; - - if (is_enable) - ci = vnet_config_add_feature (vm, vcm, - ci, - lookup_feature_index, - /* config data */ 0, - /* # bytes of config data */ 0); - else - ci = vnet_config_del_feature (vm, vcm, - ci, - lookup_feature_index, - /* config data */ 0, - /* # bytes of config data */ 0); - - cm->config_index_by_sw_if_index[sw_if_index] = ci; - } } /* get first interface address */ ip6_address_t * ip6_interface_first_address (ip6_main_t * im, u32 sw_if_index, - ip_interface_address_t ** result_ia) + ip_interface_address_t ** result_ia) { - ip_lookup_main_t * lm = &im->lookup_main; - ip_interface_address_t * ia = 0; - ip6_address_t * result = 0; + ip_lookup_main_t *lm = &im->lookup_main; + ip_interface_address_t *ia = 0; + ip6_address_t *result = 0; + /* *INDENT-OFF* */ foreach_ip_interface_address (lm, ia, sw_if_index, 1 /* honor unnumbered */, ({ @@ -474,6 +435,7 @@ ip6_interface_first_address (ip6_main_t * im, result = a; break; })); + /* *INDENT-ON* */ if (result_ia) *result_ia = result ? ia : 0; return result; @@ -483,15 +445,14 @@ clib_error_t * ip6_add_del_interface_address (vlib_main_t * vm, u32 sw_if_index, ip6_address_t * address, - u32 address_length, - u32 is_del) + u32 address_length, u32 is_del) { - vnet_main_t * vnm = vnet_get_main(); - ip6_main_t * im = &ip6_main; - ip_lookup_main_t * lm = &im->lookup_main; - clib_error_t * error; + vnet_main_t *vnm = vnet_get_main (); + ip6_main_t *im = &ip6_main; + ip_lookup_main_t *lm = &im->lookup_main; + clib_error_t *error; u32 if_address_index; - ip6_address_fib_t ip6_af, * addr_fib = 0; + ip6_address_fib_t ip6_af, *addr_fib = 0; vec_validate (im->fib_index_by_sw_if_index, sw_if_index); ip6_addr_fib_init (&ip6_af, address, @@ -502,12 +463,7 @@ ip6_add_del_interface_address (vlib_main_t * vm, uword elts_before = pool_elts (lm->if_address_pool); error = ip_interface_address_add_del - (lm, - sw_if_index, - addr_fib, - address_length, - is_del, - &if_address_index); + (lm, sw_if_index, addr_fib, address_length, is_del, &if_address_index); if (error) goto done; @@ -516,47 +472,48 @@ ip6_add_del_interface_address (vlib_main_t * vm, goto done; } + ip6_sw_interface_enable_disable (sw_if_index, !is_del); + if (is_del) - ip6_del_interface_routes (im, ip6_af.fib_index, address, - address_length); + ip6_del_interface_routes (im, ip6_af.fib_index, address, address_length); else - ip6_add_interface_routes (vnm, sw_if_index, - im, ip6_af.fib_index, - pool_elt_at_index (lm->if_address_pool, if_address_index)); + ip6_add_interface_routes (vnm, sw_if_index, + im, ip6_af.fib_index, + pool_elt_at_index (lm->if_address_pool, + if_address_index)); { - ip6_add_del_interface_address_callback_t * cb; + ip6_add_del_interface_address_callback_t *cb; vec_foreach (cb, im->add_del_interface_address_callbacks) cb->function (im, cb->function_opaque, sw_if_index, - address, address_length, - if_address_index, - is_del); + address, address_length, if_address_index, is_del); } - done: +done: vec_free (addr_fib); return error; } clib_error_t * -ip6_sw_interface_admin_up_down (vnet_main_t * vnm, - u32 sw_if_index, - u32 flags) +ip6_sw_interface_admin_up_down (vnet_main_t * vnm, u32 sw_if_index, u32 flags) { - ip6_main_t * im = &ip6_main; - ip_interface_address_t * ia; - ip6_address_t * a; + ip6_main_t *im = &ip6_main; + ip_interface_address_t *ia; + ip6_address_t *a; u32 is_admin_up, fib_index; /* Fill in lookup tables with default table (0). */ vec_validate (im->fib_index_by_sw_if_index, sw_if_index); - vec_validate_init_empty (im->lookup_main.if_address_pool_index_by_sw_if_index, sw_if_index, ~0); + vec_validate_init_empty (im-> + lookup_main.if_address_pool_index_by_sw_if_index, + sw_if_index, ~0); is_admin_up = (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) != 0; fib_index = vec_elt (im->fib_index_by_sw_if_index, sw_if_index); + /* *INDENT-OFF* */ foreach_ip_interface_address (&im->lookup_main, ia, sw_if_index, 0 /* honor unnumbered */, ({ @@ -569,6 +526,7 @@ ip6_sw_interface_admin_up_down (vnet_main_t * vnm, ip6_del_interface_routes (im, fib_index, a, ia->address_length); })); + /* *INDENT-ON* */ return 0; } @@ -576,172 +534,129 @@ ip6_sw_interface_admin_up_down (vnet_main_t * vnm, VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION (ip6_sw_interface_admin_up_down); /* Built-in ip6 unicast rx feature path definition */ -VNET_IP6_UNICAST_FEATURE_INIT (ip6_flow_classify, static) = { +/* *INDENT-OFF* */ +VNET_FEATURE_ARC_INIT (ip6_unicast, static) = +{ + .arc_name = "ip6-unicast", + .start_nodes = VNET_FEATURES ("ip6-input"), + .arc_index_ptr = &ip6_main.lookup_main.ucast_feature_arc_index, +}; + +VNET_FEATURE_INIT (ip6_flow_classify, static) = +{ + .arc_name = "ip6-unicast", .node_name = "ip6-flow-classify", - .runs_before = ORDER_CONSTRAINTS {"ip6-inacl", 0}, - .feature_index = &ip6_main.ip6_unicast_rx_feature_flow_classify, + .runs_before = VNET_FEATURES ("ip6-inacl"), }; -VNET_IP6_UNICAST_FEATURE_INIT (ip6_inacl, static) = { +VNET_FEATURE_INIT (ip6_inacl, static) = +{ + .arc_name = "ip6-unicast", .node_name = "ip6-inacl", - .runs_before = ORDER_CONSTRAINTS {"ip6-policer-classify", 0}, - .feature_index = &ip6_main.ip6_unicast_rx_feature_check_access, + .runs_before = VNET_FEATURES ("ip6-policer-classify"), }; -VNET_IP6_UNICAST_FEATURE_INIT (ip6_policer_classify, static) = { +VNET_FEATURE_INIT (ip6_policer_classify, static) = +{ + .arc_name = "ip6-unicast", .node_name = "ip6-policer-classify", - .runs_before = ORDER_CONSTRAINTS {"ipsec-input-ip6", 0}, - .feature_index = &ip6_main.ip6_unicast_rx_feature_policer_classify, + .runs_before = VNET_FEATURES ("ipsec-input-ip6"), }; -VNET_IP6_UNICAST_FEATURE_INIT (ip6_ipsec, static) = { +VNET_FEATURE_INIT (ip6_ipsec, static) = +{ + .arc_name = "ip6-unicast", .node_name = "ipsec-input-ip6", - .runs_before = ORDER_CONSTRAINTS {"l2tp-decap", 0}, - .feature_index = &ip6_main.ip6_unicast_rx_feature_ipsec, + .runs_before = VNET_FEATURES ("l2tp-decap"), }; -VNET_IP6_UNICAST_FEATURE_INIT (ip6_l2tp, static) = { +VNET_FEATURE_INIT (ip6_l2tp, static) = +{ + .arc_name = "ip6-unicast", .node_name = "l2tp-decap", - .runs_before = ORDER_CONSTRAINTS {"vpath-input-ip6", 0}, - .feature_index = &ip6_main.ip6_unicast_rx_feature_l2tp_decap, + .runs_before = VNET_FEATURES ("vpath-input-ip6"), }; -VNET_IP6_UNICAST_FEATURE_INIT (ip6_vpath, static) = { +VNET_FEATURE_INIT (ip6_vpath, static) = +{ + .arc_name = "ip6-unicast", .node_name = "vpath-input-ip6", - .runs_before = ORDER_CONSTRAINTS {"ip6-lookup", 0}, - .feature_index = &ip6_main.ip6_unicast_rx_feature_vpath, + .runs_before = VNET_FEATURES ("ip6-lookup"), }; -VNET_IP6_UNICAST_FEATURE_INIT (ip6_lookup, static) = { +VNET_FEATURE_INIT (ip6_lookup, static) = +{ + .arc_name = "ip6-unicast", .node_name = "ip6-lookup", - .runs_before = ORDER_CONSTRAINTS {"ip6-drop", 0}, - .feature_index = &ip6_main.ip6_unicast_rx_feature_lookup, + .runs_before = VNET_FEATURES ("ip6-drop"), }; -VNET_IP6_UNICAST_FEATURE_INIT (ip6_drop, static) = { +VNET_FEATURE_INIT (ip6_drop, static) = +{ + .arc_name = "ip6-unicast", .node_name = "ip6-drop", .runs_before = 0, /*last feature*/ - .feature_index = &ip6_main.ip6_unicast_rx_feature_drop, }; /* Built-in ip6 multicast rx feature path definition (none now) */ -VNET_IP6_MULTICAST_FEATURE_INIT (ip6_vpath_mc, static) = { +VNET_FEATURE_ARC_INIT (ip6_multicast, static) = +{ + .arc_name = "ip6-multicast", + .start_nodes = VNET_FEATURES ("ip6-input"), + .arc_index_ptr = &ip6_main.lookup_main.mcast_feature_arc_index, +}; + +VNET_FEATURE_INIT (ip6_vpath_mc, static) = { + .arc_name = "ip6-multicast", .node_name = "vpath-input-ip6", - .runs_before = ORDER_CONSTRAINTS {"ip6-lookup", 0}, - .feature_index = &ip6_main.ip6_multicast_rx_feature_vpath, + .runs_before = VNET_FEATURES ("ip6-lookup"), }; -VNET_IP6_MULTICAST_FEATURE_INIT (ip6_lookup, static) = { +VNET_FEATURE_INIT (ip6_mc_lookup, static) = { + .arc_name = "ip6-multicast", .node_name = "ip6-lookup", - .runs_before = ORDER_CONSTRAINTS {"ip6-drop", 0}, - .feature_index = &ip6_main.ip6_multicast_rx_feature_lookup, + .runs_before = VNET_FEATURES ("ip6-drop"), }; -VNET_IP6_MULTICAST_FEATURE_INIT (ip6_drop_mc, static) = { +VNET_FEATURE_INIT (ip6_drop_mc, static) = { + .arc_name = "ip6-multicast", .node_name = "ip6-drop", .runs_before = 0, /* last feature */ - .feature_index = &ip6_main.ip6_multicast_rx_feature_drop, }; -static char * rx_feature_start_nodes[] = - {"ip6-input"}; - -static char * tx_feature_start_nodes[] = +/* Built-in ip4 tx feature path definition */ +VNET_FEATURE_ARC_INIT (ip6_output, static) = { - "ip6-rewrite", - "ip6-midchain", + .arc_name = "ip6-output", + .start_nodes = VNET_FEATURES ("ip6-rewrite", "ip6-midchain"), + .arc_index_ptr = &ip6_main.lookup_main.output_feature_arc_index, }; -/* Built-in ip4 tx feature path definition */ -VNET_IP6_TX_FEATURE_INIT (interface_output, static) = { +VNET_FEATURE_INIT (ip6_ipsec_output, static) = { + .arc_name = "ip6-output", + .node_name = "ipsec-output-ip6", + .runs_before = VNET_FEATURES ("interface-output"), +}; + +VNET_FEATURE_INIT (ip6_interface_output, static) = { + .arc_name = "ip6-output", .node_name = "interface-output", .runs_before = 0, /* not before any other features */ - .feature_index = &ip6_main.ip6_tx_feature_interface_output, }; - -static clib_error_t * -ip6_feature_init (vlib_main_t * vm, ip6_main_t * im) -{ - ip_lookup_main_t * lm = &im->lookup_main; - clib_error_t * error; - vnet_cast_t cast; - ip_config_main_t * cm; - vnet_config_main_t * vcm; - char **feature_start_nodes; - int feature_start_len; - - for (cast = 0; cast < VNET_N_IP_FEAT; cast++) - { - cm = &lm->feature_config_mains[cast]; - vcm = &cm->config_main; - - if (cast < VNET_IP_TX_FEAT) - { - feature_start_nodes = rx_feature_start_nodes; - feature_start_len = ARRAY_LEN(rx_feature_start_nodes); - } - else - { - feature_start_nodes = tx_feature_start_nodes; - feature_start_len = ARRAY_LEN(tx_feature_start_nodes); - } - - if ((error = vnet_feature_arc_init (vm, vcm, - feature_start_nodes, - feature_start_len, - im->next_feature[cast], - &im->feature_nodes[cast]))) - return error; - } - return 0; -} +/* *INDENT-ON* */ clib_error_t * -ip6_sw_interface_add_del (vnet_main_t * vnm, - u32 sw_if_index, - u32 is_add) +ip6_sw_interface_add_del (vnet_main_t * vnm, u32 sw_if_index, u32 is_add) { - vlib_main_t * vm = vnm->vlib_main; - ip6_main_t * im = &ip6_main; - ip_lookup_main_t * lm = &im->lookup_main; - u32 ci, cast; - u32 feature_index; + vnet_feature_enable_disable ("ip6-unicast", "ip6-drop", sw_if_index, + is_add, 0, 0); - for (cast = 0; cast < VNET_N_IP_FEAT; cast++) - { - ip_config_main_t * cm = &lm->feature_config_mains[cast]; - vnet_config_main_t * vcm = &cm->config_main; + vnet_feature_enable_disable ("ip6-multicast", "ip6-drop", sw_if_index, + is_add, 0, 0); - vec_validate_init_empty (cm->config_index_by_sw_if_index, sw_if_index, ~0); - ci = cm->config_index_by_sw_if_index[sw_if_index]; + vnet_feature_enable_disable ("ip6-output", "interface-output", sw_if_index, + is_add, 0, 0); - if (cast == VNET_IP_RX_UNICAST_FEAT) - feature_index = im->ip6_unicast_rx_feature_drop; - else if (cast == VNET_IP_RX_MULTICAST_FEAT) - feature_index = im->ip6_multicast_rx_feature_drop; - else - feature_index = im->ip6_tx_feature_interface_output; - - if (is_add) - ci = vnet_config_add_feature (vm, vcm, - ci, - feature_index, - /* config data */ 0, - /* # bytes of config data */ 0); - else - { - ci = vnet_config_del_feature (vm, vcm, ci, - feature_index, - /* config data */ 0, - /* # bytes of config data */ 0); - if (vec_len(im->ip_enabled_by_sw_if_index) > sw_if_index) - im->ip_enabled_by_sw_if_index[sw_if_index] = 0; - } - cm->config_index_by_sw_if_index[sw_if_index] = ci; - /* - * note: do not update the tx feature count here. - */ - } return /* no error */ 0; } @@ -749,98 +664,223 @@ VNET_SW_INTERFACE_ADD_DEL_FUNCTION (ip6_sw_interface_add_del); static uword ip6_lookup (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) + vlib_node_runtime_t * node, vlib_frame_t * frame) { return ip6_lookup_inline (vm, node, frame); } -static u8 * format_ip6_lookup_trace (u8 * s, va_list * args); +static u8 *format_ip6_lookup_trace (u8 * s, va_list * args); -VLIB_REGISTER_NODE (ip6_lookup_node) = { +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE (ip6_lookup_node) = +{ .function = ip6_lookup, .name = "ip6-lookup", .vector_size = sizeof (u32), - .format_trace = format_ip6_lookup_trace, - .n_next_nodes = IP6_LOOKUP_N_NEXT, .next_nodes = IP6_LOOKUP_NEXT_NODES, }; +/* *INDENT-ON* */ -VLIB_NODE_FUNCTION_MULTIARCH (ip6_lookup_node, ip6_lookup) +VLIB_NODE_FUNCTION_MULTIARCH (ip6_lookup_node, ip6_lookup); always_inline uword ip6_load_balance (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) + vlib_node_runtime_t * node, vlib_frame_t * frame) { - vlib_combined_counter_main_t * cm = &load_balance_main.lbm_via_counters; - u32 n_left_from, n_left_to_next, * from, * to_next; + vlib_combined_counter_main_t *cm = &load_balance_main.lbm_via_counters; + u32 n_left_from, n_left_to_next, *from, *to_next; ip_lookup_next_t next; - u32 cpu_index = os_get_cpu_number(); + u32 cpu_index = os_get_cpu_number (); + ip6_main_t *im = &ip6_main; from = vlib_frame_vector_args (frame); n_left_from = frame->n_vectors; next = node->cached_next_index; if (node->flags & VLIB_NODE_FLAG_TRACE) - ip6_forward_next_trace(vm, node, frame, VLIB_TX); + ip6_forward_next_trace (vm, node, frame, VLIB_TX); while (n_left_from > 0) { - vlib_get_next_frame (vm, node, next, - to_next, n_left_to_next); + vlib_get_next_frame (vm, node, next, to_next, n_left_to_next); + + + while (n_left_from >= 4 && n_left_to_next >= 2) + { + ip_lookup_next_t next0, next1; + const load_balance_t *lb0, *lb1; + vlib_buffer_t *p0, *p1; + u32 pi0, lbi0, hc0, pi1, lbi1, hc1; + const ip6_header_t *ip0, *ip1; + const dpo_id_t *dpo0, *dpo1; + + /* Prefetch next iteration. */ + { + vlib_buffer_t *p2, *p3; + + p2 = vlib_get_buffer (vm, from[2]); + p3 = vlib_get_buffer (vm, from[3]); + + vlib_prefetch_buffer_header (p2, STORE); + vlib_prefetch_buffer_header (p3, STORE); + + CLIB_PREFETCH (p2->data, sizeof (ip0[0]), STORE); + CLIB_PREFETCH (p3->data, sizeof (ip0[0]), STORE); + } + + pi0 = to_next[0] = from[0]; + pi1 = to_next[1] = from[1]; + + from += 2; + n_left_from -= 2; + to_next += 2; + n_left_to_next -= 2; + + p0 = vlib_get_buffer (vm, pi0); + p1 = vlib_get_buffer (vm, pi1); + + ip0 = vlib_buffer_get_current (p0); + ip1 = vlib_buffer_get_current (p1); + lbi0 = vnet_buffer (p0)->ip.adj_index[VLIB_TX]; + lbi1 = vnet_buffer (p1)->ip.adj_index[VLIB_TX]; + + lb0 = load_balance_get (lbi0); + lb1 = load_balance_get (lbi1); + + /* + * this node is for via FIBs we can re-use the hash value from the + * to node if present. + * We don't want to use the same hash value at each level in the recursion + * graph as that would lead to polarisation + */ + hc0 = vnet_buffer (p0)->ip.flow_hash = 0; + hc1 = vnet_buffer (p1)->ip.flow_hash = 0; + + if (PREDICT_FALSE (lb0->lb_n_buckets > 1)) + { + if (PREDICT_TRUE (vnet_buffer (p0)->ip.flow_hash)) + { + hc0 = vnet_buffer (p0)->ip.flow_hash = + vnet_buffer (p0)->ip.flow_hash >> 1; + } + else + { + hc0 = vnet_buffer (p0)->ip.flow_hash = + ip6_compute_flow_hash (ip0, hc0); + } + } + if (PREDICT_FALSE (lb1->lb_n_buckets > 1)) + { + if (PREDICT_TRUE (vnet_buffer (p1)->ip.flow_hash)) + { + hc1 = vnet_buffer (p1)->ip.flow_hash = + vnet_buffer (p1)->ip.flow_hash >> 1; + } + else + { + hc1 = vnet_buffer (p1)->ip.flow_hash = + ip6_compute_flow_hash (ip1, hc1); + } + } + + dpo0 = + load_balance_get_bucket_i (lb0, + hc0 & (lb0->lb_n_buckets_minus_1)); + dpo1 = + load_balance_get_bucket_i (lb1, + hc1 & (lb1->lb_n_buckets_minus_1)); + next0 = dpo0->dpoi_next_node; + next1 = dpo1->dpoi_next_node; + + /* Only process the HBH Option Header if explicitly configured to do so */ + if (PREDICT_FALSE + (ip0->protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS)) + { + next0 = (dpo_is_adj (dpo0) && im->hbh_enabled) ? + (ip_lookup_next_t) IP6_LOOKUP_NEXT_HOP_BY_HOP : next0; + } + /* Only process the HBH Option Header if explicitly configured to do so */ + if (PREDICT_FALSE + (ip1->protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS)) + { + next1 = (dpo_is_adj (dpo1) && im->hbh_enabled) ? + (ip_lookup_next_t) IP6_LOOKUP_NEXT_HOP_BY_HOP : next1; + } + + vnet_buffer (p0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index; + vnet_buffer (p1)->ip.adj_index[VLIB_TX] = dpo1->dpoi_index; + + vlib_increment_combined_counter + (cm, cpu_index, lbi0, 1, vlib_buffer_length_in_chain (vm, p0)); + vlib_increment_combined_counter + (cm, cpu_index, lbi1, 1, vlib_buffer_length_in_chain (vm, p1)); + + vlib_validate_buffer_enqueue_x2 (vm, node, next, + to_next, n_left_to_next, + pi0, pi1, next0, next1); + } while (n_left_from > 0 && n_left_to_next > 0) { ip_lookup_next_t next0; const load_balance_t *lb0; - vlib_buffer_t * p0; + vlib_buffer_t *p0; u32 pi0, lbi0, hc0; const ip6_header_t *ip0; const dpo_id_t *dpo0; pi0 = from[0]; to_next[0] = pi0; + from += 1; + to_next += 1; + n_left_to_next -= 1; + n_left_from -= 1; p0 = vlib_get_buffer (vm, pi0); ip0 = vlib_buffer_get_current (p0); lbi0 = vnet_buffer (p0)->ip.adj_index[VLIB_TX]; - lb0 = load_balance_get(lbi0); - hc0 = lb0->lb_hash_config; - vnet_buffer(p0)->ip.flow_hash = ip6_compute_flow_hash(ip0, hc0); + lb0 = load_balance_get (lbi0); - dpo0 = load_balance_get_bucket_i(lb0, - vnet_buffer(p0)->ip.flow_hash & - (lb0->lb_n_buckets - 1)); + hc0 = vnet_buffer (p0)->ip.flow_hash = 0; + if (PREDICT_FALSE (lb0->lb_n_buckets > 1)) + { + if (PREDICT_TRUE (vnet_buffer (p0)->ip.flow_hash)) + { + hc0 = vnet_buffer (p0)->ip.flow_hash = + vnet_buffer (p0)->ip.flow_hash >> 1; + } + else + { + hc0 = vnet_buffer (p0)->ip.flow_hash = + ip6_compute_flow_hash (ip0, hc0); + } + } + dpo0 = + load_balance_get_bucket_i (lb0, + hc0 & (lb0->lb_n_buckets_minus_1)); next0 = dpo0->dpoi_next_node; vnet_buffer (p0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index; - vlib_increment_combined_counter - (cm, cpu_index, lbi0, 1, - vlib_buffer_length_in_chain (vm, p0)); - - from += 1; - to_next += 1; - n_left_to_next -= 1; - n_left_from -= 1; - - if (PREDICT_FALSE (next0 != next)) + /* Only process the HBH Option Header if explicitly configured to do so */ + if (PREDICT_FALSE + (ip0->protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS)) { - n_left_to_next += 1; - vlib_put_next_frame (vm, node, next, n_left_to_next); - next = next0; - vlib_get_next_frame (vm, node, next, - to_next, n_left_to_next); - to_next[0] = pi0; - to_next += 1; - n_left_to_next -= 1; + next0 = (dpo_is_adj (dpo0) && im->hbh_enabled) ? + (ip_lookup_next_t) IP6_LOOKUP_NEXT_HOP_BY_HOP : next0; } + + vlib_increment_combined_counter + (cm, cpu_index, lbi0, 1, vlib_buffer_length_in_chain (vm, p0)); + + vlib_validate_buffer_enqueue_x1 (vm, node, next, + to_next, n_left_to_next, + pi0, next0); } vlib_put_next_frame (vm, node, next, n_left_to_next); @@ -849,73 +889,78 @@ ip6_load_balance (vlib_main_t * vm, return frame->n_vectors; } -VLIB_REGISTER_NODE (ip6_load_balance_node) = { +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE (ip6_load_balance_node) = +{ .function = ip6_load_balance, .name = "ip6-load-balance", .vector_size = sizeof (u32), .sibling_of = "ip6-lookup", .format_trace = format_ip6_lookup_trace, - .n_next_nodes = 0, }; +/* *INDENT-ON* */ -VLIB_NODE_FUNCTION_MULTIARCH (ip6_load_balance_node, ip6_load_balance) +VLIB_NODE_FUNCTION_MULTIARCH (ip6_load_balance_node, ip6_load_balance); -typedef struct { +typedef struct +{ /* Adjacency taken. */ u32 adj_index; u32 flow_hash; u32 fib_index; /* Packet data, possibly *after* rewrite. */ - u8 packet_data[128 - 1*sizeof(u32)]; -} ip6_forward_next_trace_t; + u8 packet_data[128 - 1 * sizeof (u32)]; +} +ip6_forward_next_trace_t; -static u8 * format_ip6_forward_next_trace (u8 * s, va_list * args) +static u8 * +format_ip6_forward_next_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 *); - ip6_forward_next_trace_t * t = va_arg (*args, ip6_forward_next_trace_t *); + ip6_forward_next_trace_t *t = va_arg (*args, ip6_forward_next_trace_t *); uword indent = format_get_indent (s); - s = format(s, "%U%U", - format_white_space, indent, - format_ip6_header, t->packet_data, sizeof (t->packet_data)); + s = format (s, "%U%U", + format_white_space, indent, + format_ip6_header, t->packet_data, sizeof (t->packet_data)); return s; } -static u8 * format_ip6_lookup_trace (u8 * s, va_list * args) +static u8 * +format_ip6_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 *); - ip6_forward_next_trace_t * t = va_arg (*args, ip6_forward_next_trace_t *); + ip6_forward_next_trace_t *t = va_arg (*args, ip6_forward_next_trace_t *); uword indent = format_get_indent (s); s = format (s, "fib %d dpo-idx %d flow hash: 0x%08x", - t->fib_index, t->adj_index, t->flow_hash); - s = format(s, "\n%U%U", - format_white_space, indent, - format_ip6_header, t->packet_data, sizeof (t->packet_data)); + t->fib_index, t->adj_index, t->flow_hash); + s = format (s, "\n%U%U", + format_white_space, indent, + format_ip6_header, t->packet_data, sizeof (t->packet_data)); return s; } -static u8 * format_ip6_rewrite_trace (u8 * s, va_list * args) +static u8 * +format_ip6_rewrite_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 *); - ip6_forward_next_trace_t * t = va_arg (*args, ip6_forward_next_trace_t *); - vnet_main_t * vnm = vnet_get_main(); + ip6_forward_next_trace_t *t = va_arg (*args, ip6_forward_next_trace_t *); + vnet_main_t *vnm = vnet_get_main (); uword indent = format_get_indent (s); s = format (s, "tx_sw_if_index %d adj-idx %d : %U flow hash: 0x%08x", - t->fib_index, t->adj_index, format_ip_adjacency, - vnm, t->adj_index, FORMAT_IP_ADJACENCY_NONE, - t->flow_hash); + t->fib_index, t->adj_index, format_ip_adjacency, + t->adj_index, FORMAT_IP_ADJACENCY_NONE, t->flow_hash); s = format (s, "\n%U%U", - format_white_space, indent, - format_ip_adjacency_packet_data, - vnm, t->adj_index, - t->packet_data, sizeof (t->packet_data)); + format_white_space, indent, + format_ip_adjacency_packet_data, + vnm, t->adj_index, t->packet_data, sizeof (t->packet_data)); return s; } @@ -923,11 +968,10 @@ static u8 * format_ip6_rewrite_trace (u8 * s, va_list * args) void ip6_forward_next_trace (vlib_main_t * vm, vlib_node_runtime_t * node, - vlib_frame_t * frame, - vlib_rx_or_tx_t which_adj_index) + vlib_frame_t * frame, vlib_rx_or_tx_t which_adj_index) { - u32 * from, n_left; - ip6_main_t * im = &ip6_main; + u32 *from, n_left; + ip6_main_t *im = &ip6_main; n_left = frame->n_vectors; from = vlib_frame_vector_args (frame); @@ -935,8 +979,8 @@ ip6_forward_next_trace (vlib_main_t * vm, while (n_left >= 4) { u32 bi0, bi1; - vlib_buffer_t * b0, * b1; - ip6_forward_next_trace_t * t0, * t1; + vlib_buffer_t *b0, *b1; + ip6_forward_next_trace_t *t0, *t1; /* Prefetch next iteration. */ vlib_prefetch_buffer_with_index (vm, from[2], LOAD); @@ -952,29 +996,31 @@ ip6_forward_next_trace (vlib_main_t * vm, { t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0])); t0->adj_index = vnet_buffer (b0)->ip.adj_index[which_adj_index]; - t0->flow_hash = vnet_buffer (b0)->ip.flow_hash; - t0->fib_index = (vnet_buffer(b0)->sw_if_index[VLIB_TX] != (u32)~0) ? - vnet_buffer(b0)->sw_if_index[VLIB_TX] : - vec_elt (im->fib_index_by_sw_if_index, - vnet_buffer(b0)->sw_if_index[VLIB_RX]); + t0->flow_hash = vnet_buffer (b0)->ip.flow_hash; + t0->fib_index = + (vnet_buffer (b0)->sw_if_index[VLIB_TX] != + (u32) ~ 0) ? vnet_buffer (b0)->sw_if_index[VLIB_TX] : + vec_elt (im->fib_index_by_sw_if_index, + vnet_buffer (b0)->sw_if_index[VLIB_RX]); clib_memcpy (t0->packet_data, - vlib_buffer_get_current (b0), - sizeof (t0->packet_data)); + vlib_buffer_get_current (b0), + sizeof (t0->packet_data)); } if (b1->flags & VLIB_BUFFER_IS_TRACED) { t1 = vlib_add_trace (vm, node, b1, sizeof (t1[0])); t1->adj_index = vnet_buffer (b1)->ip.adj_index[which_adj_index]; - t1->flow_hash = vnet_buffer (b1)->ip.flow_hash; - t1->fib_index = (vnet_buffer(b1)->sw_if_index[VLIB_TX] != (u32)~0) ? - vnet_buffer(b1)->sw_if_index[VLIB_TX] : - vec_elt (im->fib_index_by_sw_if_index, - vnet_buffer(b1)->sw_if_index[VLIB_RX]); + t1->flow_hash = vnet_buffer (b1)->ip.flow_hash; + t1->fib_index = + (vnet_buffer (b1)->sw_if_index[VLIB_TX] != + (u32) ~ 0) ? vnet_buffer (b1)->sw_if_index[VLIB_TX] : + vec_elt (im->fib_index_by_sw_if_index, + vnet_buffer (b1)->sw_if_index[VLIB_RX]); clib_memcpy (t1->packet_data, - vlib_buffer_get_current (b1), - sizeof (t1->packet_data)); + vlib_buffer_get_current (b1), + sizeof (t1->packet_data)); } from += 2; n_left -= 2; @@ -983,8 +1029,8 @@ ip6_forward_next_trace (vlib_main_t * vm, while (n_left >= 1) { u32 bi0; - vlib_buffer_t * b0; - ip6_forward_next_trace_t * t0; + vlib_buffer_t *b0; + ip6_forward_next_trace_t *t0; bi0 = from[0]; @@ -994,15 +1040,16 @@ ip6_forward_next_trace (vlib_main_t * vm, { t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0])); t0->adj_index = vnet_buffer (b0)->ip.adj_index[which_adj_index]; - t0->flow_hash = vnet_buffer (b0)->ip.flow_hash; - t0->fib_index = (vnet_buffer(b0)->sw_if_index[VLIB_TX] != (u32)~0) ? - vnet_buffer(b0)->sw_if_index[VLIB_TX] : - vec_elt (im->fib_index_by_sw_if_index, - vnet_buffer(b0)->sw_if_index[VLIB_RX]); + t0->flow_hash = vnet_buffer (b0)->ip.flow_hash; + t0->fib_index = + (vnet_buffer (b0)->sw_if_index[VLIB_TX] != + (u32) ~ 0) ? vnet_buffer (b0)->sw_if_index[VLIB_TX] : + vec_elt (im->fib_index_by_sw_if_index, + vnet_buffer (b0)->sw_if_index[VLIB_RX]); clib_memcpy (t0->packet_data, - vlib_buffer_get_current (b0), - sizeof (t0->packet_data)); + vlib_buffer_get_current (b0), + sizeof (t0->packet_data)); } from += 1; n_left -= 1; @@ -1012,19 +1059,16 @@ ip6_forward_next_trace (vlib_main_t * vm, static uword ip6_drop_or_punt (vlib_main_t * vm, vlib_node_runtime_t * node, - vlib_frame_t * frame, - ip6_error_t error_code) + vlib_frame_t * frame, ip6_error_t error_code) { - u32 * buffers = vlib_frame_vector_args (frame); + u32 *buffers = vlib_frame_vector_args (frame); uword n_packets = frame->n_vectors; - vlib_error_drop_buffers (vm, node, - buffers, + vlib_error_drop_buffers (vm, node, buffers, /* stride */ 1, n_packets, /* next */ 0, - ip6_input_node.index, - error_code); + ip6_input_node.index, error_code); if (node->flags & VLIB_NODE_FLAG_TRACE) ip6_forward_next_trace (vm, node, frame, VLIB_TX); @@ -1033,70 +1077,77 @@ ip6_drop_or_punt (vlib_main_t * vm, } static uword -ip6_drop (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ return ip6_drop_or_punt (vm, node, frame, IP6_ERROR_ADJACENCY_DROP); } +ip6_drop (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) +{ + return ip6_drop_or_punt (vm, node, frame, IP6_ERROR_ADJACENCY_DROP); +} static uword -ip6_punt (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ return ip6_drop_or_punt (vm, node, frame, IP6_ERROR_ADJACENCY_PUNT); } +ip6_punt (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) +{ + return ip6_drop_or_punt (vm, node, frame, IP6_ERROR_ADJACENCY_PUNT); +} -VLIB_REGISTER_NODE (ip6_drop_node,static) = { +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE (ip6_drop_node, static) = +{ .function = ip6_drop, .name = "ip6-drop", .vector_size = sizeof (u32), - .format_trace = format_ip6_forward_next_trace, - .n_next_nodes = 1, - .next_nodes = { - [0] = "error-drop", - }, + .next_nodes = + { + [0] = "error-drop",}, }; +/* *INDENT-ON* */ -VLIB_NODE_FUNCTION_MULTIARCH (ip6_drop_node, ip6_drop) +VLIB_NODE_FUNCTION_MULTIARCH (ip6_drop_node, ip6_drop); -VLIB_REGISTER_NODE (ip6_punt_node,static) = { +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE (ip6_punt_node, static) = +{ .function = ip6_punt, .name = "ip6-punt", .vector_size = sizeof (u32), - .format_trace = format_ip6_forward_next_trace, - .n_next_nodes = 1, - .next_nodes = { - [0] = "error-punt", - }, + .next_nodes = + { + [0] = "error-punt",}, }; +/* *INDENT-ON* */ -VLIB_NODE_FUNCTION_MULTIARCH (ip6_punt_node, ip6_punt) +VLIB_NODE_FUNCTION_MULTIARCH (ip6_punt_node, ip6_punt); -VLIB_REGISTER_NODE (ip6_multicast_node,static) = { +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE (ip6_multicast_node, static) = +{ .function = ip6_drop, .name = "ip6-multicast", .vector_size = sizeof (u32), - .format_trace = format_ip6_forward_next_trace, - .n_next_nodes = 1, - .next_nodes = { + .next_nodes = + { [0] = "error-drop", }, }; +/* *INDENT-ON* */ + /* Compute TCP/UDP/ICMP6 checksum in software. */ -u16 ip6_tcp_udp_icmp_compute_checksum (vlib_main_t * vm, vlib_buffer_t * p0, ip6_header_t * ip0, int *bogus_lengthp) +u16 +ip6_tcp_udp_icmp_compute_checksum (vlib_main_t * vm, vlib_buffer_t * p0, + ip6_header_t * ip0, int *bogus_lengthp) { ip_csum_t sum0; u16 sum16, payload_length_host_byte_order; u32 i, n_this_buffer, n_bytes_left; - u32 headers_size = sizeof(ip0[0]); - void * data_this_buffer; + u32 headers_size = sizeof (ip0[0]); + void *data_this_buffer; - ASSERT(bogus_lengthp); + ASSERT (bogus_lengthp); *bogus_lengthp = 0; /* Initialize checksum with ip header. */ @@ -1107,59 +1158,37 @@ u16 ip6_tcp_udp_icmp_compute_checksum (vlib_main_t * vm, vlib_buffer_t * p0, ip6 for (i = 0; i < ARRAY_LEN (ip0->src_address.as_uword); i++) { sum0 = ip_csum_with_carry (sum0, - clib_mem_unaligned (&ip0->src_address.as_uword[i], uword)); - sum0 = ip_csum_with_carry (sum0, - clib_mem_unaligned (&ip0->dst_address.as_uword[i], uword)); + clib_mem_unaligned (&ip0-> + src_address.as_uword[i], + uword)); + sum0 = + ip_csum_with_carry (sum0, + clib_mem_unaligned (&ip0->dst_address.as_uword[i], + uword)); } /* some icmp packets may come with a "router alert" hop-by-hop extension header (e.g., mldv2 packets) */ - if (PREDICT_FALSE (ip0->protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS)) + if (PREDICT_FALSE (ip0->protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS)) { - u32 skip_bytes; - ip6_hop_by_hop_ext_t *ext_hdr = (ip6_hop_by_hop_ext_t *)data_this_buffer; + u32 skip_bytes; + ip6_hop_by_hop_ext_t *ext_hdr = + (ip6_hop_by_hop_ext_t *) data_this_buffer; /* validate really icmp6 next */ - ASSERT(ext_hdr->next_hdr == IP_PROTOCOL_ICMP6); + ASSERT (ext_hdr->next_hdr == IP_PROTOCOL_ICMP6); - skip_bytes = 8* (1 + ext_hdr->n_data_u64s); - data_this_buffer = (void *)((u8 *)data_this_buffer + skip_bytes); + skip_bytes = 8 * (1 + ext_hdr->n_data_u64s); + data_this_buffer = (void *) ((u8 *) data_this_buffer + skip_bytes); - payload_length_host_byte_order -= skip_bytes; + payload_length_host_byte_order -= skip_bytes; headers_size += skip_bytes; - } + } n_bytes_left = n_this_buffer = payload_length_host_byte_order; -#if DPDK > 0 - if (p0 && n_this_buffer + headers_size > p0->current_length) - { - struct rte_mbuf *mb = rte_mbuf_from_vlib_buffer(p0); - u8 nb_segs = mb->nb_segs; - - n_this_buffer = (p0->current_length > headers_size ? - p0->current_length - headers_size : 0); - while (n_bytes_left) - { - sum0 = ip_incremental_checksum (sum0, data_this_buffer, n_this_buffer); - n_bytes_left -= n_this_buffer; - - mb = mb->next; - nb_segs--; - if ((nb_segs == 0) || (mb == 0)) - break; - - data_this_buffer = rte_ctrlmbuf_data(mb); - n_this_buffer = mb->data_len; - } - if (n_bytes_left || nb_segs) - { - *bogus_lengthp = 1; - return 0xfefe; - } - } - else sum0 = ip_incremental_checksum (sum0, data_this_buffer, n_this_buffer); -#else - if (p0 && n_this_buffer + headers_size > p0->current_length) - n_this_buffer = p0->current_length > headers_size ? p0->current_length - headers_size : 0; + if (p0 && n_this_buffer + headers_size > p0->current_length) + n_this_buffer = + p0->current_length > + headers_size ? p0->current_length - headers_size : 0; while (1) { sum0 = ip_incremental_checksum (sum0, data_this_buffer, n_this_buffer); @@ -1168,25 +1197,25 @@ u16 ip6_tcp_udp_icmp_compute_checksum (vlib_main_t * vm, vlib_buffer_t * p0, ip6 break; if (!(p0->flags & VLIB_BUFFER_NEXT_PRESENT)) - { - *bogus_lengthp = 1; - return 0xfefe; - } + { + *bogus_lengthp = 1; + return 0xfefe; + } p0 = vlib_get_buffer (vm, p0->next_buffer); data_this_buffer = vlib_buffer_get_current (p0); n_this_buffer = p0->current_length; } -#endif /* DPDK */ - sum16 = ~ ip_csum_fold (sum0); + sum16 = ~ip_csum_fold (sum0); return sum16; } -u32 ip6_tcp_udp_icmp_validate_checksum (vlib_main_t * vm, vlib_buffer_t * p0) +u32 +ip6_tcp_udp_icmp_validate_checksum (vlib_main_t * vm, vlib_buffer_t * p0) { - ip6_header_t * ip0 = vlib_buffer_get_current (p0); - udp_header_t * udp0; + ip6_header_t *ip0 = vlib_buffer_get_current (p0); + udp_header_t *udp0; u16 sum16; int bogus_length; @@ -1194,7 +1223,7 @@ u32 ip6_tcp_udp_icmp_validate_checksum (vlib_main_t * vm, vlib_buffer_t * p0) ASSERT (ip0->protocol == IP_PROTOCOL_TCP || ip0->protocol == IP_PROTOCOL_ICMP6 || ip0->protocol == IP_PROTOCOL_UDP - || ip0->protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS); + || ip0->protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS); udp0 = (void *) (ip0 + 1); if (ip0->protocol == IP_PROTOCOL_UDP && udp0->checksum == 0) @@ -1212,16 +1241,89 @@ u32 ip6_tcp_udp_icmp_validate_checksum (vlib_main_t * vm, vlib_buffer_t * p0) return p0->flags; } +/* ip6_locate_header + * + * This function is to search for the header specified by the find_hdr number. + * 1. If the find_hdr < 0 then it finds and returns the protocol number and + * offset stored in *offset of the transport or ESP header in the chain if + * found. + * 2. If a header with find_hdr > 0 protocol number is found then the + * offset is stored in *offset and protocol number of the header is + * returned. + * 3. If find_hdr header is not found or packet is malformed or + * it is a non-first fragment -1 is returned. + */ +always_inline int +ip6_locate_header (vlib_buffer_t * p0, + ip6_header_t * ip0, int find_hdr, u32 * offset) +{ + u8 next_proto = ip0->protocol; + u8 *next_header; + u8 done = 0; + u32 cur_offset; + u8 *temp_nxthdr = 0; + u32 exthdr_len = 0; + + next_header = ip6_next_header (ip0); + cur_offset = sizeof (ip6_header_t); + while (1) + { + done = (next_proto == find_hdr); + if (PREDICT_FALSE + (next_header >= + (u8 *) vlib_buffer_get_current (p0) + p0->current_length)) + { + //A malicious packet could set an extension header with a too big size + return (-1); + } + if (done) + break; + if ((!ip6_ext_hdr (next_proto)) || next_proto == IP_PROTOCOL_IP6_NONXT) + { + if (find_hdr < 0) + break; + return -1; + } + if (next_proto == IP_PROTOCOL_IPV6_FRAGMENTATION) + { + ip6_frag_hdr_t *frag_hdr = (ip6_frag_hdr_t *) next_header; + u16 frag_off = ip6_frag_hdr_offset (frag_hdr); + /* Non first fragment return -1 */ + if (frag_off) + return (-1); + exthdr_len = sizeof (ip6_frag_hdr_t); + temp_nxthdr = next_header + exthdr_len; + } + else if (next_proto == IP_PROTOCOL_IPSEC_AH) + { + exthdr_len = + ip6_ext_authhdr_len (((ip6_ext_header_t *) next_header)); + temp_nxthdr = next_header + exthdr_len; + } + else + { + exthdr_len = + ip6_ext_header_len (((ip6_ext_header_t *) next_header)); + temp_nxthdr = next_header + exthdr_len; + } + next_proto = ((ip6_ext_header_t *) next_header)->next_hdr; + next_header = temp_nxthdr; + cur_offset += exthdr_len; + } + + *offset = cur_offset; + return (next_proto); +} + static uword -ip6_local (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) +ip6_local (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) { - ip6_main_t * im = &ip6_main; - ip_lookup_main_t * lm = &im->lookup_main; + ip6_main_t *im = &ip6_main; + ip_lookup_main_t *lm = &im->lookup_main; ip_local_next_t next_index; - u32 * from, * to_next, n_left_from, n_left_to_next; - vlib_node_runtime_t * error_node = vlib_node_get_runtime (vm, ip6_input_node.index); + u32 *from, *to_next, n_left_from, n_left_to_next; + vlib_node_runtime_t *error_node = + vlib_node_get_runtime (vm, ip6_input_node.index); from = vlib_frame_vector_args (frame); n_left_from = frame->n_vectors; @@ -1232,19 +1334,19 @@ ip6_local (vlib_main_t * vm, while (n_left_from > 0) { - vlib_get_next_frame (vm, node, next_index, - to_next, n_left_to_next); + vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); while (n_left_from >= 4 && n_left_to_next >= 2) { - vlib_buffer_t * p0, * p1; - ip6_header_t * ip0, * ip1; - udp_header_t * udp0, * udp1; + vlib_buffer_t *p0, *p1; + ip6_header_t *ip0, *ip1; + udp_header_t *udp0, *udp1; u32 pi0, ip_len0, udp_len0, flags0, next0; u32 pi1, ip_len1, udp_len1, flags1, next1; i32 len_diff0, len_diff1; u8 error0, type0, good_l4_checksum0; u8 error1, type1, good_l4_checksum1; + u32 udp_offset0, udp_offset1; pi0 = to_next[0] = from[0]; pi1 = to_next[1] = from[1]; @@ -1270,40 +1372,70 @@ ip6_local (vlib_main_t * vm, good_l4_checksum0 = (flags0 & IP_BUFFER_L4_CHECKSUM_CORRECT) != 0; good_l4_checksum1 = (flags1 & IP_BUFFER_L4_CHECKSUM_CORRECT) != 0; + len_diff0 = 0; + len_diff1 = 0; - udp0 = ip6_next_header (ip0); - udp1 = ip6_next_header (ip1); - - /* Don't verify UDP checksum for packets with explicit zero checksum. */ - good_l4_checksum0 |= type0 == IP_BUILTIN_PROTOCOL_UDP && udp0->checksum == 0; - good_l4_checksum1 |= type1 == IP_BUILTIN_PROTOCOL_UDP && udp1->checksum == 0; + /* Skip HBH local processing */ + if (PREDICT_FALSE + (ip0->protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS)) + { + ip6_hop_by_hop_ext_t *ext_hdr = + (ip6_hop_by_hop_ext_t *) ip6_next_header (ip0); + next0 = lm->local_next_by_ip_protocol[ext_hdr->next_hdr]; + type0 = lm->builtin_protocol_by_ip_protocol[ext_hdr->next_hdr]; + } + if (PREDICT_FALSE + (ip1->protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS)) + { + ip6_hop_by_hop_ext_t *ext_hdr = + (ip6_hop_by_hop_ext_t *) ip6_next_header (ip1); + next1 = lm->local_next_by_ip_protocol[ext_hdr->next_hdr]; + type1 = lm->builtin_protocol_by_ip_protocol[ext_hdr->next_hdr]; + } + if (PREDICT_TRUE (IP_PROTOCOL_UDP == ip6_locate_header (p0, ip0, + IP_PROTOCOL_UDP, + &udp_offset0))) + { + udp0 = (udp_header_t *) ((u8 *) ip0 + udp_offset0); + /* Don't verify UDP checksum for packets with explicit zero checksum. */ + good_l4_checksum0 |= type0 == IP_BUILTIN_PROTOCOL_UDP + && udp0->checksum == 0; + /* Verify UDP length. */ + ip_len0 = clib_net_to_host_u16 (ip0->payload_length); + udp_len0 = clib_net_to_host_u16 (udp0->length); + len_diff0 = ip_len0 - udp_len0; + } + if (PREDICT_TRUE (IP_PROTOCOL_UDP == ip6_locate_header (p1, ip1, + IP_PROTOCOL_UDP, + &udp_offset1))) + { + udp1 = (udp_header_t *) ((u8 *) ip1 + udp_offset1); + /* Don't verify UDP checksum for packets with explicit zero checksum. */ + good_l4_checksum1 |= type1 == IP_BUILTIN_PROTOCOL_UDP + && udp1->checksum == 0; + /* Verify UDP length. */ + ip_len1 = clib_net_to_host_u16 (ip1->payload_length); + udp_len1 = clib_net_to_host_u16 (udp1->length); + len_diff1 = ip_len1 - udp_len1; + } good_l4_checksum0 |= type0 == IP_BUILTIN_PROTOCOL_UNKNOWN; good_l4_checksum1 |= type1 == IP_BUILTIN_PROTOCOL_UNKNOWN; - /* Verify UDP length. */ - ip_len0 = clib_net_to_host_u16 (ip0->payload_length); - ip_len1 = clib_net_to_host_u16 (ip1->payload_length); - udp_len0 = clib_net_to_host_u16 (udp0->length); - udp_len1 = clib_net_to_host_u16 (udp1->length); - - len_diff0 = ip_len0 - udp_len0; - len_diff1 = ip_len1 - udp_len1; - len_diff0 = type0 == IP_BUILTIN_PROTOCOL_UDP ? len_diff0 : 0; len_diff1 = type1 == IP_BUILTIN_PROTOCOL_UDP ? len_diff1 : 0; if (PREDICT_FALSE (type0 != IP_BUILTIN_PROTOCOL_UNKNOWN - && ! good_l4_checksum0 - && ! (flags0 & IP_BUFFER_L4_CHECKSUM_COMPUTED))) + && !good_l4_checksum0 + && !(flags0 & IP_BUFFER_L4_CHECKSUM_COMPUTED))) { flags0 = ip6_tcp_udp_icmp_validate_checksum (vm, p0); good_l4_checksum0 = (flags0 & IP_BUFFER_L4_CHECKSUM_CORRECT) != 0; } if (PREDICT_FALSE (type1 != IP_BUILTIN_PROTOCOL_UNKNOWN - && ! good_l4_checksum1 - && ! (flags1 & IP_BUFFER_L4_CHECKSUM_COMPUTED))) + && !good_l4_checksum1 + && !(flags1 & IP_BUFFER_L4_CHECKSUM_COMPUTED))) { flags1 = ip6_tcp_udp_icmp_validate_checksum (vm, p1); good_l4_checksum1 = @@ -1315,38 +1447,38 @@ ip6_local (vlib_main_t * vm, error0 = len_diff0 < 0 ? IP6_ERROR_UDP_LENGTH : error0; error1 = len_diff1 < 0 ? IP6_ERROR_UDP_LENGTH : error1; - ASSERT (IP6_ERROR_UDP_CHECKSUM + IP_BUILTIN_PROTOCOL_UDP == IP6_ERROR_UDP_CHECKSUM); - ASSERT (IP6_ERROR_UDP_CHECKSUM + IP_BUILTIN_PROTOCOL_ICMP == IP6_ERROR_ICMP_CHECKSUM); - error0 = (! good_l4_checksum0 - ? IP6_ERROR_UDP_CHECKSUM + type0 - : error0); - error1 = (! good_l4_checksum1 - ? IP6_ERROR_UDP_CHECKSUM + type1 - : error1); + ASSERT (IP6_ERROR_UDP_CHECKSUM + IP_BUILTIN_PROTOCOL_UDP == + IP6_ERROR_UDP_CHECKSUM); + ASSERT (IP6_ERROR_UDP_CHECKSUM + IP_BUILTIN_PROTOCOL_ICMP == + IP6_ERROR_ICMP_CHECKSUM); + error0 = + (!good_l4_checksum0 ? IP6_ERROR_UDP_CHECKSUM + type0 : error0); + error1 = + (!good_l4_checksum1 ? IP6_ERROR_UDP_CHECKSUM + type1 : error1); /* Drop packets from unroutable hosts. */ - /* If this is a neighbor solicitation (ICMP), skip source RPF check */ + /* If this is a neighbor solicitation (ICMP), skip source RPF check */ if (error0 == IP6_ERROR_UNKNOWN_PROTOCOL && type0 != IP_BUILTIN_PROTOCOL_ICMP && - !ip6_address_is_link_local_unicast(&ip0->src_address)) + !ip6_address_is_link_local_unicast (&ip0->src_address)) { u32 src_adj_index0 = ip6_src_lookup_for_packet (im, p0, ip0); error0 = (ADJ_INDEX_INVALID == src_adj_index0 - ? IP6_ERROR_SRC_LOOKUP_MISS - : error0); + ? IP6_ERROR_SRC_LOOKUP_MISS : error0); } if (error1 == IP6_ERROR_UNKNOWN_PROTOCOL && type1 != IP_BUILTIN_PROTOCOL_ICMP && - !ip6_address_is_link_local_unicast(&ip1->src_address)) + !ip6_address_is_link_local_unicast (&ip1->src_address)) { u32 src_adj_index1 = ip6_src_lookup_for_packet (im, p1, ip1); error1 = (ADJ_INDEX_INVALID == src_adj_index1 - ? IP6_ERROR_SRC_LOOKUP_MISS - : error1); + ? IP6_ERROR_SRC_LOOKUP_MISS : error1); } - next0 = error0 != IP6_ERROR_UNKNOWN_PROTOCOL ? IP_LOCAL_NEXT_DROP : next0; - next1 = error1 != IP6_ERROR_UNKNOWN_PROTOCOL ? IP_LOCAL_NEXT_DROP : next1; + next0 = + error0 != IP6_ERROR_UNKNOWN_PROTOCOL ? IP_LOCAL_NEXT_DROP : next0; + next1 = + error1 != IP6_ERROR_UNKNOWN_PROTOCOL ? IP_LOCAL_NEXT_DROP : next1; p0->error = error_node->errors[error0]; p1->error = error_node->errors[error1]; @@ -1358,12 +1490,13 @@ ip6_local (vlib_main_t * vm, while (n_left_from > 0 && n_left_to_next > 0) { - vlib_buffer_t * p0; - ip6_header_t * ip0; - udp_header_t * udp0; + vlib_buffer_t *p0; + ip6_header_t *ip0; + udp_header_t *udp0; u32 pi0, ip_len0, udp_len0, flags0, next0; i32 len_diff0; u8 error0, type0, good_l4_checksum0; + u32 udp_offset0; pi0 = to_next[0] = from[0]; from += 1; @@ -1381,25 +1514,37 @@ ip6_local (vlib_main_t * vm, flags0 = p0->flags; good_l4_checksum0 = (flags0 & IP_BUFFER_L4_CHECKSUM_CORRECT) != 0; + len_diff0 = 0; - udp0 = ip6_next_header (ip0); - - /* Don't verify UDP checksum for packets with explicit zero checksum. */ - good_l4_checksum0 |= type0 == IP_BUILTIN_PROTOCOL_UDP && udp0->checksum == 0; + /* Skip HBH local processing */ + if (PREDICT_FALSE + (ip0->protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS)) + { + ip6_hop_by_hop_ext_t *ext_hdr = + (ip6_hop_by_hop_ext_t *) ip6_next_header (ip0); + next0 = lm->local_next_by_ip_protocol[ext_hdr->next_hdr]; + type0 = lm->builtin_protocol_by_ip_protocol[ext_hdr->next_hdr]; + } + if (PREDICT_TRUE (IP_PROTOCOL_UDP == ip6_locate_header (p0, ip0, + IP_PROTOCOL_UDP, + &udp_offset0))) + { + udp0 = (udp_header_t *) ((u8 *) ip0 + udp_offset0); + /* Don't verify UDP checksum for packets with explicit zero checksum. */ + good_l4_checksum0 |= type0 == IP_BUILTIN_PROTOCOL_UDP + && udp0->checksum == 0; + /* Verify UDP length. */ + ip_len0 = clib_net_to_host_u16 (ip0->payload_length); + udp_len0 = clib_net_to_host_u16 (udp0->length); + len_diff0 = ip_len0 - udp_len0; + } good_l4_checksum0 |= type0 == IP_BUILTIN_PROTOCOL_UNKNOWN; - - /* Verify UDP length. */ - ip_len0 = clib_net_to_host_u16 (ip0->payload_length); - udp_len0 = clib_net_to_host_u16 (udp0->length); - - len_diff0 = ip_len0 - udp_len0; - len_diff0 = type0 == IP_BUILTIN_PROTOCOL_UDP ? len_diff0 : 0; if (PREDICT_FALSE (type0 != IP_BUILTIN_PROTOCOL_UNKNOWN - && ! good_l4_checksum0 - && ! (flags0 & IP_BUFFER_L4_CHECKSUM_COMPUTED))) + && !good_l4_checksum0 + && !(flags0 & IP_BUFFER_L4_CHECKSUM_COMPUTED))) { flags0 = ip6_tcp_udp_icmp_validate_checksum (vm, p0); good_l4_checksum0 = @@ -1410,24 +1555,25 @@ ip6_local (vlib_main_t * vm, error0 = len_diff0 < 0 ? IP6_ERROR_UDP_LENGTH : error0; - ASSERT (IP6_ERROR_UDP_CHECKSUM + IP_BUILTIN_PROTOCOL_UDP == IP6_ERROR_UDP_CHECKSUM); - ASSERT (IP6_ERROR_UDP_CHECKSUM + IP_BUILTIN_PROTOCOL_ICMP == IP6_ERROR_ICMP_CHECKSUM); - error0 = (! good_l4_checksum0 - ? IP6_ERROR_UDP_CHECKSUM + type0 - : error0); + ASSERT (IP6_ERROR_UDP_CHECKSUM + IP_BUILTIN_PROTOCOL_UDP == + IP6_ERROR_UDP_CHECKSUM); + ASSERT (IP6_ERROR_UDP_CHECKSUM + IP_BUILTIN_PROTOCOL_ICMP == + IP6_ERROR_ICMP_CHECKSUM); + error0 = + (!good_l4_checksum0 ? IP6_ERROR_UDP_CHECKSUM + type0 : error0); - /* If this is a neighbor solicitation (ICMP), skip source RPF check */ + /* If this is a neighbor solicitation (ICMP), skip source RPF check */ if (error0 == IP6_ERROR_UNKNOWN_PROTOCOL && type0 != IP_BUILTIN_PROTOCOL_ICMP && - !ip6_address_is_link_local_unicast(&ip0->src_address)) + !ip6_address_is_link_local_unicast (&ip0->src_address)) { u32 src_adj_index0 = ip6_src_lookup_for_packet (im, p0, ip0); error0 = (ADJ_INDEX_INVALID == src_adj_index0 - ? IP6_ERROR_SRC_LOOKUP_MISS - : error0); + ? IP6_ERROR_SRC_LOOKUP_MISS : error0); } - next0 = error0 != IP6_ERROR_UNKNOWN_PROTOCOL ? IP_LOCAL_NEXT_DROP : next0; + next0 = + error0 != IP6_ERROR_UNKNOWN_PROTOCOL ? IP_LOCAL_NEXT_DROP : next0; p0->error = error_node->errors[error0]; @@ -1442,41 +1588,47 @@ ip6_local (vlib_main_t * vm, return frame->n_vectors; } -VLIB_REGISTER_NODE (ip6_local_node,static) = { +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE (ip6_local_node, static) = +{ .function = ip6_local, .name = "ip6-local", .vector_size = sizeof (u32), - .format_trace = format_ip6_forward_next_trace, - .n_next_nodes = IP_LOCAL_N_NEXT, - .next_nodes = { + .next_nodes = + { [IP_LOCAL_NEXT_DROP] = "error-drop", [IP_LOCAL_NEXT_PUNT] = "error-punt", [IP_LOCAL_NEXT_UDP_LOOKUP] = "ip6-udp-lookup", [IP_LOCAL_NEXT_ICMP] = "ip6-icmp-input", }, }; +/* *INDENT-ON* */ -VLIB_NODE_FUNCTION_MULTIARCH (ip6_local_node, ip6_local) +VLIB_NODE_FUNCTION_MULTIARCH (ip6_local_node, ip6_local); -void ip6_register_protocol (u32 protocol, u32 node_index) +void +ip6_register_protocol (u32 protocol, u32 node_index) { - vlib_main_t * vm = vlib_get_main(); - ip6_main_t * im = &ip6_main; - ip_lookup_main_t * lm = &im->lookup_main; + vlib_main_t *vm = vlib_get_main (); + ip6_main_t *im = &ip6_main; + ip_lookup_main_t *lm = &im->lookup_main; ASSERT (protocol < ARRAY_LEN (lm->local_next_by_ip_protocol)); - lm->local_next_by_ip_protocol[protocol] = vlib_node_add_next (vm, ip6_local_node.index, node_index); + lm->local_next_by_ip_protocol[protocol] = + vlib_node_add_next (vm, ip6_local_node.index, node_index); } -typedef enum { +typedef enum +{ IP6_DISCOVER_NEIGHBOR_NEXT_DROP, IP6_DISCOVER_NEIGHBOR_NEXT_REPLY_TX, IP6_DISCOVER_NEIGHBOR_N_NEXT, } ip6_discover_neighbor_next_t; -typedef enum { +typedef enum +{ IP6_DISCOVER_NEIGHBOR_ERROR_DROP, IP6_DISCOVER_NEIGHBOR_ERROR_REQUEST_SENT, IP6_DISCOVER_NEIGHBOR_ERROR_NO_SOURCE_ADDRESS, @@ -1485,13 +1637,12 @@ typedef enum { static uword ip6_discover_neighbor_inline (vlib_main_t * vm, vlib_node_runtime_t * node, - vlib_frame_t * frame, - int is_glean) + vlib_frame_t * frame, int is_glean) { - vnet_main_t * vnm = vnet_get_main(); - ip6_main_t * im = &ip6_main; - ip_lookup_main_t * lm = &im->lookup_main; - u32 * from, * to_next_drop; + vnet_main_t *vnm = vnet_get_main (); + ip6_main_t *im = &ip6_main; + ip_lookup_main_t *lm = &im->lookup_main; + u32 *from, *to_next_drop; uword n_left_from, n_left_to_next_drop; static f64 time_last_seed_change = -1e100; static u32 hash_seeds[3]; @@ -1506,8 +1657,8 @@ ip6_discover_neighbor_inline (vlib_main_t * vm, if (time_now - time_last_seed_change > 1e-3) { uword i; - u32 * r = clib_random_buffer_get_data (&vm->random_buffer, - sizeof (hash_seeds)); + u32 *r = clib_random_buffer_get_data (&vm->random_buffer, + sizeof (hash_seeds)); for (i = 0; i < ARRAY_LEN (hash_seeds); i++) hash_seeds[i] = r[i]; @@ -1528,12 +1679,12 @@ ip6_discover_neighbor_inline (vlib_main_t * vm, while (n_left_from > 0 && n_left_to_next_drop > 0) { - vlib_buffer_t * p0; - ip6_header_t * ip0; + vlib_buffer_t *p0; + ip6_header_t *ip0; u32 pi0, adj_index0, a0, b0, c0, m0, sw_if_index0, drop0; uword bm0; - ip_adjacency_t * adj0; - vnet_hw_interface_t * hw_if0; + ip_adjacency_t *adj0; + vnet_hw_interface_t *hw_if0; u32 next0; pi0 = from[0]; @@ -1548,8 +1699,10 @@ ip6_discover_neighbor_inline (vlib_main_t * vm, if (!is_glean) { - ip0->dst_address.as_u64[0] = adj0->sub_type.nbr.next_hop.ip6.as_u64[0]; - ip0->dst_address.as_u64[1] = adj0->sub_type.nbr.next_hop.ip6.as_u64[1]; + ip0->dst_address.as_u64[0] = + adj0->sub_type.nbr.next_hop.ip6.as_u64[0]; + ip0->dst_address.as_u64[1] = + adj0->sub_type.nbr.next_hop.ip6.as_u64[1]; } a0 = hash_seeds[0]; @@ -1586,46 +1739,54 @@ ip6_discover_neighbor_inline (vlib_main_t * vm, to_next_drop += 1; n_left_to_next_drop -= 1; - hw_if0 = vnet_get_sup_hw_interface (vnm, sw_if_index0); + hw_if0 = vnet_get_sup_hw_interface (vnm, sw_if_index0); - /* If the interface is link-down, drop the pkt */ - if (!(hw_if0->flags & VNET_HW_INTERFACE_FLAG_LINK_UP)) - drop0 = 1; + /* If the interface is link-down, drop the pkt */ + if (!(hw_if0->flags & VNET_HW_INTERFACE_FLAG_LINK_UP)) + drop0 = 1; p0->error = - node->errors[drop0 ? IP6_DISCOVER_NEIGHBOR_ERROR_DROP - : IP6_DISCOVER_NEIGHBOR_ERROR_REQUEST_SENT]; + node->errors[drop0 ? IP6_DISCOVER_NEIGHBOR_ERROR_DROP + : IP6_DISCOVER_NEIGHBOR_ERROR_REQUEST_SENT]; if (drop0) continue; + /* + * the adj has been updated to a rewrite but the node the DPO that got + * us here hasn't - yet. no big deal. we'll drop while we wait. + */ + if (IP_LOOKUP_NEXT_REWRITE == adj0->lookup_next_index) + continue; + { u32 bi0 = 0; - icmp6_neighbor_solicitation_header_t * h0; - vlib_buffer_t * b0; + icmp6_neighbor_solicitation_header_t *h0; + vlib_buffer_t *b0; h0 = vlib_packet_template_get_packet - (vm, &im->discover_neighbor_packet_template, &bi0); + (vm, &im->discover_neighbor_packet_template, &bi0); /* - * Build ethernet header. - * Choose source address based on destination lookup - * adjacency. - */ + * Build ethernet header. + * Choose source address based on destination lookup + * adjacency. + */ if (ip6_src_address_for_packet (lm, sw_if_index0, &h0->ip.src_address)) { /* There is no address on the interface */ - p0->error = node->errors[IP6_DISCOVER_NEIGHBOR_ERROR_NO_SOURCE_ADDRESS]; - vlib_buffer_free(vm, &bi0, 1); + p0->error = + node->errors[IP6_DISCOVER_NEIGHBOR_ERROR_NO_SOURCE_ADDRESS]; + vlib_buffer_free (vm, &bi0, 1); continue; } /* - * Destination address is a solicited node multicast address. - * We need to fill in - * the low 24 bits with low 24 bits of target's address. - */ + * Destination address is a solicited node multicast address. + * We need to fill in + * the low 24 bits with low 24 bits of target's address. + */ h0->ip.dst_address.as_u8[13] = ip0->dst_address.as_u8[13]; h0->ip.dst_address.as_u8[14] = ip0->dst_address.as_u8[14]; h0->ip.dst_address.as_u8[15] = ip0->dst_address.as_u8[15]; @@ -1633,24 +1794,23 @@ ip6_discover_neighbor_inline (vlib_main_t * vm, h0->neighbor.target_address = ip0->dst_address; clib_memcpy (h0->link_layer_option.ethernet_address, - hw_if0->hw_address, vec_len (hw_if0->hw_address)); + hw_if0->hw_address, vec_len (hw_if0->hw_address)); - /* $$$$ appears we need this; why is the checksum non-zero? */ - h0->neighbor.icmp.checksum = 0; + /* $$$$ appears we need this; why is the checksum non-zero? */ + h0->neighbor.icmp.checksum = 0; h0->neighbor.icmp.checksum = - ip6_tcp_udp_icmp_compute_checksum (vm, 0, &h0->ip, - &bogus_length); + ip6_tcp_udp_icmp_compute_checksum (vm, 0, &h0->ip, + &bogus_length); - ASSERT (bogus_length == 0); + ASSERT (bogus_length == 0); vlib_buffer_copy_trace_flag (vm, p0, bi0); b0 = vlib_get_buffer (vm, bi0); vnet_buffer (b0)->sw_if_index[VLIB_TX] - = vnet_buffer (p0)->sw_if_index[VLIB_TX]; + = vnet_buffer (p0)->sw_if_index[VLIB_TX]; /* Add rewrite/encap string. */ - vnet_rewrite_one_header (adj0[0], h0, - sizeof (ethernet_header_t)); + vnet_rewrite_one_header (adj0[0], h0, sizeof (ethernet_header_t)); vlib_buffer_advance (b0, -adj0->rewrite_header.data_bytes); next0 = IP6_DISCOVER_NEIGHBOR_NEXT_REPLY_TX; @@ -1660,7 +1820,7 @@ ip6_discover_neighbor_inline (vlib_main_t * vm, } vlib_put_next_frame (vm, node, IP6_DISCOVER_NEIGHBOR_NEXT_DROP, - n_left_to_next_drop); + n_left_to_next_drop); } return frame->n_vectors; @@ -1668,74 +1828,72 @@ ip6_discover_neighbor_inline (vlib_main_t * vm, static uword ip6_discover_neighbor (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) + vlib_node_runtime_t * node, vlib_frame_t * frame) { - return (ip6_discover_neighbor_inline(vm, node, frame, 0)); + return (ip6_discover_neighbor_inline (vm, node, frame, 0)); } static uword -ip6_glean (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) +ip6_glean (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) { - return (ip6_discover_neighbor_inline(vm, node, frame, 1)); + return (ip6_discover_neighbor_inline (vm, node, frame, 1)); } -static char * ip6_discover_neighbor_error_strings[] = { +static char *ip6_discover_neighbor_error_strings[] = { [IP6_DISCOVER_NEIGHBOR_ERROR_DROP] = "address overflow drops", - [IP6_DISCOVER_NEIGHBOR_ERROR_REQUEST_SENT] - = "neighbor solicitations sent", + [IP6_DISCOVER_NEIGHBOR_ERROR_REQUEST_SENT] = "neighbor solicitations sent", [IP6_DISCOVER_NEIGHBOR_ERROR_NO_SOURCE_ADDRESS] = "no source address for ND solicitation", }; -VLIB_REGISTER_NODE (ip6_discover_neighbor_node) = { +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE (ip6_discover_neighbor_node) = +{ .function = ip6_discover_neighbor, .name = "ip6-discover-neighbor", .vector_size = sizeof (u32), - .format_trace = format_ip6_forward_next_trace, - .n_errors = ARRAY_LEN (ip6_discover_neighbor_error_strings), .error_strings = ip6_discover_neighbor_error_strings, - .n_next_nodes = IP6_DISCOVER_NEIGHBOR_N_NEXT, - .next_nodes = { + .next_nodes = + { [IP6_DISCOVER_NEIGHBOR_NEXT_DROP] = "error-drop", [IP6_DISCOVER_NEIGHBOR_NEXT_REPLY_TX] = "interface-output", }, }; +/* *INDENT-ON* */ -VLIB_REGISTER_NODE (ip6_glean_node) = { +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE (ip6_glean_node) = +{ .function = ip6_glean, .name = "ip6-glean", .vector_size = sizeof (u32), - .format_trace = format_ip6_forward_next_trace, - .n_errors = ARRAY_LEN (ip6_discover_neighbor_error_strings), .error_strings = ip6_discover_neighbor_error_strings, - .n_next_nodes = IP6_DISCOVER_NEIGHBOR_N_NEXT, - .next_nodes = { + .next_nodes = + { [IP6_DISCOVER_NEIGHBOR_NEXT_DROP] = "error-drop", [IP6_DISCOVER_NEIGHBOR_NEXT_REPLY_TX] = "interface-output", }, }; +/* *INDENT-ON* */ clib_error_t * ip6_probe_neighbor (vlib_main_t * vm, ip6_address_t * dst, u32 sw_if_index) { - vnet_main_t * vnm = vnet_get_main(); - ip6_main_t * im = &ip6_main; - icmp6_neighbor_solicitation_header_t * h; - ip6_address_t * src; - ip_interface_address_t * ia; - ip_adjacency_t * adj; - vnet_hw_interface_t * hi; - vnet_sw_interface_t * si; - vlib_buffer_t * b; + vnet_main_t *vnm = vnet_get_main (); + ip6_main_t *im = &ip6_main; + icmp6_neighbor_solicitation_header_t *h; + ip6_address_t *src; + ip_interface_address_t *ia; + ip_adjacency_t *adj; + vnet_hw_interface_t *hi; + vnet_sw_interface_t *si; + vlib_buffer_t *b; u32 bi = 0; int bogus_length; @@ -1744,22 +1902,26 @@ ip6_probe_neighbor (vlib_main_t * vm, ip6_address_t * dst, u32 sw_if_index) if (!(si->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP)) { return clib_error_return (0, "%U: interface %U down", - format_ip6_address, dst, - format_vnet_sw_if_index_name, vnm, - sw_if_index); + format_ip6_address, dst, + format_vnet_sw_if_index_name, vnm, + sw_if_index); } - src = ip6_interface_address_matching_destination (im, dst, sw_if_index, &ia); - if (! src) + src = + ip6_interface_address_matching_destination (im, dst, sw_if_index, &ia); + if (!src) { vnm->api_errno = VNET_API_ERROR_NO_MATCHING_INTERFACE; return clib_error_return - (0, "no matching interface address for destination %U (interface %U)", - format_ip6_address, dst, - format_vnet_sw_if_index_name, vnm, sw_if_index); + (0, "no matching interface address for destination %U (interface %U)", + format_ip6_address, dst, + format_vnet_sw_if_index_name, vnm, sw_if_index); } - h = vlib_packet_template_get_packet (vm, &im->discover_neighbor_packet_template, &bi); + h = + vlib_packet_template_get_packet (vm, + &im->discover_neighbor_packet_template, + &bi); hi = vnet_get_sup_hw_interface (vnm, sw_if_index); @@ -1772,14 +1934,16 @@ ip6_probe_neighbor (vlib_main_t * vm, ip6_address_t * dst, u32 sw_if_index) h->ip.src_address = src[0]; h->neighbor.target_address = dst[0]; - clib_memcpy (h->link_layer_option.ethernet_address, hi->hw_address, vec_len (hi->hw_address)); + clib_memcpy (h->link_layer_option.ethernet_address, hi->hw_address, + vec_len (hi->hw_address)); h->neighbor.icmp.checksum = ip6_tcp_udp_icmp_compute_checksum (vm, 0, &h->ip, &bogus_length); - ASSERT(bogus_length == 0); + ASSERT (bogus_length == 0); b = vlib_get_buffer (vm, bi); - vnet_buffer (b)->sw_if_index[VLIB_RX] = vnet_buffer (b)->sw_if_index[VLIB_TX] = sw_if_index; + vnet_buffer (b)->sw_if_index[VLIB_RX] = + vnet_buffer (b)->sw_if_index[VLIB_TX] = sw_if_index; /* Add encapsulation string for software interface (e.g. ethernet header). */ adj = ip_get_adjacency (&im->lookup_main, ia->neighbor_probe_adj_index); @@ -1787,8 +1951,8 @@ ip6_probe_neighbor (vlib_main_t * vm, ip6_address_t * dst, u32 sw_if_index) vlib_buffer_advance (b, -adj->rewrite_header.data_bytes); { - vlib_frame_t * f = vlib_get_frame_to_node (vm, hi->output_node_index); - u32 * to_next = vlib_frame_vector_args (f); + vlib_frame_t *f = vlib_get_frame_to_node (vm, hi->output_node_index); + u32 *to_next = vlib_frame_vector_args (f); to_next[0] = bi; f->n_vectors = 1; vlib_put_frame_to_node (vm, hi->output_node_index, f); @@ -1797,7 +1961,8 @@ ip6_probe_neighbor (vlib_main_t * vm, ip6_address_t * dst, u32 sw_if_index) return /* no error */ 0; } -typedef enum { +typedef enum +{ IP6_REWRITE_NEXT_DROP, IP6_REWRITE_NEXT_ICMP_ERROR, } ip6_rewrite_next_t; @@ -1805,20 +1970,17 @@ typedef enum { always_inline uword ip6_rewrite_inline (vlib_main_t * vm, vlib_node_runtime_t * node, - vlib_frame_t * frame, - int rewrite_for_locally_received_packets, - int is_midchain) + vlib_frame_t * frame, int is_midchain) { - ip_lookup_main_t * lm = &ip6_main.lookup_main; - u32 * from = vlib_frame_vector_args (frame); - u32 n_left_from, n_left_to_next, * to_next, next_index; - vlib_node_runtime_t * error_node = vlib_node_get_runtime (vm, ip6_input_node.index); - vlib_rx_or_tx_t adj_rx_tx = rewrite_for_locally_received_packets ? VLIB_RX : VLIB_TX; - ip_config_main_t * cm = &lm->feature_config_mains[VNET_IP_TX_FEAT]; + ip_lookup_main_t *lm = &ip6_main.lookup_main; + u32 *from = vlib_frame_vector_args (frame); + u32 n_left_from, n_left_to_next, *to_next, next_index; + vlib_node_runtime_t *error_node = + vlib_node_get_runtime (vm, ip6_input_node.index); n_left_from = frame->n_vectors; next_index = node->cached_next_index; - u32 cpu_index = os_get_cpu_number(); + u32 cpu_index = os_get_cpu_number (); while (n_left_from > 0) { @@ -1826,16 +1988,16 @@ ip6_rewrite_inline (vlib_main_t * vm, while (n_left_from >= 4 && n_left_to_next >= 2) { - ip_adjacency_t * adj0, * adj1; - vlib_buffer_t * p0, * p1; - ip6_header_t * ip0, * ip1; + ip_adjacency_t *adj0, *adj1; + vlib_buffer_t *p0, *p1; + ip6_header_t *ip0, *ip1; u32 pi0, rw_len0, next0, error0, adj_index0; u32 pi1, rw_len1, next1, error1, adj_index1; - u32 tx_sw_if_index0, tx_sw_if_index1; + u32 tx_sw_if_index0, tx_sw_if_index1; /* Prefetch next iteration. */ { - vlib_buffer_t * p2, * p3; + vlib_buffer_t *p2, *p3; p2 = vlib_get_buffer (vm, from[2]); p3 = vlib_get_buffer (vm, from[3]); @@ -1861,140 +2023,141 @@ ip6_rewrite_inline (vlib_main_t * vm, p0 = vlib_get_buffer (vm, pi0); p1 = vlib_get_buffer (vm, pi1); - adj_index0 = vnet_buffer (p0)->ip.adj_index[adj_rx_tx]; - adj_index1 = vnet_buffer (p1)->ip.adj_index[adj_rx_tx]; + adj_index0 = vnet_buffer (p0)->ip.adj_index[VLIB_TX]; + adj_index1 = vnet_buffer (p1)->ip.adj_index[VLIB_TX]; - /* We should never rewrite a pkt using the MISS adjacency */ - ASSERT(adj_index0 && adj_index1); + /* We should never rewrite a pkt using the MISS adjacency */ + ASSERT (adj_index0 && adj_index1); ip0 = vlib_buffer_get_current (p0); ip1 = vlib_buffer_get_current (p1); error0 = error1 = IP6_ERROR_NONE; - next0 = next1 = IP6_REWRITE_NEXT_DROP; + next0 = next1 = IP6_REWRITE_NEXT_DROP; - if (! rewrite_for_locally_received_packets) + if (PREDICT_TRUE (!(p0->flags & VNET_BUFFER_LOCALLY_ORIGINATED))) { - i32 hop_limit0 = ip0->hop_limit, hop_limit1 = ip1->hop_limit; + i32 hop_limit0 = ip0->hop_limit; /* Input node should have reject packets with hop limit 0. */ ASSERT (ip0->hop_limit > 0); - ASSERT (ip1->hop_limit > 0); hop_limit0 -= 1; - hop_limit1 -= 1; ip0->hop_limit = hop_limit0; - ip1->hop_limit = hop_limit1; - /* - * If the hop count drops below 1 when forwarding, generate - * an ICMP response. - */ - if (PREDICT_FALSE(hop_limit0 <= 0)) - { - error0 = IP6_ERROR_TIME_EXPIRED; - next0 = IP6_REWRITE_NEXT_ICMP_ERROR; - vnet_buffer (p0)->sw_if_index[VLIB_TX] = (u32)~0; - icmp6_error_set_vnet_buffer(p0, ICMP6_time_exceeded, - ICMP6_time_exceeded_ttl_exceeded_in_transit, 0); - } - if (PREDICT_FALSE(hop_limit1 <= 0)) - { - error1 = IP6_ERROR_TIME_EXPIRED; - next1 = IP6_REWRITE_NEXT_ICMP_ERROR; - vnet_buffer (p1)->sw_if_index[VLIB_TX] = (u32)~0; - icmp6_error_set_vnet_buffer(p1, ICMP6_time_exceeded, - ICMP6_time_exceeded_ttl_exceeded_in_transit, 0); - } + /* + * If the hop count drops below 1 when forwarding, generate + * an ICMP response. + */ + if (PREDICT_FALSE (hop_limit0 <= 0)) + { + error0 = IP6_ERROR_TIME_EXPIRED; + next0 = IP6_REWRITE_NEXT_ICMP_ERROR; + vnet_buffer (p0)->sw_if_index[VLIB_TX] = (u32) ~ 0; + icmp6_error_set_vnet_buffer (p0, ICMP6_time_exceeded, + ICMP6_time_exceeded_ttl_exceeded_in_transit, + 0); + } + } + else + { + p0->flags &= ~VNET_BUFFER_LOCALLY_ORIGINATED; } + if (PREDICT_TRUE (!(p1->flags & VNET_BUFFER_LOCALLY_ORIGINATED))) + { + i32 hop_limit1 = ip1->hop_limit; + + /* Input node should have reject packets with hop limit 0. */ + ASSERT (ip1->hop_limit > 0); + + hop_limit1 -= 1; + ip1->hop_limit = hop_limit1; + + /* + * If the hop count drops below 1 when forwarding, generate + * an ICMP response. + */ + if (PREDICT_FALSE (hop_limit1 <= 0)) + { + error1 = IP6_ERROR_TIME_EXPIRED; + next1 = IP6_REWRITE_NEXT_ICMP_ERROR; + vnet_buffer (p1)->sw_if_index[VLIB_TX] = (u32) ~ 0; + icmp6_error_set_vnet_buffer (p1, ICMP6_time_exceeded, + ICMP6_time_exceeded_ttl_exceeded_in_transit, + 0); + } + } + else + { + p1->flags &= ~VNET_BUFFER_LOCALLY_ORIGINATED; + } adj0 = ip_get_adjacency (lm, adj_index0); adj1 = ip_get_adjacency (lm, adj_index1); rw_len0 = adj0[0].rewrite_header.data_bytes; rw_len1 = adj1[0].rewrite_header.data_bytes; - vnet_buffer(p0)->ip.save_rewrite_length = rw_len0; - vnet_buffer(p1)->ip.save_rewrite_length = rw_len1; + vnet_buffer (p0)->ip.save_rewrite_length = rw_len0; + vnet_buffer (p1)->ip.save_rewrite_length = rw_len1; vlib_increment_combined_counter (&adjacency_counters, - cpu_index, - adj_index0, + cpu_index, adj_index0, /* packet increment */ 0, /* byte increment */ rw_len0); vlib_increment_combined_counter (&adjacency_counters, - cpu_index, - adj_index1, + cpu_index, adj_index1, /* packet increment */ 0, /* byte increment */ rw_len1); /* Check MTU of outgoing interface. */ - error0 = (vlib_buffer_length_in_chain (vm, p0) > adj0[0].rewrite_header.max_l3_packet_bytes - ? IP6_ERROR_MTU_EXCEEDED - : error0); - error1 = (vlib_buffer_length_in_chain (vm, p1) > adj1[0].rewrite_header.max_l3_packet_bytes - ? IP6_ERROR_MTU_EXCEEDED - : error1); - - /* Don't adjust the buffer for hop count issue; icmp-error node - * wants to see the IP headerr */ - if (PREDICT_TRUE(error0 == IP6_ERROR_NONE)) - { - p0->current_data -= rw_len0; - p0->current_length += rw_len0; - - tx_sw_if_index0 = adj0[0].rewrite_header.sw_if_index; - vnet_buffer (p0)->sw_if_index[VLIB_TX] = - tx_sw_if_index0; - next0 = adj0[0].rewrite_header.next_index; - - if (PREDICT_FALSE - (clib_bitmap_get (lm->tx_sw_if_has_ip_output_features, - tx_sw_if_index0))) - { - p0->current_config_index = - vec_elt (cm->config_index_by_sw_if_index, - tx_sw_if_index0); - vnet_get_config_data (&cm->config_main, - &p0->current_config_index, - &next0, - /* # bytes of config data */ 0); - } - } - if (PREDICT_TRUE(error1 == IP6_ERROR_NONE)) - { - p1->current_data -= rw_len1; - p1->current_length += rw_len1; - - tx_sw_if_index1 = adj1[0].rewrite_header.sw_if_index; - vnet_buffer (p1)->sw_if_index[VLIB_TX] = - tx_sw_if_index1; - next1 = adj1[0].rewrite_header.next_index; - - if (PREDICT_FALSE - (clib_bitmap_get (lm->tx_sw_if_has_ip_output_features, - tx_sw_if_index1))) - { - p1->current_config_index = - vec_elt (cm->config_index_by_sw_if_index, - tx_sw_if_index1); - vnet_get_config_data (&cm->config_main, - &p1->current_config_index, - &next1, - /* # bytes of config data */ 0); - } - } + error0 = + (vlib_buffer_length_in_chain (vm, p0) > + adj0[0]. + rewrite_header.max_l3_packet_bytes ? IP6_ERROR_MTU_EXCEEDED : + error0); + error1 = + (vlib_buffer_length_in_chain (vm, p1) > + adj1[0]. + rewrite_header.max_l3_packet_bytes ? IP6_ERROR_MTU_EXCEEDED : + error1); + + /* Don't adjust the buffer for hop count issue; icmp-error node + * wants to see the IP headerr */ + if (PREDICT_TRUE (error0 == IP6_ERROR_NONE)) + { + p0->current_data -= rw_len0; + p0->current_length += rw_len0; + + tx_sw_if_index0 = adj0[0].rewrite_header.sw_if_index; + vnet_buffer (p0)->sw_if_index[VLIB_TX] = tx_sw_if_index0; + next0 = adj0[0].rewrite_header.next_index; + + vnet_feature_arc_start (lm->output_feature_arc_index, + tx_sw_if_index0, &next0, p0); + } + if (PREDICT_TRUE (error1 == IP6_ERROR_NONE)) + { + p1->current_data -= rw_len1; + p1->current_length += rw_len1; + + tx_sw_if_index1 = adj1[0].rewrite_header.sw_if_index; + vnet_buffer (p1)->sw_if_index[VLIB_TX] = tx_sw_if_index1; + next1 = adj1[0].rewrite_header.next_index; + + vnet_feature_arc_start (lm->output_feature_arc_index, + tx_sw_if_index1, &next1, p1); + } /* Guess we are only writing on simple Ethernet header. */ vnet_rewrite_two_headers (adj0[0], adj1[0], - ip0, ip1, - sizeof (ethernet_header_t)); + ip0, ip1, sizeof (ethernet_header_t)); if (is_midchain) - { - adj0->sub_type.midchain.fixup_func(vm, adj0, p0); - adj1->sub_type.midchain.fixup_func(vm, adj1, p1); - } + { + adj0->sub_type.midchain.fixup_func (vm, adj0, p0); + adj1->sub_type.midchain.fixup_func (vm, adj1, p1); + } vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next, n_left_to_next, @@ -2003,31 +2166,31 @@ ip6_rewrite_inline (vlib_main_t * vm, while (n_left_from > 0 && n_left_to_next > 0) { - ip_adjacency_t * adj0; - vlib_buffer_t * p0; - ip6_header_t * ip0; + ip_adjacency_t *adj0; + vlib_buffer_t *p0; + ip6_header_t *ip0; u32 pi0, rw_len0; u32 adj_index0, next0, error0; - u32 tx_sw_if_index0; + u32 tx_sw_if_index0; pi0 = to_next[0] = from[0]; p0 = vlib_get_buffer (vm, pi0); - adj_index0 = vnet_buffer (p0)->ip.adj_index[adj_rx_tx]; + adj_index0 = vnet_buffer (p0)->ip.adj_index[VLIB_TX]; - /* We should never rewrite a pkt using the MISS adjacency */ - ASSERT(adj_index0); + /* We should never rewrite a pkt using the MISS adjacency */ + ASSERT (adj_index0); adj0 = ip_get_adjacency (lm, adj_index0); ip0 = vlib_buffer_get_current (p0); error0 = IP6_ERROR_NONE; - next0 = IP6_REWRITE_NEXT_DROP; + next0 = IP6_REWRITE_NEXT_DROP; /* Check hop limit */ - if (! rewrite_for_locally_received_packets) + if (PREDICT_TRUE (!(p0->flags & VNET_BUFFER_LOCALLY_ORIGINATED))) { i32 hop_limit0 = ip0->hop_limit; @@ -2037,18 +2200,23 @@ ip6_rewrite_inline (vlib_main_t * vm, ip0->hop_limit = hop_limit0; - if (PREDICT_FALSE(hop_limit0 <= 0)) - { - /* - * If the hop count drops below 1 when forwarding, generate - * an ICMP response. - */ - error0 = IP6_ERROR_TIME_EXPIRED; - next0 = IP6_REWRITE_NEXT_ICMP_ERROR; - vnet_buffer (p0)->sw_if_index[VLIB_TX] = (u32)~0; - icmp6_error_set_vnet_buffer(p0, ICMP6_time_exceeded, - ICMP6_time_exceeded_ttl_exceeded_in_transit, 0); - } + if (PREDICT_FALSE (hop_limit0 <= 0)) + { + /* + * If the hop count drops below 1 when forwarding, generate + * an ICMP response. + */ + error0 = IP6_ERROR_TIME_EXPIRED; + next0 = IP6_REWRITE_NEXT_ICMP_ERROR; + vnet_buffer (p0)->sw_if_index[VLIB_TX] = (u32) ~ 0; + icmp6_error_set_vnet_buffer (p0, ICMP6_time_exceeded, + ICMP6_time_exceeded_ttl_exceeded_in_transit, + 0); + } + } + else + { + p0->flags &= ~VNET_BUFFER_LOCALLY_ORIGINATED; } /* Guess we are only writing on simple Ethernet header. */ @@ -2056,49 +2224,40 @@ ip6_rewrite_inline (vlib_main_t * vm, /* Update packet buffer attributes/set output interface. */ rw_len0 = adj0[0].rewrite_header.data_bytes; - vnet_buffer(p0)->ip.save_rewrite_length = rw_len0; + vnet_buffer (p0)->ip.save_rewrite_length = rw_len0; vlib_increment_combined_counter (&adjacency_counters, - cpu_index, - adj_index0, + cpu_index, adj_index0, /* packet increment */ 0, /* byte increment */ rw_len0); /* Check MTU of outgoing interface. */ - error0 = (vlib_buffer_length_in_chain (vm, p0) > adj0[0].rewrite_header.max_l3_packet_bytes - ? IP6_ERROR_MTU_EXCEEDED - : error0); - - /* Don't adjust the buffer for hop count issue; icmp-error node - * wants to see the IP headerr */ - if (PREDICT_TRUE(error0 == IP6_ERROR_NONE)) - { + error0 = + (vlib_buffer_length_in_chain (vm, p0) > + adj0[0]. + rewrite_header.max_l3_packet_bytes ? IP6_ERROR_MTU_EXCEEDED : + error0); + + /* Don't adjust the buffer for hop count issue; icmp-error node + * wants to see the IP headerr */ + if (PREDICT_TRUE (error0 == IP6_ERROR_NONE)) + { p0->current_data -= rw_len0; p0->current_length += rw_len0; - tx_sw_if_index0 = adj0[0].rewrite_header.sw_if_index; - - vnet_buffer (p0)->sw_if_index[VLIB_TX] = tx_sw_if_index0; - next0 = adj0[0].rewrite_header.next_index; - - if (PREDICT_FALSE - (clib_bitmap_get (lm->tx_sw_if_has_ip_output_features, - tx_sw_if_index0))) - { - p0->current_config_index = - vec_elt (cm->config_index_by_sw_if_index, - tx_sw_if_index0); - vnet_get_config_data (&cm->config_main, - &p0->current_config_index, - &next0, - /* # bytes of config data */ 0); - } - } + tx_sw_if_index0 = adj0[0].rewrite_header.sw_if_index; + + vnet_buffer (p0)->sw_if_index[VLIB_TX] = tx_sw_if_index0; + next0 = adj0[0].rewrite_header.next_index; + + vnet_feature_arc_start (lm->output_feature_arc_index, + tx_sw_if_index0, &next0, p0); + } if (is_midchain) - { - adj0->sub_type.midchain.fixup_func(vm, adj0, p0); - } + { + adj0->sub_type.midchain.fixup_func (vm, adj0, p0); + } p0->error = error_node->errors[error0]; @@ -2117,86 +2276,57 @@ ip6_rewrite_inline (vlib_main_t * vm, /* Need to do trace after rewrites to pick up new packet data. */ if (node->flags & VLIB_NODE_FLAG_TRACE) - ip6_forward_next_trace (vm, node, frame, adj_rx_tx); + ip6_forward_next_trace (vm, node, frame, VLIB_TX); return frame->n_vectors; } static uword -ip6_rewrite_transit (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - return ip6_rewrite_inline (vm, node, frame, - /* rewrite_for_locally_received_packets */ 0, - /* midchain */ 0); -} - -static uword -ip6_rewrite_local (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) +ip6_rewrite (vlib_main_t * vm, + vlib_node_runtime_t * node, vlib_frame_t * frame) { return ip6_rewrite_inline (vm, node, frame, - /* rewrite_for_locally_received_packets */ 1, /* midchain */ 0); } static uword ip6_midchain (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) + vlib_node_runtime_t * node, vlib_frame_t * frame) { return ip6_rewrite_inline (vm, node, frame, - /* rewrite_for_locally_received_packets */ 0, /* midchain */ 1); } -VLIB_REGISTER_NODE (ip6_midchain_node) = { +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE (ip6_midchain_node) = +{ .function = ip6_midchain, .name = "ip6-midchain", .vector_size = sizeof (u32), - .format_trace = format_ip6_forward_next_trace, - .sibling_of = "ip6-rewrite", + }; +/* *INDENT-ON* */ - .next_nodes = { - [IP6_REWRITE_NEXT_DROP] = "error-drop", - }, -}; - -VLIB_NODE_FUNCTION_MULTIARCH (ip6_midchain_node, ip6_midchain) +VLIB_NODE_FUNCTION_MULTIARCH (ip6_midchain_node, ip6_midchain); -VLIB_REGISTER_NODE (ip6_rewrite_node) = { - .function = ip6_rewrite_transit, +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE (ip6_rewrite_node) = +{ + .function = ip6_rewrite, .name = "ip6-rewrite", .vector_size = sizeof (u32), - .format_trace = format_ip6_rewrite_trace, - .n_next_nodes = 2, - .next_nodes = { + .next_nodes = + { [IP6_REWRITE_NEXT_DROP] = "error-drop", [IP6_REWRITE_NEXT_ICMP_ERROR] = "ip6-icmp-error", }, }; +/* *INDENT-ON* */ -VLIB_NODE_FUNCTION_MULTIARCH (ip6_rewrite_node, ip6_rewrite_transit); - -VLIB_REGISTER_NODE (ip6_rewrite_local_node) = { - .function = ip6_rewrite_local, - .name = "ip6-rewrite-local", - .vector_size = sizeof (u32), - - .sibling_of = "ip6-rewrite", - - .format_trace = format_ip6_rewrite_trace, - - .n_next_nodes = 0, -}; - -VLIB_NODE_FUNCTION_MULTIARCH (ip6_rewrite_local_node, ip6_rewrite_local); +VLIB_NODE_FUNCTION_MULTIARCH (ip6_rewrite_node, ip6_rewrite); /* * Hop-by-Hop handling @@ -2209,18 +2339,20 @@ _(PROCESSED, "pkts with ip6 hop-by-hop options") \ _(FORMAT, "incorrectly formatted hop-by-hop options") \ _(UNKNOWN_OPTION, "unknown ip6 hop-by-hop options") -typedef enum { +typedef enum +{ #define _(sym,str) IP6_HOP_BY_HOP_ERROR_##sym, foreach_ip6_hop_by_hop_error #undef _ - IP6_HOP_BY_HOP_N_ERROR, + IP6_HOP_BY_HOP_N_ERROR, } ip6_hop_by_hop_error_t; /* * Primary h-b-h handler trace support * We work pretty hard on the problem for obvious reasons */ -typedef struct { +typedef struct +{ u32 next_index; u32 trace_len; u8 option_data[256]; @@ -2228,7 +2360,7 @@ typedef struct { vlib_node_registration_t ip6_hop_by_hop_node; -static char * ip6_hop_by_hop_error_strings[] = { +static char *ip6_hop_by_hop_error_strings[] = { #define _(sym,string) string, foreach_ip6_hop_by_hop_error #undef _ @@ -2239,48 +2371,56 @@ format_ip6_hop_by_hop_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 *); - ip6_hop_by_hop_trace_t * t = va_arg (*args, ip6_hop_by_hop_trace_t *); + ip6_hop_by_hop_trace_t *t = va_arg (*args, ip6_hop_by_hop_trace_t *); ip6_hop_by_hop_header_t *hbh0; ip6_hop_by_hop_option_t *opt0, *limit0; ip6_hop_by_hop_main_t *hm = &ip6_hop_by_hop_main; u8 type0; - hbh0 = (ip6_hop_by_hop_header_t *)t->option_data; + hbh0 = (ip6_hop_by_hop_header_t *) t->option_data; s = format (s, "IP6_HOP_BY_HOP: next index %d len %d traced %d", - t->next_index, (hbh0->length+1)<<3, t->trace_len); + t->next_index, (hbh0->length + 1) << 3, t->trace_len); - opt0 = (ip6_hop_by_hop_option_t *) (hbh0+1); - limit0 = (ip6_hop_by_hop_option_t *) ((u8 *)hbh0) + t->trace_len; + opt0 = (ip6_hop_by_hop_option_t *) (hbh0 + 1); + limit0 = (ip6_hop_by_hop_option_t *) ((u8 *) hbh0) + t->trace_len; - while (opt0 < limit0) { - type0 = opt0->type; - switch (type0) { - case 0: /* Pad, just stop */ - opt0 = (ip6_hop_by_hop_option_t *) ((u8 *)opt0) + 1; - break; + while (opt0 < limit0) + { + type0 = opt0->type; + switch (type0) + { + case 0: /* Pad, just stop */ + opt0 = (ip6_hop_by_hop_option_t *) ((u8 *) opt0) + 1; + break; - default: - if (hm->trace[type0]) { - s = (*hm->trace[type0])(s, opt0); - } else { - s = format (s, "\n unrecognized option %d length %d", type0, opt0->length); - } - opt0 = (ip6_hop_by_hop_option_t *) (((u8 *)opt0) + opt0->length + sizeof (ip6_hop_by_hop_option_t)); - break; + default: + if (hm->trace[type0]) + { + s = (*hm->trace[type0]) (s, opt0); + } + else + { + s = + format (s, "\n unrecognized option %d length %d", type0, + opt0->length); + } + opt0 = + (ip6_hop_by_hop_option_t *) (((u8 *) opt0) + opt0->length + + sizeof (ip6_hop_by_hop_option_t)); + break; + } } - } return s; } -always_inline u8 ip6_scan_hbh_options ( - vlib_buffer_t * b0, - ip6_header_t *ip0, - ip6_hop_by_hop_header_t *hbh0, - ip6_hop_by_hop_option_t *opt0, - ip6_hop_by_hop_option_t *limit0, - u32 *next0) +always_inline u8 +ip6_scan_hbh_options (vlib_buffer_t * b0, + ip6_header_t * ip0, + ip6_hop_by_hop_header_t * hbh0, + ip6_hop_by_hop_option_t * opt0, + ip6_hop_by_hop_option_t * limit0, u32 * next0) { ip6_hop_by_hop_main_t *hm = &ip6_hop_by_hop_main; u8 type0; @@ -2291,19 +2431,19 @@ always_inline u8 ip6_scan_hbh_options ( type0 = opt0->type; switch (type0) { - case 0: /* Pad1 */ - opt0 = (ip6_hop_by_hop_option_t *) ((u8 *)opt0) + 1; + case 0: /* Pad1 */ + opt0 = (ip6_hop_by_hop_option_t *) ((u8 *) opt0) + 1; continue; - case 1: /* PadN */ + case 1: /* PadN */ break; default: if (hm->options[type0]) { - if ((*hm->options[type0])(b0, ip0, opt0) < 0) - { + if ((*hm->options[type0]) (b0, ip0, opt0) < 0) + { error0 = IP6_HOP_BY_HOP_ERROR_FORMAT; - return(error0); - } + return (error0); + } } else { @@ -2319,29 +2459,34 @@ always_inline u8 ip6_scan_hbh_options ( case HBH_OPTION_TYPE_DISCARD_UNKNOWN_ICMP: error0 = IP6_HOP_BY_HOP_ERROR_UNKNOWN_OPTION; *next0 = IP_LOOKUP_NEXT_ICMP_ERROR; - icmp6_error_set_vnet_buffer(b0, ICMP6_parameter_problem, - ICMP6_parameter_problem_unrecognized_option, (u8 *)opt0 - (u8 *)ip0); + icmp6_error_set_vnet_buffer (b0, ICMP6_parameter_problem, + ICMP6_parameter_problem_unrecognized_option, + (u8 *) opt0 - (u8 *) ip0); break; case HBH_OPTION_TYPE_DISCARD_UNKNOWN_ICMP_NOT_MCAST: error0 = IP6_HOP_BY_HOP_ERROR_UNKNOWN_OPTION; - if (!ip6_address_is_multicast(&ip0->dst_address)) + if (!ip6_address_is_multicast (&ip0->dst_address)) { - *next0 = IP_LOOKUP_NEXT_ICMP_ERROR; - icmp6_error_set_vnet_buffer(b0, ICMP6_parameter_problem, - ICMP6_parameter_problem_unrecognized_option, (u8 *)opt0 - (u8 *)ip0); + *next0 = IP_LOOKUP_NEXT_ICMP_ERROR; + icmp6_error_set_vnet_buffer (b0, + ICMP6_parameter_problem, + ICMP6_parameter_problem_unrecognized_option, + (u8 *) opt0 - (u8 *) ip0); } else { - *next0 = IP_LOOKUP_NEXT_DROP; + *next0 = IP_LOOKUP_NEXT_DROP; } break; } - return(error0); + return (error0); } } - opt0 = (ip6_hop_by_hop_option_t *) (((u8 *)opt0) + opt0->length + sizeof (ip6_hop_by_hop_option_t)); + opt0 = + (ip6_hop_by_hop_option_t *) (((u8 *) opt0) + opt0->length + + sizeof (ip6_hop_by_hop_option_t)); } - return(error0); + return (error0); } /* @@ -2349,240 +2494,288 @@ always_inline u8 ip6_scan_hbh_options ( */ static uword ip6_hop_by_hop (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) + vlib_node_runtime_t * node, vlib_frame_t * frame) { - vlib_node_runtime_t *error_node = vlib_node_get_runtime(vm, ip6_hop_by_hop_node.index); + vlib_node_runtime_t *error_node = + vlib_node_get_runtime (vm, ip6_hop_by_hop_node.index); ip6_hop_by_hop_main_t *hm = &ip6_hop_by_hop_main; u32 n_left_from, *from, *to_next; ip_lookup_next_t next_index; - ip6_main_t * im = &ip6_main; + ip6_main_t *im = &ip6_main; ip_lookup_main_t *lm = &im->lookup_main; 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; + while (n_left_from > 0) + { + u32 n_left_to_next; - vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); + vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); - while (n_left_from >= 4 && n_left_to_next >= 2) { - u32 bi0, bi1; - vlib_buffer_t * b0, *b1; - u32 next0, next1; - ip6_header_t * ip0, *ip1; - ip6_hop_by_hop_header_t *hbh0, *hbh1; - ip6_hop_by_hop_option_t *opt0, *limit0, *opt1, *limit1; - u8 error0 = 0, error1 = 0; + while (n_left_from >= 4 && n_left_to_next >= 2) + { + u32 bi0, bi1; + vlib_buffer_t *b0, *b1; + u32 next0, next1; + ip6_header_t *ip0, *ip1; + ip6_hop_by_hop_header_t *hbh0, *hbh1; + ip6_hop_by_hop_option_t *opt0, *limit0, *opt1, *limit1; + u8 error0 = 0, error1 = 0; - /* Prefetch next iteration. */ - { - vlib_buffer_t * p2, * p3; + /* Prefetch next iteration. */ + { + vlib_buffer_t *p2, *p3; - p2 = vlib_get_buffer (vm, from[2]); - p3 = vlib_get_buffer (vm, from[3]); + p2 = vlib_get_buffer (vm, from[2]); + p3 = vlib_get_buffer (vm, from[3]); - vlib_prefetch_buffer_header (p2, LOAD); - vlib_prefetch_buffer_header (p3, LOAD); + vlib_prefetch_buffer_header (p2, LOAD); + vlib_prefetch_buffer_header (p3, LOAD); - CLIB_PREFETCH (p2->data, 2*CLIB_CACHE_LINE_BYTES, LOAD); - CLIB_PREFETCH (p3->data, 2*CLIB_CACHE_LINE_BYTES, LOAD); - } + CLIB_PREFETCH (p2->data, 2 * CLIB_CACHE_LINE_BYTES, LOAD); + CLIB_PREFETCH (p3->data, 2 * CLIB_CACHE_LINE_BYTES, LOAD); + } - /* Speculatively enqueue b0, b1 to the current next frame */ - to_next[0] = bi0 = from[0]; - to_next[1] = bi1 = from[1]; - from += 2; - to_next += 2; - n_left_from -= 2; - n_left_to_next -= 2; + /* Speculatively enqueue b0, b1 to the current next frame */ + to_next[0] = bi0 = from[0]; + to_next[1] = bi1 = from[1]; + from += 2; + to_next += 2; + n_left_from -= 2; + n_left_to_next -= 2; - b0 = vlib_get_buffer (vm, bi0); - b1 = vlib_get_buffer (vm, bi1); - u32 adj_index0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX]; - ip_adjacency_t *adj0 = ip_get_adjacency(lm, adj_index0); - u32 adj_index1 = vnet_buffer(b1)->ip.adj_index[VLIB_TX]; - ip_adjacency_t *adj1 = ip_get_adjacency(lm, adj_index1); - - /* Default use the next_index from the adjacency. A HBH option rarely redirects to a different node */ - next0 = adj0->lookup_next_index; - next1 = adj1->lookup_next_index; - - ip0 = vlib_buffer_get_current (b0); - ip1 = vlib_buffer_get_current (b1); - hbh0 = (ip6_hop_by_hop_header_t *)(ip0+1); - hbh1 = (ip6_hop_by_hop_header_t *)(ip1+1); - opt0 = (ip6_hop_by_hop_option_t *)(hbh0+1); - opt1 = (ip6_hop_by_hop_option_t *)(hbh1+1); - limit0 = (ip6_hop_by_hop_option_t *)((u8 *)hbh0 + ((hbh0->length + 1) << 3)); - limit1 = (ip6_hop_by_hop_option_t *)((u8 *)hbh1 + ((hbh1->length + 1) << 3)); - - /* - * Basic validity checks - */ - if ((hbh0->length + 1) << 3 > clib_net_to_host_u16(ip0->payload_length)) { - error0 = IP6_HOP_BY_HOP_ERROR_FORMAT; - next0 = IP_LOOKUP_NEXT_DROP; - goto outdual; - } - /* Scan the set of h-b-h options, process ones that we understand */ - error0 = ip6_scan_hbh_options(b0, ip0, hbh0, opt0, limit0, &next0); - - if ((hbh1->length + 1) << 3 > clib_net_to_host_u16(ip1->payload_length)) { - error1 = IP6_HOP_BY_HOP_ERROR_FORMAT; - next1 = IP_LOOKUP_NEXT_DROP; - goto outdual; - } - /* Scan the set of h-b-h options, process ones that we understand */ - error1 = ip6_scan_hbh_options(b1,ip1,hbh1,opt1,limit1, &next1); - - outdual: - /* Has the classifier flagged this buffer for special treatment? */ - if ((error0 == 0) && (vnet_buffer(b0)->l2_classify.opaque_index == OI_DECAP)) - next0 = hm->next_override; - - /* Has the classifier flagged this buffer for special treatment? */ - if ((error1 == 0) && (vnet_buffer(b1)->l2_classify.opaque_index == OI_DECAP)) - next1 = hm->next_override; - - if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE))) - { - if (b0->flags & VLIB_BUFFER_IS_TRACED) { - ip6_hop_by_hop_trace_t *t = vlib_add_trace(vm, node, b0, sizeof (*t)); - u32 trace_len = (hbh0->length + 1) << 3; - t->next_index = next0; - /* Capture the h-b-h option verbatim */ - trace_len = trace_len < ARRAY_LEN(t->option_data) ? trace_len : ARRAY_LEN(t->option_data); - t->trace_len = trace_len; - clib_memcpy(t->option_data, hbh0, trace_len); - } - if (b1->flags & VLIB_BUFFER_IS_TRACED) { - ip6_hop_by_hop_trace_t *t = vlib_add_trace(vm, node, b1, sizeof (*t)); - u32 trace_len = (hbh1->length + 1) << 3; - t->next_index = next1; - /* Capture the h-b-h option verbatim */ - trace_len = trace_len < ARRAY_LEN(t->option_data) ? trace_len : ARRAY_LEN(t->option_data); - t->trace_len = trace_len; - clib_memcpy(t->option_data, hbh1, trace_len); - } + b0 = vlib_get_buffer (vm, bi0); + b1 = vlib_get_buffer (vm, bi1); + + /* Default use the next_index from the adjacency. A HBH option rarely redirects to a different node */ + u32 adj_index0 = vnet_buffer (b0)->ip.adj_index[VLIB_TX]; + ip_adjacency_t *adj0 = ip_get_adjacency (lm, adj_index0); + u32 adj_index1 = vnet_buffer (b1)->ip.adj_index[VLIB_TX]; + ip_adjacency_t *adj1 = ip_get_adjacency (lm, adj_index1); + + /* Default use the next_index from the adjacency. A HBH option rarely redirects to a different node */ + next0 = adj0->lookup_next_index; + next1 = adj1->lookup_next_index; + + ip0 = vlib_buffer_get_current (b0); + ip1 = vlib_buffer_get_current (b1); + hbh0 = (ip6_hop_by_hop_header_t *) (ip0 + 1); + hbh1 = (ip6_hop_by_hop_header_t *) (ip1 + 1); + opt0 = (ip6_hop_by_hop_option_t *) (hbh0 + 1); + opt1 = (ip6_hop_by_hop_option_t *) (hbh1 + 1); + limit0 = + (ip6_hop_by_hop_option_t *) ((u8 *) hbh0 + + ((hbh0->length + 1) << 3)); + limit1 = + (ip6_hop_by_hop_option_t *) ((u8 *) hbh1 + + ((hbh1->length + 1) << 3)); + + /* + * Basic validity checks + */ + if ((hbh0->length + 1) << 3 > + clib_net_to_host_u16 (ip0->payload_length)) + { + error0 = IP6_HOP_BY_HOP_ERROR_FORMAT; + next0 = IP_LOOKUP_NEXT_DROP; + goto outdual; + } + /* Scan the set of h-b-h options, process ones that we understand */ + error0 = ip6_scan_hbh_options (b0, ip0, hbh0, opt0, limit0, &next0); + + if ((hbh1->length + 1) << 3 > + clib_net_to_host_u16 (ip1->payload_length)) + { + error1 = IP6_HOP_BY_HOP_ERROR_FORMAT; + next1 = IP_LOOKUP_NEXT_DROP; + goto outdual; + } + /* Scan the set of h-b-h options, process ones that we understand */ + error1 = ip6_scan_hbh_options (b1, ip1, hbh1, opt1, limit1, &next1); + + outdual: + /* Has the classifier flagged this buffer for special treatment? */ + if (PREDICT_FALSE + ((error0 == 0) + && (vnet_buffer (b0)->l2_classify.opaque_index & OI_DECAP))) + next0 = hm->next_override; + + /* Has the classifier flagged this buffer for special treatment? */ + if (PREDICT_FALSE + ((error1 == 0) + && (vnet_buffer (b1)->l2_classify.opaque_index & OI_DECAP))) + next1 = hm->next_override; + + if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE))) + { + if (b0->flags & VLIB_BUFFER_IS_TRACED) + { + ip6_hop_by_hop_trace_t *t = + vlib_add_trace (vm, node, b0, sizeof (*t)); + u32 trace_len = (hbh0->length + 1) << 3; + t->next_index = next0; + /* Capture the h-b-h option verbatim */ + trace_len = + trace_len < + ARRAY_LEN (t->option_data) ? trace_len : + ARRAY_LEN (t->option_data); + t->trace_len = trace_len; + clib_memcpy (t->option_data, hbh0, trace_len); + } + if (b1->flags & VLIB_BUFFER_IS_TRACED) + { + ip6_hop_by_hop_trace_t *t = + vlib_add_trace (vm, node, b1, sizeof (*t)); + u32 trace_len = (hbh1->length + 1) << 3; + t->next_index = next1; + /* Capture the h-b-h option verbatim */ + trace_len = + trace_len < + ARRAY_LEN (t->option_data) ? trace_len : + ARRAY_LEN (t->option_data); + t->trace_len = trace_len; + clib_memcpy (t->option_data, hbh1, trace_len); + } + + } + + b0->error = error_node->errors[error0]; + b1->error = error_node->errors[error1]; + /* verify speculative enqueue, maybe switch current next frame */ + vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next, + n_left_to_next, bi0, bi1, next0, + next1); } - b0->error = error_node->errors[error0]; - b1->error = error_node->errors[error1]; + while (n_left_from > 0 && n_left_to_next > 0) + { + u32 bi0; + vlib_buffer_t *b0; + u32 next0; + ip6_header_t *ip0; + ip6_hop_by_hop_header_t *hbh0; + ip6_hop_by_hop_option_t *opt0, *limit0; + u8 error0 = 0; + + /* Speculatively enqueue b0 to the current next frame */ + 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); + /* + * Default use the next_index from the adjacency. + * A HBH option rarely redirects to a different node + */ + u32 adj_index0 = vnet_buffer (b0)->ip.adj_index[VLIB_TX]; + ip_adjacency_t *adj0 = ip_get_adjacency (lm, adj_index0); + next0 = adj0->lookup_next_index; + + ip0 = vlib_buffer_get_current (b0); + hbh0 = (ip6_hop_by_hop_header_t *) (ip0 + 1); + opt0 = (ip6_hop_by_hop_option_t *) (hbh0 + 1); + limit0 = + (ip6_hop_by_hop_option_t *) ((u8 *) hbh0 + + ((hbh0->length + 1) << 3)); + + /* + * Basic validity checks + */ + if ((hbh0->length + 1) << 3 > + clib_net_to_host_u16 (ip0->payload_length)) + { + error0 = IP6_HOP_BY_HOP_ERROR_FORMAT; + next0 = IP_LOOKUP_NEXT_DROP; + goto out0; + } - /* verify speculative enqueue, maybe switch current next frame */ - vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next, n_left_to_next, bi0, - bi1,next0, next1); - } + /* Scan the set of h-b-h options, process ones that we understand */ + error0 = ip6_scan_hbh_options (b0, ip0, hbh0, opt0, limit0, &next0); - while (n_left_from > 0 && n_left_to_next > 0) { - u32 bi0; - vlib_buffer_t * b0; - u32 next0; - ip6_header_t * ip0; - ip6_hop_by_hop_header_t *hbh0; - ip6_hop_by_hop_option_t *opt0, *limit0; - u8 error0 = 0; - - /* Speculatively enqueue b0 to the current next frame */ - bi0 = from[0]; - to_next[0] = bi0; - from += 1; - to_next += 1; - n_left_from -= 1; - n_left_to_next -= 1; + out0: + /* Has the classifier flagged this buffer for special treatment? */ + if (PREDICT_FALSE + ((error0 == 0) + && (vnet_buffer (b0)->l2_classify.opaque_index & OI_DECAP))) + next0 = hm->next_override; - b0 = vlib_get_buffer (vm, bi0); - u32 adj_index0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX]; - ip_adjacency_t *adj0 = ip_get_adjacency(lm, adj_index0); - /* Default use the next_index from the adjacency. A HBH option rarely redirects to a different node */ - next0 = adj0->lookup_next_index; - - ip0 = vlib_buffer_get_current (b0); - hbh0 = (ip6_hop_by_hop_header_t *)(ip0+1); - opt0 = (ip6_hop_by_hop_option_t *)(hbh0+1); - limit0 = (ip6_hop_by_hop_option_t *)((u8 *)hbh0 + ((hbh0->length + 1) << 3)); - - /* - * Basic validity checks - */ - if ((hbh0->length + 1) << 3 > clib_net_to_host_u16(ip0->payload_length)) { - error0 = IP6_HOP_BY_HOP_ERROR_FORMAT; - next0 = IP_LOOKUP_NEXT_DROP; - goto out0; - } - - /* Scan the set of h-b-h options, process ones that we understand */ - error0 = ip6_scan_hbh_options(b0, ip0, hbh0, opt0, limit0, &next0); - - out0: - /* Has the classifier flagged this buffer for special treatment? */ - if ((error0 == 0) && (vnet_buffer(b0)->l2_classify.opaque_index == OI_DECAP)) - next0 = hm->next_override; - - if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED)) { - ip6_hop_by_hop_trace_t *t = vlib_add_trace(vm, node, b0, sizeof (*t)); - u32 trace_len = (hbh0->length + 1) << 3; - t->next_index = next0; - /* Capture the h-b-h option verbatim */ - trace_len = trace_len < ARRAY_LEN(t->option_data) ? trace_len : ARRAY_LEN(t->option_data); - t->trace_len = trace_len; - clib_memcpy(t->option_data, hbh0, trace_len); - } - - b0->error = error_node->errors[error0]; - - /* verify speculative enqueue, maybe switch current next frame */ - vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, n_left_to_next, bi0, next0); + if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) + { + ip6_hop_by_hop_trace_t *t = + vlib_add_trace (vm, node, b0, sizeof (*t)); + u32 trace_len = (hbh0->length + 1) << 3; + t->next_index = next0; + /* Capture the h-b-h option verbatim */ + trace_len = + trace_len < + ARRAY_LEN (t->option_data) ? trace_len : + ARRAY_LEN (t->option_data); + t->trace_len = trace_len; + clib_memcpy (t->option_data, hbh0, trace_len); + } + + b0->error = error_node->errors[error0]; + + /* verify speculative enqueue, maybe switch current next frame */ + 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_put_next_frame (vm, node, next_index, n_left_to_next); - } return frame->n_vectors; } -VLIB_REGISTER_NODE (ip6_hop_by_hop_node) = { +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE (ip6_hop_by_hop_node) = +{ .function = ip6_hop_by_hop, .name = "ip6-hop-by-hop", .sibling_of = "ip6-lookup", .vector_size = sizeof (u32), .format_trace = format_ip6_hop_by_hop_trace, .type = VLIB_NODE_TYPE_INTERNAL, - .n_errors = ARRAY_LEN(ip6_hop_by_hop_error_strings), + .n_errors = ARRAY_LEN (ip6_hop_by_hop_error_strings), .error_strings = ip6_hop_by_hop_error_strings, .n_next_nodes = 0, }; +/* *INDENT-ON* */ VLIB_NODE_FUNCTION_MULTIARCH (ip6_hop_by_hop_node, ip6_hop_by_hop); static clib_error_t * ip6_hop_by_hop_init (vlib_main_t * vm) { - ip6_hop_by_hop_main_t * hm = &ip6_hop_by_hop_main; - memset(hm->options, 0, sizeof(hm->options)); - memset(hm->trace, 0, sizeof(hm->trace)); + ip6_hop_by_hop_main_t *hm = &ip6_hop_by_hop_main; + memset (hm->options, 0, sizeof (hm->options)); + memset (hm->trace, 0, sizeof (hm->trace)); hm->next_override = IP6_LOOKUP_NEXT_POP_HOP_BY_HOP; return (0); } VLIB_INIT_FUNCTION (ip6_hop_by_hop_init); -void ip6_hbh_set_next_override (uword next) +void +ip6_hbh_set_next_override (uword next) { - ip6_hop_by_hop_main_t * hm = &ip6_hop_by_hop_main; + ip6_hop_by_hop_main_t *hm = &ip6_hop_by_hop_main; hm->next_override = next; } int ip6_hbh_register_option (u8 option, - int options(vlib_buffer_t *b, ip6_header_t *ip, ip6_hop_by_hop_option_t *opt), - u8 *trace(u8 *s, ip6_hop_by_hop_option_t *opt)) + int options (vlib_buffer_t * b, ip6_header_t * ip, + ip6_hop_by_hop_option_t * opt), + u8 * trace (u8 * s, ip6_hop_by_hop_option_t * opt)) { - ip6_main_t * im = &ip6_main; - ip6_hop_by_hop_main_t * hm = &ip6_hop_by_hop_main; + ip6_main_t *im = &ip6_main; + ip6_hop_by_hop_main_t *hm = &ip6_hop_by_hop_main; ASSERT (option < ARRAY_LEN (hm->options)); @@ -2602,8 +2795,8 @@ ip6_hbh_register_option (u8 option, int ip6_hbh_unregister_option (u8 option) { - ip6_main_t * im = &ip6_main; - ip6_hop_by_hop_main_t * hm = &ip6_hop_by_hop_main; + ip6_main_t *im = &ip6_main; + ip6_hop_by_hop_main_t *hm = &ip6_hop_by_hop_main; ASSERT (option < ARRAY_LEN (hm->options)); @@ -2617,12 +2810,14 @@ ip6_hbh_unregister_option (u8 option) /* Disable global knob if this was the last option configured */ int i; bool found = false; - for (i = 0; i < 256; i++) { - if (hm->options[option]) { - found = true; - break; + for (i = 0; i < 256; i++) + { + if (hm->options[option]) + { + found = true; + break; + } } - } if (!found) im->hbh_enabled = 0; @@ -2635,10 +2830,13 @@ ip6_main_t ip6_main; static clib_error_t * ip6_lookup_init (vlib_main_t * vm) { - ip6_main_t * im = &ip6_main; - clib_error_t * error; + ip6_main_t *im = &ip6_main; + clib_error_t *error; uword i; + if ((error = vlib_call_init_function (vm, vnet_feature_init))) + return error; + for (i = 0; i < ARRAY_LEN (im->fib_masks); i++) { u32 j, i0, i1; @@ -2650,7 +2848,8 @@ ip6_lookup_init (vlib_main_t * vm) im->fib_masks[i].as_u32[j] = ~0; if (i1) - im->fib_masks[i].as_u32[i0] = clib_host_to_net_u32 (pow2_mask (i1) << (32 - i1)); + im->fib_masks[i].as_u32[i0] = + clib_host_to_net_u32 (pow2_mask (i1) << (32 - i1)); } ip_lookup_init (&im->lookup_main, /* is_ip6 */ 1); @@ -2658,25 +2857,23 @@ ip6_lookup_init (vlib_main_t * vm) if (im->lookup_table_nbuckets == 0) im->lookup_table_nbuckets = IP6_FIB_DEFAULT_HASH_NUM_BUCKETS; - im->lookup_table_nbuckets = 1<< max_log2 (im->lookup_table_nbuckets); + im->lookup_table_nbuckets = 1 << max_log2 (im->lookup_table_nbuckets); if (im->lookup_table_size == 0) im->lookup_table_size = IP6_FIB_DEFAULT_HASH_MEMORY_SIZE; - BV(clib_bihash_init) (&(im->ip6_table[IP6_FIB_TABLE_FWDING].ip6_hash), - "ip6 FIB fwding table", - im->lookup_table_nbuckets, - im->lookup_table_size); - BV(clib_bihash_init) (&im->ip6_table[IP6_FIB_TABLE_NON_FWDING].ip6_hash, - "ip6 FIB non-fwding table", - im->lookup_table_nbuckets, - im->lookup_table_size); + BV (clib_bihash_init) (&(im->ip6_table[IP6_FIB_TABLE_FWDING].ip6_hash), + "ip6 FIB fwding table", + im->lookup_table_nbuckets, im->lookup_table_size); + BV (clib_bihash_init) (&im->ip6_table[IP6_FIB_TABLE_NON_FWDING].ip6_hash, + "ip6 FIB non-fwding table", + im->lookup_table_nbuckets, im->lookup_table_size); /* Create FIB with index 0 and table id of 0. */ - fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP6, 0); + fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, 0); { - pg_node_t * pn; + pg_node_t *pn; pn = pg_get_node (ip6_lookup_node.index); pn->unformat_edit = unformat_pg_ip6_header; } @@ -2689,17 +2886,22 @@ ip6_lookup_init (vlib_main_t * vm) memset (&p, 0, sizeof (p)); - p.ip.ip_version_traffic_class_and_flow_label = clib_host_to_net_u32 (0x6 << 28); - p.ip.payload_length = clib_host_to_net_u16 (sizeof (p) - - STRUCT_OFFSET_OF (icmp6_neighbor_solicitation_header_t, neighbor)); + p.ip.ip_version_traffic_class_and_flow_label = + clib_host_to_net_u32 (0x6 << 28); + p.ip.payload_length = + clib_host_to_net_u16 (sizeof (p) - + STRUCT_OFFSET_OF + (icmp6_neighbor_solicitation_header_t, neighbor)); p.ip.protocol = IP_PROTOCOL_ICMP6; p.ip.hop_limit = 255; ip6_set_solicited_node_multicast_address (&p.ip.dst_address, 0); p.neighbor.icmp.type = ICMP6_neighbor_solicitation; - p.link_layer_option.header.type = ICMP6_NEIGHBOR_DISCOVERY_OPTION_source_link_layer_address; - p.link_layer_option.header.n_data_u64s = sizeof (p.link_layer_option) / sizeof (u64); + p.link_layer_option.header.type = + ICMP6_NEIGHBOR_DISCOVERY_OPTION_source_link_layer_address; + p.link_layer_option.header.n_data_u64s = + sizeof (p.link_layer_option) / sizeof (u64); vlib_packet_template_init (vm, &im->discover_neighbor_packet_template, @@ -2708,8 +2910,6 @@ ip6_lookup_init (vlib_main_t * vm) "ip6 neighbor discovery"); } - error = ip6_feature_init (vm, im); - return error; } @@ -2717,16 +2917,16 @@ VLIB_INIT_FUNCTION (ip6_lookup_init); static clib_error_t * add_del_ip6_interface_table (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) + unformat_input_t * input, + vlib_cli_command_t * cmd) { - vnet_main_t * vnm = vnet_get_main(); - clib_error_t * error = 0; + vnet_main_t *vnm = vnet_get_main (); + clib_error_t *error = 0; u32 sw_if_index, table_id; sw_if_index = ~0; - if (! unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index)) + if (!unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index)) { error = clib_error_return (0, "unknown interface `%U'", format_unformat_error, input); @@ -2743,57 +2943,79 @@ add_del_ip6_interface_table (vlib_main_t * vm, } { - u32 fib_index = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP6, - table_id); + u32 fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, + table_id); vec_validate (ip6_main.fib_index_by_sw_if_index, sw_if_index); ip6_main.fib_index_by_sw_if_index[sw_if_index] = fib_index; } - done: +done: return error; } -VLIB_CLI_COMMAND (set_interface_ip6_table_command, static) = { +/*? + * Place the indicated interface into the supplied IPv6 FIB table (also known + * as a VRF). If the FIB table does not exist, this command creates it. To + * display the current IPv6 FIB table, use the command 'show ip6 fib'. + * FIB table will only be displayed if a route has been added to the table, or + * an IP Address is assigned to an interface in the table (which adds a route + * automatically). + * + * @note IP addresses added after setting the interface IP table end up in + * the indicated FIB table. If the IP address is added prior to adding the + * interface to the FIB table, it will NOT be part of the FIB table. Predictable + * but potentially counter-intuitive results occur if you provision interface + * addresses in multiple FIBs. Upon RX, packets will be processed in the last + * IP table ID provisioned. It might be marginally useful to evade source RPF + * drops to put an interface address into multiple FIBs. + * + * @cliexpar + * Example of how to add an interface to an IPv6 FIB table (where 2 is the table-id): + * @cliexcmd{set interface ip6 table GigabitEthernet2/0/0 2} + ?*/ +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (set_interface_ip6_table_command, static) = +{ .path = "set interface ip6 table", .function = add_del_ip6_interface_table, - .short_help = "set interface ip6 table " + .short_help = "set interface ip6 table " }; +/* *INDENT-ON* */ void -ip6_link_local_address_from_ethernet_mac_address (ip6_address_t *ip, - u8 *mac) +ip6_link_local_address_from_ethernet_mac_address (ip6_address_t * ip, + u8 * mac) { ip->as_u64[0] = clib_host_to_net_u64 (0xFE80000000000000ULL); /* Invert the "u" bit */ - ip->as_u8 [8] = mac[0] ^ (1<<1); - ip->as_u8 [9] = mac[1]; - ip->as_u8 [10] = mac[2]; - ip->as_u8 [11] = 0xFF; - ip->as_u8 [12] = 0xFE; - ip->as_u8 [13] = mac[3]; - ip->as_u8 [14] = mac[4]; - ip->as_u8 [15] = mac[5]; + ip->as_u8[8] = mac[0] ^ (1 << 1); + ip->as_u8[9] = mac[1]; + ip->as_u8[10] = mac[2]; + ip->as_u8[11] = 0xFF; + ip->as_u8[12] = 0xFE; + ip->as_u8[13] = mac[3]; + ip->as_u8[14] = mac[4]; + ip->as_u8[15] = mac[5]; } void -ip6_ethernet_mac_address_from_link_local_address (u8 *mac, - ip6_address_t *ip) +ip6_ethernet_mac_address_from_link_local_address (u8 * mac, + ip6_address_t * ip) { /* Invert the previously inverted "u" bit */ - mac[0] = ip->as_u8 [8] ^ (1<<1); - mac[1] = ip->as_u8 [9]; - mac[2] = ip->as_u8 [10]; - mac[3] = ip->as_u8 [13]; - mac[4] = ip->as_u8 [14]; - mac[5] = ip->as_u8 [15]; + mac[0] = ip->as_u8[8] ^ (1 << 1); + mac[1] = ip->as_u8[9]; + mac[2] = ip->as_u8[10]; + mac[3] = ip->as_u8[13]; + mac[4] = ip->as_u8[14]; + mac[5] = ip->as_u8[15]; } static clib_error_t * test_ip6_link_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) + unformat_input_t * input, vlib_cli_command_t * cmd) { u8 mac[6]; ip6_address_t _a, *a = &_a; @@ -2801,27 +3023,41 @@ test_ip6_link_command_fn (vlib_main_t * vm, if (unformat (input, "%U", unformat_ethernet_address, mac)) { ip6_link_local_address_from_ethernet_mac_address (a, mac); - vlib_cli_output (vm, "Link local address: %U", - format_ip6_address, a); + vlib_cli_output (vm, "Link local address: %U", format_ip6_address, a); ip6_ethernet_mac_address_from_link_local_address (mac, a); vlib_cli_output (vm, "Original MAC address: %U", - format_ethernet_address, mac); + format_ethernet_address, mac); } return 0; } -VLIB_CLI_COMMAND (test_link_command, static) = { +/*? + * This command converts the given MAC Address into an IPv6 link-local + * address. + * + * @cliexpar + * Example of how to create an IPv6 link-local address: + * @cliexstart{test ip6 link 16:d9:e0:91:79:86} + * Link local address: fe80::14d9:e0ff:fe91:7986 + * Original MAC address: 16:d9:e0:91:79:86 + * @cliexend +?*/ +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (test_link_command, static) = +{ .path = "test ip6 link", .function = test_ip6_link_command_fn, .short_help = "test ip6 link ", }; +/* *INDENT-ON* */ -int vnet_set_ip6_flow_hash (u32 table_id, u32 flow_hash_config) +int +vnet_set_ip6_flow_hash (u32 table_id, u32 flow_hash_config) { - ip6_main_t * im6 = &ip6_main; - ip6_fib_t * fib; - uword * p = hash_get (im6->fib_index_by_table_id, table_id); + ip6_main_t *im6 = &ip6_main; + ip6_fib_t *fib; + uword *p = hash_get (im6->fib_index_by_table_id, table_id); if (p == 0) return -1; @@ -2834,27 +3070,29 @@ int vnet_set_ip6_flow_hash (u32 table_id, u32 flow_hash_config) static clib_error_t * set_ip6_flow_hash_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) + unformat_input_t * input, + vlib_cli_command_t * cmd) { int matched = 0; u32 table_id = 0; u32 flow_hash_config = 0; int rv; - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { - if (unformat (input, "table %d", &table_id)) - matched = 1; + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "table %d", &table_id)) + matched = 1; #define _(a,v) \ else if (unformat (input, #a)) { flow_hash_config |= v; matched=1;} - foreach_flow_hash_bit + foreach_flow_hash_bit #undef _ - else break; - } + else + break; + } if (matched == 0) return clib_error_return (0, "unknown input `%U'", - format_unformat_error, input); + format_unformat_error, input); rv = vnet_set_ip6_flow_hash (table_id, flow_hash_config); switch (rv) @@ -2873,47 +3111,141 @@ set_ip6_flow_hash_command_fn (vlib_main_t * vm, return 0; } -VLIB_CLI_COMMAND (set_ip6_flow_hash_command, static) = { - .path = "set ip6 flow-hash", - .short_help = - "set ip table flow-hash table src dst sport dport proto reverse", - .function = set_ip6_flow_hash_command_fn, +/*? + * Configure the set of IPv6 fields used by the flow hash. + * + * @cliexpar + * @parblock + * Example of how to set the flow hash on a given table: + * @cliexcmd{set ip6 flow-hash table 8 dst sport dport proto} + * + * Example of display the configured flow hash: + * @cliexstart{show ip6 fib} + * ipv6-VRF:0, fib_index 0, flow hash: src dst sport dport proto + * @::/0 + * unicast-ip6-chain + * [@0]: dpo-load-balance: [index:5 buckets:1 uRPF:5 to:[0:0]] + * [0] [@0]: dpo-drop ip6 + * fe80::/10 + * unicast-ip6-chain + * [@0]: dpo-load-balance: [index:10 buckets:1 uRPF:10 to:[0:0]] + * [0] [@2]: dpo-receive + * ff02::1/128 + * unicast-ip6-chain + * [@0]: dpo-load-balance: [index:8 buckets:1 uRPF:8 to:[0:0]] + * [0] [@2]: dpo-receive + * ff02::2/128 + * unicast-ip6-chain + * [@0]: dpo-load-balance: [index:7 buckets:1 uRPF:7 to:[0:0]] + * [0] [@2]: dpo-receive + * ff02::16/128 + * unicast-ip6-chain + * [@0]: dpo-load-balance: [index:9 buckets:1 uRPF:9 to:[0:0]] + * [0] [@2]: dpo-receive + * ff02::1:ff00:0/104 + * unicast-ip6-chain + * [@0]: dpo-load-balance: [index:6 buckets:1 uRPF:6 to:[0:0]] + * [0] [@2]: dpo-receive + * ipv6-VRF:8, fib_index 1, flow hash: dst sport dport proto + * @::/0 + * unicast-ip6-chain + * [@0]: dpo-load-balance: [index:21 buckets:1 uRPF:20 to:[0:0]] + * [0] [@0]: dpo-drop ip6 + * @::a:1:1:0:4/126 + * unicast-ip6-chain + * [@0]: dpo-load-balance: [index:27 buckets:1 uRPF:26 to:[0:0]] + * [0] [@4]: ipv6-glean: af_packet0 + * @::a:1:1:0:7/128 + * unicast-ip6-chain + * [@0]: dpo-load-balance: [index:28 buckets:1 uRPF:27 to:[0:0]] + * [0] [@2]: dpo-receive: @::a:1:1:0:7 on af_packet0 + * fe80::/10 + * unicast-ip6-chain + * [@0]: dpo-load-balance: [index:26 buckets:1 uRPF:25 to:[0:0]] + * [0] [@2]: dpo-receive + * fe80::fe:3eff:fe3e:9222/128 + * unicast-ip6-chain + * [@0]: dpo-load-balance: [index:29 buckets:1 uRPF:28 to:[0:0]] + * [0] [@2]: dpo-receive: fe80::fe:3eff:fe3e:9222 on af_packet0 + * ff02::1/128 + * unicast-ip6-chain + * [@0]: dpo-load-balance: [index:24 buckets:1 uRPF:23 to:[0:0]] + * [0] [@2]: dpo-receive + * ff02::2/128 + * unicast-ip6-chain + * [@0]: dpo-load-balance: [index:23 buckets:1 uRPF:22 to:[0:0]] + * [0] [@2]: dpo-receive + * ff02::16/128 + * unicast-ip6-chain + * [@0]: dpo-load-balance: [index:25 buckets:1 uRPF:24 to:[0:0]] + * [0] [@2]: dpo-receive + * ff02::1:ff00:0/104 + * unicast-ip6-chain + * [@0]: dpo-load-balance: [index:22 buckets:1 uRPF:21 to:[0:0]] + * [0] [@2]: dpo-receive + * @cliexend + * @endparblock +?*/ +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (set_ip6_flow_hash_command, static) = +{ + .path = "set ip6 flow-hash", + .short_help = + "set ip6 flow-hash table [src] [dst] [sport] [dport] [proto] [reverse]", + .function = set_ip6_flow_hash_command_fn, }; +/* *INDENT-ON* */ static clib_error_t * show_ip6_local_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) + unformat_input_t * input, vlib_cli_command_t * cmd) { - ip6_main_t * im = &ip6_main; - ip_lookup_main_t * lm = &im->lookup_main; + ip6_main_t *im = &ip6_main; + ip_lookup_main_t *lm = &im->lookup_main; int i; vlib_cli_output (vm, "Protocols handled by ip6_local"); - for (i = 0; i < ARRAY_LEN(lm->local_next_by_ip_protocol); i++) + for (i = 0; i < ARRAY_LEN (lm->local_next_by_ip_protocol); i++) { if (lm->local_next_by_ip_protocol[i] != IP_LOCAL_NEXT_PUNT) - vlib_cli_output (vm, "%d", i); + vlib_cli_output (vm, "%d", i); } return 0; } -VLIB_CLI_COMMAND (show_ip6_local, static) = { +/*? + * Display the set of protocols handled by the local IPv6 stack. + * + * @cliexpar + * Example of how to display local protocol table: + * @cliexstart{show ip6 local} + * Protocols handled by ip6_local + * 17 + * 43 + * 58 + * 115 + * @cliexend +?*/ +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (show_ip6_local, static) = +{ .path = "show ip6 local", .function = show_ip6_local_command_fn, - .short_help = "Show ip6 local protocol table", + .short_help = "show ip6 local", }; +/* *INDENT-ON* */ -int vnet_set_ip6_classify_intfc (vlib_main_t * vm, u32 sw_if_index, - u32 table_index) +int +vnet_set_ip6_classify_intfc (vlib_main_t * vm, u32 sw_if_index, + u32 table_index) { - vnet_main_t * vnm = vnet_get_main(); - vnet_interface_main_t * im = &vnm->interface_main; - ip6_main_t * ipm = &ip6_main; - ip_lookup_main_t * lm = &ipm->lookup_main; - vnet_classify_main_t * cm = &vnet_classify_main; + vnet_main_t *vnm = vnet_get_main (); + vnet_interface_main_t *im = &vnm->interface_main; + ip6_main_t *ipm = &ip6_main; + ip_lookup_main_t *lm = &ipm->lookup_main; + vnet_classify_main_t *cm = &vnet_classify_main; ip6_address_t *if_addr; if (pool_is_free_index (im->sw_interfaces, sw_if_index)) @@ -2923,73 +3255,71 @@ int vnet_set_ip6_classify_intfc (vlib_main_t * vm, u32 sw_if_index, return VNET_API_ERROR_NO_SUCH_ENTRY; vec_validate (lm->classify_table_index_by_sw_if_index, sw_if_index); - lm->classify_table_index_by_sw_if_index [sw_if_index] = table_index; + lm->classify_table_index_by_sw_if_index[sw_if_index] = table_index; if_addr = ip6_interface_first_address (ipm, sw_if_index, NULL); if (NULL != if_addr) - { + { fib_prefix_t pfx = { - .fp_len = 128, - .fp_proto = FIB_PROTOCOL_IP6, - .fp_addr.ip6 = *if_addr, + .fp_len = 128, + .fp_proto = FIB_PROTOCOL_IP6, + .fp_addr.ip6 = *if_addr, }; u32 fib_index; - fib_index = fib_table_get_index_for_sw_if_index(FIB_PROTOCOL_IP4, - sw_if_index); - + fib_index = fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4, + sw_if_index); - if (table_index != (u32) ~0) - { - dpo_id_t dpo = DPO_NULL; - dpo_set(&dpo, - DPO_CLASSIFY, - DPO_PROTO_IP4, - classify_dpo_create(FIB_PROTOCOL_IP4, - table_index)); - - fib_table_entry_special_dpo_add(fib_index, - &pfx, - FIB_SOURCE_CLASSIFY, - FIB_ENTRY_FLAG_NONE, - &dpo); - dpo_reset(&dpo); - } + if (table_index != (u32) ~ 0) + { + dpo_id_t dpo = DPO_INVALID; + + dpo_set (&dpo, + DPO_CLASSIFY, + DPO_PROTO_IP6, + classify_dpo_create (DPO_PROTO_IP6, table_index)); + + fib_table_entry_special_dpo_add (fib_index, + &pfx, + FIB_SOURCE_CLASSIFY, + FIB_ENTRY_FLAG_NONE, &dpo); + dpo_reset (&dpo); + } else - { - fib_table_entry_special_remove(fib_index, - &pfx, - FIB_SOURCE_CLASSIFY); - } - } + { + fib_table_entry_special_remove (fib_index, + &pfx, FIB_SOURCE_CLASSIFY); + } + } return 0; } static clib_error_t * set_ip6_classify_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) + unformat_input_t * input, + vlib_cli_command_t * cmd) { u32 table_index = ~0; int table_index_set = 0; u32 sw_if_index = ~0; int rv; - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { - if (unformat (input, "table-index %d", &table_index)) - table_index_set = 1; - else if (unformat (input, "intfc %U", unformat_vnet_sw_interface, - vnet_get_main(), &sw_if_index)) - ; - else - break; - } + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "table-index %d", &table_index)) + table_index_set = 1; + else if (unformat (input, "intfc %U", unformat_vnet_sw_interface, + vnet_get_main (), &sw_if_index)) + ; + else + break; + } if (table_index_set == 0) - return clib_error_return (0, "classify table-index must be specified"); + return clib_error_return (0, "classify table-index must be specified"); if (sw_if_index == ~0) return clib_error_return (0, "interface / subif must be specified"); @@ -3010,82 +3340,63 @@ set_ip6_classify_command_fn (vlib_main_t * vm, return 0; } -VLIB_CLI_COMMAND (set_ip6_classify_command, static) = { - .path = "set ip6 classify", - .short_help = - "set ip6 classify intfc table-index ", - .function = set_ip6_classify_command_fn, +/*? + * Assign a classification table to an interface. The classification + * table is created using the 'classify table' and 'classify session' + * commands. Once the table is create, use this command to filter packets + * on an interface. + * + * @cliexpar + * Example of how to assign a classification table to an interface: + * @cliexcmd{set ip6 classify intfc GigabitEthernet2/0/0 table-index 1} +?*/ +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (set_ip6_classify_command, static) = +{ + .path = "set ip6 classify", + .short_help = + "set ip6 classify intfc table-index ", + .function = set_ip6_classify_command_fn, }; +/* *INDENT-ON* */ static clib_error_t * ip6_config (vlib_main_t * vm, unformat_input_t * input) { - ip6_main_t * im = &ip6_main; + ip6_main_t *im = &ip6_main; uword heapsize = 0; u32 tmp; u32 nbuckets = 0; - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { - if (unformat (input, "hash-buckets %d", &tmp)) - nbuckets = tmp; - else if (unformat (input, "heap-size %dm", &tmp)) - heapsize = ((u64)tmp) << 20; - else if (unformat (input, "heap-size %dM", &tmp)) - heapsize = ((u64)tmp) << 20; - else if (unformat (input, "heap-size %dg", &tmp)) - heapsize = ((u64)tmp) << 30; - else if (unformat (input, "heap-size %dG", &tmp)) - heapsize = ((u64)tmp) << 30; - else - return clib_error_return (0, "unknown input '%U'", - format_unformat_error, input); - } - - im->lookup_table_nbuckets = nbuckets; - im->lookup_table_size = heapsize; - - return 0; -} - -VLIB_EARLY_CONFIG_FUNCTION (ip6_config, "ip6"); - -#define TEST_CODE 1 -#if TEST_CODE > 0 - -static clib_error_t * -set_interface_ip6_output_feature_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - vnet_main_t * vnm = vnet_get_main(); - u32 sw_if_index = ~0; - int is_add = 1; - ip6_main_t * im = &ip6_main; - ip_lookup_main_t * lm = &im->lookup_main; - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { - if (unformat (input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index)) - ; - else if (unformat (input, "del")) - is_add = 0; + if (unformat (input, "hash-buckets %d", &tmp)) + nbuckets = tmp; + else if (unformat (input, "heap-size %dm", &tmp)) + heapsize = ((u64) tmp) << 20; + else if (unformat (input, "heap-size %dM", &tmp)) + heapsize = ((u64) tmp) << 20; + else if (unformat (input, "heap-size %dg", &tmp)) + heapsize = ((u64) tmp) << 30; + else if (unformat (input, "heap-size %dG", &tmp)) + heapsize = ((u64) tmp) << 30; else - break; + return clib_error_return (0, "unknown input '%U'", + format_unformat_error, input); } - if (sw_if_index == ~0) - return clib_error_return (0, "unknown interface `%U'", - format_unformat_error, input); - - lm->tx_sw_if_has_ip_output_features = - clib_bitmap_set (lm->tx_sw_if_has_ip_output_features, sw_if_index, is_add); + im->lookup_table_nbuckets = nbuckets; + im->lookup_table_size = heapsize; return 0; } -VLIB_CLI_COMMAND (set_interface_ip6_output_feature, static) = { - .path = "set interface ip6 output feature", - .function = set_interface_ip6_output_feature_command_fn, - .short_help = "set interface output feature ", -}; -#endif /* TEST_CODE */ +VLIB_EARLY_CONFIG_FUNCTION (ip6_config, "ip6"); + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */