LCOV - code coverage report
Current view: top level - vnet/ip - ip6_input.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 102 102 100.0 %
Date: 2023-10-26 01:39:38 Functions: 11 14 78.6 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2015 Cisco and/or its affiliates.
       3             :  * Licensed under the Apache License, Version 2.0 (the "License");
       4             :  * you may not use this file except in compliance with the License.
       5             :  * You may obtain a copy of the License at:
       6             :  *
       7             :  *     http://www.apache.org/licenses/LICENSE-2.0
       8             :  *
       9             :  * Unless required by applicable law or agreed to in writing, software
      10             :  * distributed under the License is distributed on an "AS IS" BASIS,
      11             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12             :  * See the License for the specific language governing permissions and
      13             :  * limitations under the License.
      14             :  */
      15             : /*
      16             :  * ip/ip6_input.c: IP v6 input node
      17             :  *
      18             :  * Copyright (c) 2008 Eliot Dresselhaus
      19             :  *
      20             :  * Permission is hereby granted, free of charge, to any person obtaining
      21             :  * a copy of this software and associated documentation files (the
      22             :  * "Software"), to deal in the Software without restriction, including
      23             :  * without limitation the rights to use, copy, modify, merge, publish,
      24             :  * distribute, sublicense, and/or sell copies of the Software, and to
      25             :  * permit persons to whom the Software is furnished to do so, subject to
      26             :  * the following conditions:
      27             :  *
      28             :  * The above copyright notice and this permission notice shall be
      29             :  * included in all copies or substantial portions of the Software.
      30             :  *
      31             :  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
      32             :  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
      33             :  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
      34             :  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
      35             :  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
      36             :  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
      37             :  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      38             :  */
      39             : 
      40             : #include <vnet/ip/ip6_input.h>
      41             : #include <vnet/ethernet/ethernet.h>
      42             : #include <vnet/ppp/ppp.h>
      43             : #include <vnet/hdlc/hdlc.h>
      44             : #include <vnet/pg/pg.h>
      45             : 
      46             : typedef struct
      47             : {
      48             :   u8 packet_data[64];
      49             : } ip6_input_trace_t;
      50             : 
      51             : static u8 *
      52      156654 : format_ip6_input_trace (u8 * s, va_list * va)
      53             : {
      54      156654 :   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *);
      55      156654 :   CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *);
      56      156654 :   ip6_input_trace_t *t = va_arg (*va, ip6_input_trace_t *);
      57             : 
      58      156654 :   s = format (s, "%U",
      59      156654 :               format_ip6_header, t->packet_data, sizeof (t->packet_data));
      60             : 
      61      156654 :   return s;
      62             : }
      63             : 
      64             : /* Validate IP v6 packets and pass them either to forwarding code
      65             :    or drop exception packets. */
      66      235081 : VLIB_NODE_FN (ip6_input_node) (vlib_main_t * vm, vlib_node_runtime_t * node,
      67             :                                vlib_frame_t * frame)
      68             : {
      69      232781 :   vnet_main_t *vnm = vnet_get_main ();
      70      232781 :   ip6_main_t *im = &ip6_main;
      71      232781 :   ip_lookup_main_t *lm = &im->lookup_main;
      72             :   u32 n_left_from, *from, *to_next;
      73             :   ip6_input_next_t next_index;
      74             :   vlib_node_runtime_t *error_node =
      75      232781 :     vlib_node_get_runtime (vm, ip6_input_node.index);
      76             :   vlib_simple_counter_main_t *cm;
      77      232781 :   u32 thread_index = vm->thread_index;
      78             : 
      79      232781 :   from = vlib_frame_vector_args (frame);
      80      232781 :   n_left_from = frame->n_vectors;
      81      232781 :   next_index = node->cached_next_index;
      82             : 
      83      232781 :   if (node->flags & VLIB_NODE_FLAG_TRACE)
      84        5466 :     vlib_trace_frame_buffers_only (vm, node, from, frame->n_vectors,
      85             :                                    /* stride */ 1,
      86             :                                    sizeof (ip6_input_trace_t));
      87             : 
      88      232782 :   cm = vec_elt_at_index (vnm->interface_main.sw_if_counters,
      89             :                          VNET_INTERFACE_COUNTER_IP6);
      90             : 
      91      465565 :   while (n_left_from > 0)
      92             :     {
      93             :       u32 n_left_to_next;
      94             : 
      95      232784 :       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
      96             : 
      97     4997010 :       while (n_left_from >= 4 && n_left_to_next >= 2)
      98             :         {
      99             :           vlib_buffer_t *p0, *p1;
     100             :           ip6_header_t *ip0, *ip1;
     101     4764220 :           u32 pi0, sw_if_index0, next0 = 0;
     102     4764220 :           u32 pi1, sw_if_index1, next1 = 0;
     103             :           u8 arc0, arc1;
     104             : 
     105             :           /* Prefetch next iteration. */
     106             :           {
     107             :             vlib_buffer_t *p2, *p3;
     108             : 
     109     4764220 :             p2 = vlib_get_buffer (vm, from[2]);
     110     4764220 :             p3 = vlib_get_buffer (vm, from[3]);
     111             : 
     112     4764220 :             vlib_prefetch_buffer_header (p2, LOAD);
     113     4764220 :             vlib_prefetch_buffer_header (p3, LOAD);
     114             : 
     115     4764220 :             CLIB_PREFETCH (p2->data, sizeof (ip0[0]), LOAD);
     116     4764220 :             CLIB_PREFETCH (p3->data, sizeof (ip1[0]), LOAD);
     117             :           }
     118             : 
     119     4764220 :           pi0 = from[0];
     120     4764220 :           pi1 = from[1];
     121             : 
     122     4764220 :           to_next[0] = pi0;
     123     4764220 :           to_next[1] = pi1;
     124     4764220 :           from += 2;
     125     4764220 :           to_next += 2;
     126     4764220 :           n_left_from -= 2;
     127     4764220 :           n_left_to_next -= 2;
     128             : 
     129     4764220 :           p0 = vlib_get_buffer (vm, pi0);
     130     4764220 :           p1 = vlib_get_buffer (vm, pi1);
     131             : 
     132     4764220 :           ip0 = vlib_buffer_get_current (p0);
     133     4764220 :           ip1 = vlib_buffer_get_current (p1);
     134             : 
     135     4764220 :           sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX];
     136     4764220 :           sw_if_index1 = vnet_buffer (p1)->sw_if_index[VLIB_RX];
     137             : 
     138     4764220 :           if (PREDICT_FALSE (ip6_address_is_multicast (&ip0->dst_address)))
     139             :             {
     140         480 :               arc0 = lm->mcast_feature_arc_index;
     141         480 :               next0 = IP6_INPUT_NEXT_LOOKUP_MULTICAST;
     142             :             }
     143             :           else
     144             :             {
     145     4763740 :               arc0 = lm->ucast_feature_arc_index;
     146     4763740 :               next0 = IP6_INPUT_NEXT_LOOKUP;
     147             :             }
     148             : 
     149     4764220 :           if (PREDICT_FALSE (ip6_address_is_multicast (&ip1->dst_address)))
     150             :             {
     151         468 :               arc1 = lm->mcast_feature_arc_index;
     152         468 :               next1 = IP6_INPUT_NEXT_LOOKUP_MULTICAST;
     153             :             }
     154             :           else
     155             :             {
     156     4763750 :               arc1 = lm->ucast_feature_arc_index;
     157     4763750 :               next1 = IP6_INPUT_NEXT_LOOKUP;
     158             :             }
     159             : 
     160     4764220 :           vnet_buffer (p0)->ip.adj_index[VLIB_RX] = ~0;
     161     4764220 :           vnet_buffer (p1)->ip.adj_index[VLIB_RX] = ~0;
     162             : 
     163     4764220 :           vnet_feature_arc_start (arc0, sw_if_index0, &next0, p0);
     164     4764220 :           vnet_feature_arc_start (arc1, sw_if_index1, &next1, p1);
     165             : 
     166     4764220 :           vlib_increment_simple_counter (cm, thread_index, sw_if_index0, 1);
     167     4764220 :           vlib_increment_simple_counter (cm, thread_index, sw_if_index1, 1);
     168     4764220 :           ip6_input_check_x2 (vm, error_node,
     169             :                               p0, p1, ip0, ip1, &next0, &next1);
     170             : 
     171     4764220 :           vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
     172             :                                            to_next, n_left_to_next,
     173             :                                            pi0, pi1, next0, next1);
     174             :         }
     175             : 
     176      747288 :       while (n_left_from > 0 && n_left_to_next > 0)
     177             :         {
     178             :           vlib_buffer_t *p0;
     179             :           ip6_header_t *ip0;
     180      514504 :           u32 pi0, sw_if_index0, next0 = 0;
     181             :           u8 arc0;
     182             : 
     183      514504 :           pi0 = from[0];
     184      514504 :           to_next[0] = pi0;
     185      514504 :           from += 1;
     186      514504 :           to_next += 1;
     187      514504 :           n_left_from -= 1;
     188      514504 :           n_left_to_next -= 1;
     189             : 
     190      514504 :           p0 = vlib_get_buffer (vm, pi0);
     191      514504 :           ip0 = vlib_buffer_get_current (p0);
     192             : 
     193      514504 :           sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX];
     194      514504 :           if (PREDICT_FALSE (ip6_address_is_multicast (&ip0->dst_address)))
     195             :             {
     196        3109 :               arc0 = lm->mcast_feature_arc_index;
     197        3109 :               next0 = IP6_INPUT_NEXT_LOOKUP_MULTICAST;
     198             :             }
     199             :           else
     200             :             {
     201      511395 :               arc0 = lm->ucast_feature_arc_index;
     202      511395 :               next0 = IP6_INPUT_NEXT_LOOKUP;
     203             :             }
     204             : 
     205      514504 :           vnet_buffer (p0)->ip.adj_index[VLIB_RX] = ~0;
     206      514504 :           vnet_feature_arc_start (arc0, sw_if_index0, &next0, p0);
     207             : 
     208      514504 :           vlib_increment_simple_counter (cm, thread_index, sw_if_index0, 1);
     209      514504 :           ip6_input_check_x1 (vm, error_node, p0, ip0, &next0);
     210             : 
     211      514504 :           vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
     212             :                                            to_next, n_left_to_next,
     213             :                                            pi0, next0);
     214             :         }
     215             : 
     216      232784 :       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
     217             :     }
     218             : 
     219      232781 :   return frame->n_vectors;
     220             : }
     221             : 
     222             : /* *INDENT-OFF* */
     223      183788 : VLIB_REGISTER_NODE (ip6_input_node) = {
     224             :   .name = "ip6-input",
     225             :   .vector_size = sizeof (u32),
     226             : 
     227             :   .n_errors = IP6_N_ERROR,
     228             :   .error_counters = ip6_error_counters,
     229             : 
     230             :   .n_next_nodes = IP6_INPUT_N_NEXT,
     231             :   .next_nodes = {
     232             :     [IP6_INPUT_NEXT_DROP] = "error-drop",
     233             :     [IP6_INPUT_NEXT_LOOKUP] = "ip6-lookup",
     234             :     [IP6_INPUT_NEXT_ICMP_ERROR] = "ip6-icmp-error",
     235             :     [IP6_INPUT_NEXT_LOOKUP_MULTICAST] = "ip6-mfib-forward-lookup",
     236             :   },
     237             : 
     238             :   .format_buffer = format_ip6_header,
     239             :   .format_trace = format_ip6_input_trace,
     240             : };
     241             : /* *INDENT-ON* */
     242             : 
     243             : static clib_error_t *
     244         575 : ip6_init (vlib_main_t * vm)
     245             : {
     246         575 :   ethernet_register_input_type (vm, ETHERNET_TYPE_IP6, ip6_input_node.index);
     247         575 :   ppp_register_input_protocol (vm, PPP_PROTOCOL_ip6, ip6_input_node.index);
     248         575 :   hdlc_register_input_protocol (vm, HDLC_PROTOCOL_ip6, ip6_input_node.index);
     249             : 
     250             :   {
     251             :     pg_node_t *pn;
     252         575 :     pn = pg_get_node (ip6_input_node.index);
     253         575 :     pn->unformat_edit = unformat_pg_ip6_header;
     254             :   }
     255             : 
     256             :   /* Set flow hash to something non-zero. */
     257         575 :   ip6_main.flow_hash_seed = 0xdeadbeef;
     258             : 
     259             :   /* Default hop limit for packets we generate. */
     260         575 :   ip6_main.host_config.ttl = 64;
     261             : 
     262             : 
     263         575 :   uword *u = hash_get (ip_main.protocol_info_by_name, "IPV6_FRAGMENTATION");
     264         575 :   if (u)
     265             :     {
     266         575 :       ip_protocol_info_t *info =
     267         575 :         vec_elt_at_index (ip_main.protocol_infos, *u);
     268         575 :       ASSERT (NULL == info->format_header);
     269         575 :       info->format_header = format_ip6_frag_hdr;
     270             :     }
     271         575 :   return /* no error */ 0;
     272             : }
     273             : 
     274       14975 : VLIB_INIT_FUNCTION (ip6_init);
     275             : 
     276             : /*
     277             :  * fd.io coding-style-patch-verification: ON
     278             :  *
     279             :  * Local Variables:
     280             :  * eval: (c-set-style "gnu")
     281             :  * End:
     282             :  */

Generated by: LCOV version 1.14