LCOV - code coverage report
Current view: top level - vnet/udp - udp_local.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 208 251 82.9 %
Date: 2023-07-05 22:20:52 Functions: 26 33 78.8 %

          Line data    Source code
       1             : /*
       2             :  * node.c: udp packet processing
       3             :  *
       4             :  * Copyright (c) 2013-2019 Cisco and/or its affiliates.
       5             :  * Licensed under the Apache License, Version 2.0 (the "License");
       6             :  * you may not use this file except in compliance with the License.
       7             :  * You may obtain a copy of the License at:
       8             :  *
       9             :  *     http://www.apache.org/licenses/LICENSE-2.0
      10             :  *
      11             :  * Unless required by applicable law or agreed to in writing, software
      12             :  * distributed under the License is distributed on an "AS IS" BASIS,
      13             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      14             :  * See the License for the specific language governing permissions and
      15             :  * limitations under the License.
      16             :  */
      17             : 
      18             : #include <vlib/vlib.h>
      19             : #include <vnet/pg/pg.h>
      20             : #include <vnet/udp/udp.h>
      21             : #include <vnet/udp/udp_packet.h>
      22             : #include <vppinfra/sparse_vec.h>
      23             : 
      24             : typedef enum
      25             : {
      26             :   UDP_LOCAL_NEXT_PUNT,
      27             :   UDP_LOCAL_NEXT_DROP,
      28             :   UDP_LOCAL_NEXT_ICMP,
      29             :   UDP_LOCAL_N_NEXT
      30             : } udp_local_next_t;
      31             : 
      32             : typedef struct
      33             : {
      34             :   u16 src_port;
      35             :   u16 dst_port;
      36             :   u8 bound;
      37             : } udp_local_rx_trace_t;
      38             : 
      39             : static vlib_error_desc_t udp_error_counters[] = {
      40             : #define udp_error(f, n, s, d) { #n, d, VL_COUNTER_SEVERITY_##s },
      41             : #include "udp_error.def"
      42             : #undef udp_error
      43             : };
      44             : 
      45             : #ifndef CLIB_MARCH_VARIANT
      46             : u8 *
      47       10113 : format_udp_rx_trace (u8 * s, va_list * args)
      48             : {
      49       10113 :   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
      50       10113 :   CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
      51       10113 :   udp_local_rx_trace_t *t = va_arg (*args, udp_local_rx_trace_t *);
      52             : 
      53       20226 :   s = format (s, "UDP: src-port %d dst-port %d%s",
      54       10113 :               clib_net_to_host_u16 (t->src_port),
      55       10113 :               clib_net_to_host_u16 (t->dst_port),
      56       10113 :               t->bound ? "" : " (no listener)");
      57       10113 :   return s;
      58             : }
      59             : #endif /* CLIB_MARCH_VARIANT */
      60             : 
      61             : always_inline void
      62         133 : udp_dispatch_error (vlib_node_runtime_t *node, vlib_buffer_t *b, u32 advance,
      63             :                     u8 is_ip4, u32 *next)
      64             : {
      65         133 :   udp_main_t *um = &udp_main;
      66         133 :   u8 punt_unknown = is_ip4 ? um->punt_unknown4 : um->punt_unknown6;
      67             : 
      68         133 :   if (PREDICT_FALSE (punt_unknown))
      69             :     {
      70         101 :       vlib_buffer_advance (b, -(word) advance);
      71         101 :       b->error = node->errors[UDP_ERROR_PUNT];
      72         101 :       *next = UDP_LOCAL_NEXT_PUNT;
      73             :     }
      74          32 :   else if (um->icmp_send_unreachable_disabled)
      75             :     {
      76           0 :       *next = UDP_LOCAL_NEXT_DROP;
      77           0 :       b->error = node->errors[UDP_ERROR_NO_LISTENER];
      78             :     }
      79             :   else
      80             :     {
      81             :       /* move the pointer back so icmp-error can find the ip packet header */
      82          32 :       vlib_buffer_advance (b, -(word) advance);
      83             : 
      84          32 :       if (is_ip4)
      85             :         {
      86          27 :           icmp4_error_set_vnet_buffer (
      87             :             b, ICMP4_destination_unreachable,
      88             :             ICMP4_destination_unreachable_port_unreachable, 0);
      89          27 :           b->error = node->errors[UDP_ERROR_NO_LISTENER];
      90          27 :           *next = UDP_LOCAL_NEXT_ICMP;
      91             :         }
      92             :       else
      93             :         {
      94           5 :           icmp6_error_set_vnet_buffer (
      95             :             b, ICMP6_destination_unreachable,
      96             :             ICMP6_destination_unreachable_port_unreachable, 0);
      97           5 :           b->error = node->errors[UDP_ERROR_NO_LISTENER];
      98           5 :           *next = UDP_LOCAL_NEXT_ICMP;
      99             :         }
     100             :     }
     101         133 : }
     102             : 
     103             : always_inline uword
     104       11738 : udp46_local_inline (vlib_main_t * vm,
     105             :                     vlib_node_runtime_t * node,
     106             :                     vlib_frame_t * from_frame, int is_ip4)
     107             : {
     108       11738 :   udp_main_t *um = &udp_main;
     109             :   __attribute__ ((unused)) u32 n_left_from, next_index, *from, *to_next;
     110       11738 :   u16 *next_by_dst_port = (is_ip4 ?
     111       11738 :                            um->next_by_dst_port4 : um->next_by_dst_port6);
     112       11738 :   from = vlib_frame_vector_args (from_frame);
     113       11738 :   n_left_from = from_frame->n_vectors;
     114             : 
     115       11738 :   next_index = node->cached_next_index;
     116             : 
     117       23476 :   while (n_left_from > 0)
     118             :     {
     119             :       u32 n_left_to_next;
     120             : 
     121       11738 :       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
     122             : 
     123       42129 :       while (n_left_from >= 4 && n_left_to_next >= 2)
     124             :         {
     125             :           u32 bi0, bi1;
     126             :           vlib_buffer_t *b0, *b1;
     127       30391 :           udp_header_t *h0 = 0, *h1 = 0;
     128             :           u32 i0, i1, next0, next1;
     129             :           u32 advance0, advance1;
     130             : 
     131             :           /* Prefetch next iteration. */
     132             :           {
     133             :             vlib_buffer_t *p2, *p3;
     134             : 
     135       30391 :             p2 = vlib_get_buffer (vm, from[2]);
     136       30391 :             p3 = vlib_get_buffer (vm, from[3]);
     137             : 
     138       30391 :             vlib_prefetch_buffer_header (p2, LOAD);
     139       30391 :             vlib_prefetch_buffer_header (p3, LOAD);
     140             : 
     141       30391 :             CLIB_PREFETCH (p2->data, sizeof (h0[0]), LOAD);
     142       30391 :             CLIB_PREFETCH (p3->data, sizeof (h1[0]), LOAD);
     143             :           }
     144             : 
     145       30391 :           bi0 = from[0];
     146       30391 :           bi1 = from[1];
     147       30391 :           to_next[0] = bi0;
     148       30391 :           to_next[1] = bi1;
     149       30391 :           from += 2;
     150       30391 :           to_next += 2;
     151       30391 :           n_left_to_next -= 2;
     152       30391 :           n_left_from -= 2;
     153             : 
     154       30391 :           b0 = vlib_get_buffer (vm, bi0);
     155       30391 :           b1 = vlib_get_buffer (vm, bi1);
     156             : 
     157             :           /* ip4/6_local hands us the ip header, not the udp header */
     158       30391 :           if (is_ip4)
     159             :             {
     160       26600 :               advance0 = ip4_header_bytes (vlib_buffer_get_current (b0));
     161       26600 :               advance1 = ip4_header_bytes (vlib_buffer_get_current (b1));
     162             :             }
     163             :           else
     164             :             {
     165        3791 :               advance0 = sizeof (ip6_header_t);
     166        3791 :               advance1 = sizeof (ip6_header_t);
     167             :             }
     168             : 
     169       30391 :           if (PREDICT_FALSE (b0->current_length < advance0 + sizeof (*h0)))
     170             :             {
     171           0 :               b0->error = node->errors[UDP_ERROR_LENGTH_ERROR];
     172           0 :               next0 = UDP_LOCAL_NEXT_DROP;
     173             :             }
     174             :           else
     175             :             {
     176       30391 :               vlib_buffer_advance (b0, advance0);
     177       30391 :               h0 = vlib_buffer_get_current (b0);
     178       30391 :               next0 = UDP_LOCAL_NEXT_PUNT;
     179       30391 :               if (PREDICT_FALSE (clib_net_to_host_u16 (h0->length) >
     180             :                                  vlib_buffer_length_in_chain (vm, b0)))
     181             :                 {
     182           0 :                   b0->error = node->errors[UDP_ERROR_LENGTH_ERROR];
     183           0 :                   next0 = UDP_LOCAL_NEXT_DROP;
     184             :                 }
     185             :             }
     186             : 
     187       30391 :           if (PREDICT_FALSE (b1->current_length < advance1 + sizeof (*h1)))
     188             :             {
     189           0 :               b1->error = node->errors[UDP_ERROR_LENGTH_ERROR];
     190           0 :               next1 = UDP_LOCAL_NEXT_DROP;
     191             :             }
     192             :           else
     193             :             {
     194       30391 :               vlib_buffer_advance (b1, advance1);
     195       30391 :               h1 = vlib_buffer_get_current (b1);
     196       30391 :               next1 = UDP_LOCAL_NEXT_PUNT;
     197       30391 :               if (PREDICT_FALSE (clib_net_to_host_u16 (h1->length) >
     198             :                                  vlib_buffer_length_in_chain (vm, b1)))
     199             :                 {
     200           0 :                   b1->error = node->errors[UDP_ERROR_LENGTH_ERROR];
     201           0 :                   next1 = UDP_LOCAL_NEXT_DROP;
     202             :                 }
     203             :             }
     204             : 
     205             :           /* Index sparse array with network byte order. */
     206       30391 :           if (PREDICT_TRUE (next0 == UDP_LOCAL_NEXT_PUNT &&
     207             :                             next1 == UDP_LOCAL_NEXT_PUNT))
     208             :             {
     209       30391 :               sparse_vec_index2 (next_by_dst_port, h0->dst_port, h1->dst_port,
     210             :                                  &i0, &i1);
     211       30391 :               next0 = vec_elt (next_by_dst_port, i0);
     212       30391 :               next1 = vec_elt (next_by_dst_port, i1);
     213             : 
     214       30391 :               if (PREDICT_FALSE (i0 == SPARSE_VEC_INVALID_INDEX ||
     215             :                                  next0 == UDP_NO_NODE_SET))
     216             :                 {
     217          49 :                   udp_dispatch_error (node, b0, advance0, is_ip4, &next0);
     218             :                 }
     219             :               else
     220             :                 {
     221       30342 :                   b0->error = node->errors[UDP_ERROR_NONE];
     222             :                   // advance to the payload
     223       30342 :                   vlib_buffer_advance (b0, sizeof (*h0));
     224             :                 }
     225             : 
     226       30391 :               if (PREDICT_FALSE (i1 == SPARSE_VEC_INVALID_INDEX ||
     227             :                                  next1 == UDP_NO_NODE_SET))
     228             :                 {
     229          49 :                   udp_dispatch_error (node, b1, advance1, is_ip4, &next1);
     230             :                 }
     231             :               else
     232             :                 {
     233       30342 :                   b1->error = node->errors[UDP_ERROR_NONE];
     234             :                   // advance to the payload
     235       30342 :                   vlib_buffer_advance (b1, sizeof (*h1));
     236             :                 }
     237             :             }
     238           0 :           else if (next0 == UDP_LOCAL_NEXT_PUNT)
     239             :             {
     240           0 :               i0 = sparse_vec_index (next_by_dst_port, h0->dst_port);
     241           0 :               next0 = vec_elt (next_by_dst_port, i0);
     242             : 
     243           0 :               if (PREDICT_FALSE (i0 == SPARSE_VEC_INVALID_INDEX ||
     244             :                                  next0 == UDP_NO_NODE_SET))
     245             :                 {
     246           0 :                   udp_dispatch_error (node, b0, advance0, is_ip4, &next0);
     247             :                 }
     248             :               else
     249             :                 {
     250           0 :                   b0->error = node->errors[UDP_ERROR_NONE];
     251             :                   // advance to the payload
     252           0 :                   vlib_buffer_advance (b0, sizeof (*h0));
     253             :                 }
     254             :             }
     255           0 :           else if (next1 == UDP_LOCAL_NEXT_PUNT)
     256             :             {
     257           0 :               i1 = sparse_vec_index (next_by_dst_port, h1->dst_port);
     258           0 :               next1 = vec_elt (next_by_dst_port, i1);
     259             : 
     260           0 :               if (PREDICT_FALSE (i1 == SPARSE_VEC_INVALID_INDEX ||
     261             :                                  next1 == UDP_NO_NODE_SET))
     262             :                 {
     263           0 :                   udp_dispatch_error (node, b1, advance1, is_ip4, &next1);
     264             :                 }
     265             :               else
     266             :                 {
     267           0 :                   b1->error = node->errors[UDP_ERROR_NONE];
     268             :                   // advance to the payload
     269           0 :                   vlib_buffer_advance (b1, sizeof (*h1));
     270             :                 }
     271             :             }
     272             : 
     273       30391 :           if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
     274             :             {
     275        8464 :               udp_local_rx_trace_t *tr = vlib_add_trace (vm, node,
     276             :                                                          b0, sizeof (*tr));
     277        8464 :               if (b0->error != node->errors[UDP_ERROR_LENGTH_ERROR])
     278             :                 {
     279        8464 :                   tr->src_port = h0 ? h0->src_port : 0;
     280        8464 :                   tr->dst_port = h0 ? h0->dst_port : 0;
     281        8464 :                   tr->bound = (next0 != UDP_LOCAL_NEXT_ICMP);
     282             :                 }
     283             :             }
     284       30391 :           if (PREDICT_FALSE (b1->flags & VLIB_BUFFER_IS_TRACED))
     285             :             {
     286        8464 :               udp_local_rx_trace_t *tr = vlib_add_trace (vm, node,
     287             :                                                          b1, sizeof (*tr));
     288        8464 :               if (b1->error != node->errors[UDP_ERROR_LENGTH_ERROR])
     289             :                 {
     290        8464 :                   tr->src_port = h1 ? h1->src_port : 0;
     291        8464 :                   tr->dst_port = h1 ? h1->dst_port : 0;
     292        8464 :                   tr->bound = (next1 != UDP_LOCAL_NEXT_ICMP);
     293             :                 }
     294             :             }
     295             : 
     296       30391 :           vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
     297             :                                            to_next, n_left_to_next,
     298             :                                            bi0, bi1, next0, next1);
     299             :         }
     300             : 
     301       27547 :       while (n_left_from > 0 && n_left_to_next > 0)
     302             :         {
     303             :           u32 bi0;
     304             :           vlib_buffer_t *b0;
     305       15809 :           udp_header_t *h0 = 0;
     306             :           u32 i0, next0;
     307             :           u32 advance0;
     308             : 
     309       15809 :           bi0 = from[0];
     310       15809 :           to_next[0] = bi0;
     311       15809 :           from += 1;
     312       15809 :           to_next += 1;
     313       15809 :           n_left_from -= 1;
     314       15809 :           n_left_to_next -= 1;
     315             : 
     316       15809 :           b0 = vlib_get_buffer (vm, bi0);
     317             : 
     318             :           /* ip4/6_local hands us the ip header, not the udp header */
     319       15809 :           if (is_ip4)
     320       15497 :             advance0 = ip4_header_bytes (vlib_buffer_get_current (b0));
     321             :           else
     322         312 :             advance0 = sizeof (ip6_header_t);
     323             : 
     324       15809 :           if (PREDICT_FALSE (b0->current_length < advance0 + sizeof (*h0)))
     325             :             {
     326           0 :               b0->error = node->errors[UDP_ERROR_LENGTH_ERROR];
     327           0 :               next0 = UDP_LOCAL_NEXT_DROP;
     328           0 :               goto trace_x1;
     329             :             }
     330             : 
     331       15809 :           vlib_buffer_advance (b0, advance0);
     332             : 
     333       15809 :           h0 = vlib_buffer_get_current (b0);
     334             : 
     335       15809 :           if (PREDICT_TRUE (clib_net_to_host_u16 (h0->length) <=
     336             :                             vlib_buffer_length_in_chain (vm, b0)))
     337             :             {
     338       15809 :               i0 = sparse_vec_index (next_by_dst_port, h0->dst_port);
     339       15809 :               next0 = vec_elt (next_by_dst_port, i0);
     340             : 
     341       15809 :               if (PREDICT_FALSE ((i0 == SPARSE_VEC_INVALID_INDEX) ||
     342             :                                  next0 == UDP_NO_NODE_SET))
     343             :                 {
     344          35 :                   udp_dispatch_error (node, b0, advance0, is_ip4, &next0);
     345             :                 }
     346             :               else
     347             :                 {
     348       15774 :                   b0->error = node->errors[UDP_ERROR_NONE];
     349             :                   // advance to the payload
     350       15774 :                   vlib_buffer_advance (b0, sizeof (*h0));
     351             :                 }
     352             :             }
     353             :           else
     354             :             {
     355           0 :               b0->error = node->errors[UDP_ERROR_LENGTH_ERROR];
     356           0 :               next0 = UDP_LOCAL_NEXT_DROP;
     357             :             }
     358             : 
     359       15809 :         trace_x1:
     360       15809 :           if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
     361             :             {
     362        1241 :               udp_local_rx_trace_t *tr = vlib_add_trace (vm, node,
     363             :                                                          b0, sizeof (*tr));
     364        1241 :               if (b0->error != node->errors[UDP_ERROR_LENGTH_ERROR])
     365             :                 {
     366        1241 :                   tr->src_port = h0->src_port;
     367        1241 :                   tr->dst_port = h0->dst_port;
     368        1241 :                   tr->bound = (next0 != UDP_LOCAL_NEXT_ICMP);
     369             :                 }
     370             :             }
     371             : 
     372       15809 :           vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
     373             :                                            to_next, n_left_to_next,
     374             :                                            bi0, next0);
     375             :         }
     376             : 
     377       11738 :       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
     378             :     }
     379       11738 :   return from_frame->n_vectors;
     380             : }
     381             : 
     382       13736 : VLIB_NODE_FN (udp4_local_node) (vlib_main_t * vm,
     383             :                                 vlib_node_runtime_t * node,
     384             :                                 vlib_frame_t * from_frame)
     385             : {
     386       11500 :   return udp46_local_inline (vm, node, from_frame, 1 /* is_ip4 */ );
     387             : }
     388             : 
     389        2474 : VLIB_NODE_FN (udp6_local_node) (vlib_main_t * vm,
     390             :                                 vlib_node_runtime_t * node,
     391             :                                 vlib_frame_t * from_frame)
     392             : {
     393         238 :   return udp46_local_inline (vm, node, from_frame, 0 /* is_ip4 */ );
     394             : }
     395             : 
     396             : /* *INDENT-OFF* */
     397      178120 : VLIB_REGISTER_NODE (udp4_local_node) = {
     398             :   .name = "ip4-udp-lookup",
     399             :   /* Takes a vector of packets. */
     400             :   .vector_size = sizeof (u32),
     401             : 
     402             :   .n_errors = UDP_N_ERROR,
     403             :   .error_counters = udp_error_counters,
     404             : 
     405             :   .n_next_nodes = UDP_LOCAL_N_NEXT,
     406             :   .next_nodes = {
     407             :     [UDP_LOCAL_NEXT_PUNT]= "ip4-punt",
     408             :     [UDP_LOCAL_NEXT_DROP]= "ip4-drop",
     409             :     [UDP_LOCAL_NEXT_ICMP]= "ip4-icmp-error",
     410             :   },
     411             : 
     412             :   .format_buffer = format_udp_header,
     413             :   .format_trace = format_udp_rx_trace,
     414             :   .unformat_buffer = unformat_udp_header,
     415             : };
     416             : /* *INDENT-ON* */
     417             : 
     418             : /* *INDENT-OFF* */
     419      178120 : VLIB_REGISTER_NODE (udp6_local_node) = {
     420             :   .name = "ip6-udp-lookup",
     421             :   /* Takes a vector of packets. */
     422             :   .vector_size = sizeof (u32),
     423             : 
     424             :   .n_errors = UDP_N_ERROR,
     425             :   .error_counters = udp_error_counters,
     426             : 
     427             :   .n_next_nodes = UDP_LOCAL_N_NEXT,
     428             :   .next_nodes = {
     429             :     [UDP_LOCAL_NEXT_PUNT]= "ip6-punt",
     430             :     [UDP_LOCAL_NEXT_DROP]= "ip6-drop",
     431             :     [UDP_LOCAL_NEXT_ICMP]= "ip6-icmp-error",
     432             :   },
     433             : 
     434             :   .format_buffer = format_udp_header,
     435             :   .format_trace = format_udp_rx_trace,
     436             :   .unformat_buffer = unformat_udp_header,
     437             : };
     438             : /* *INDENT-ON* */
     439             : 
     440             : #ifndef CLIB_MARCH_VARIANT
     441             : void
     442       18026 : udp_add_dst_port (udp_main_t * um, udp_dst_port_t dst_port,
     443             :                   char *dst_port_name, u8 is_ip4)
     444             : {
     445             :   udp_dst_port_info_t *pi;
     446             :   u32 i;
     447             : 
     448       18026 :   vec_add2 (um->dst_port_infos[is_ip4], pi, 1);
     449       18026 :   i = pi - um->dst_port_infos[is_ip4];
     450             : 
     451       18026 :   pi->name = dst_port_name;
     452       18026 :   pi->dst_port = dst_port;
     453       18026 :   pi->next_index = pi->node_index = ~0;
     454             : 
     455       18026 :   hash_set (um->dst_port_info_by_dst_port[is_ip4], dst_port, i);
     456             : 
     457       18026 :   if (pi->name)
     458       35776 :     hash_set_mem (um->dst_port_info_by_name[is_ip4], pi->name, i);
     459       18026 : }
     460             : 
     461             : void
     462         738 : udp_register_dst_port (vlib_main_t * vm,
     463             :                        udp_dst_port_t dst_port, u32 node_index, u8 is_ip4)
     464             : {
     465         738 :   udp_main_t *um = &udp_main;
     466             :   udp_dst_port_info_t *pi;
     467             :   u16 *n;
     468             : 
     469             :   {
     470         738 :     clib_error_t *error = vlib_call_init_function (vm, udp_local_init);
     471         738 :     if (error)
     472           0 :       clib_error_report (error);
     473             :   }
     474             : 
     475         738 :   pi = udp_get_dst_port_info (um, dst_port, is_ip4);
     476         738 :   if (!pi)
     477             :     {
     478         138 :       udp_add_dst_port (um, dst_port, 0, is_ip4);
     479         138 :       pi = udp_get_dst_port_info (um, dst_port, is_ip4);
     480         138 :       ASSERT (pi);
     481             :     }
     482             : 
     483         738 :   pi->node_index = node_index;
     484        1476 :   pi->next_index = vlib_node_add_next (vm,
     485         461 :                                        is_ip4 ? udp4_local_node.index
     486         277 :                                        : udp6_local_node.index, node_index);
     487             : 
     488             :   /* Setup udp protocol -> next index sparse vector mapping. */
     489         738 :   if (is_ip4)
     490         461 :     n = sparse_vec_validate (um->next_by_dst_port4,
     491             :                              clib_host_to_net_u16 (dst_port));
     492             :   else
     493         277 :     n = sparse_vec_validate (um->next_by_dst_port6,
     494             :                              clib_host_to_net_u16 (dst_port));
     495             : 
     496         738 :   n[0] = pi->next_index;
     497         738 : }
     498             : 
     499             : void
     500         661 : udp_unregister_dst_port (vlib_main_t * vm, udp_dst_port_t dst_port, u8 is_ip4)
     501             : {
     502         661 :   udp_main_t *um = &udp_main;
     503             :   udp_dst_port_info_t *pi;
     504             :   u16 *n;
     505             : 
     506         661 :   pi = udp_get_dst_port_info (um, dst_port, is_ip4);
     507             :   /* Not registered? Fagedaboudit */
     508         661 :   if (!pi)
     509           1 :     return;
     510             : 
     511             :   /* Kill the mapping. Don't bother killing the pi, it may be back. */
     512         660 :   if (is_ip4)
     513         418 :     n = sparse_vec_validate (um->next_by_dst_port4,
     514             :                              clib_host_to_net_u16 (dst_port));
     515             :   else
     516         242 :     n = sparse_vec_validate (um->next_by_dst_port6,
     517             :                              clib_host_to_net_u16 (dst_port));
     518             : 
     519         660 :   n[0] = UDP_NO_NODE_SET;
     520             : }
     521             : 
     522             : u8
     523        3027 : udp_is_valid_dst_port (udp_dst_port_t dst_port, u8 is_ip4)
     524             : {
     525        3027 :   udp_main_t *um = &udp_main;
     526        3027 :   u16 *next_by_dst_port =
     527        3027 :     is_ip4 ? um->next_by_dst_port4 : um->next_by_dst_port6;
     528             :   uword index =
     529        3027 :     sparse_vec_index (next_by_dst_port, clib_host_to_net_u16 (dst_port));
     530        6038 :   return (index != SPARSE_VEC_INVALID_INDEX &&
     531        3011 :           vec_elt (next_by_dst_port, index) != UDP_NO_NODE_SET);
     532             : }
     533             : 
     534             : void
     535           4 : udp_punt_unknown (vlib_main_t * vm, u8 is_ip4, u8 is_add)
     536             : {
     537           4 :   udp_main_t *um = &udp_main;
     538             :   {
     539           4 :     clib_error_t *error = vlib_call_init_function (vm, udp_local_init);
     540           4 :     if (error)
     541           0 :       clib_error_report (error);
     542             :   }
     543             : 
     544           4 :   if (is_ip4)
     545           2 :     um->punt_unknown4 = is_add;
     546             :   else
     547           2 :     um->punt_unknown6 = is_add;
     548           4 : }
     549             : 
     550             : /* Parse a UDP header. */
     551             : uword
     552           0 : unformat_udp_header (unformat_input_t * input, va_list * args)
     553             : {
     554           0 :   u8 **result = va_arg (*args, u8 **);
     555             :   udp_header_t *udp;
     556             :   __attribute__ ((unused)) int old_length;
     557             :   u16 src_port, dst_port;
     558             : 
     559             :   /* Allocate space for IP header. */
     560             :   {
     561             :     void *p;
     562             : 
     563           0 :     old_length = vec_len (*result);
     564           0 :     vec_add2 (*result, p, sizeof (ip4_header_t));
     565           0 :     udp = p;
     566             :   }
     567             : 
     568           0 :   clib_memset (udp, 0, sizeof (udp[0]));
     569           0 :   if (unformat (input, "src-port %d dst-port %d", &src_port, &dst_port))
     570             :     {
     571           0 :       udp->src_port = clib_host_to_net_u16 (src_port);
     572           0 :       udp->dst_port = clib_host_to_net_u16 (dst_port);
     573           0 :       return 1;
     574             :     }
     575           0 :   return 0;
     576             : }
     577             : 
     578             : static void
     579        1118 : udp_setup_node (vlib_main_t * vm, u32 node_index)
     580             : {
     581        1118 :   vlib_node_t *n = vlib_get_node (vm, node_index);
     582        1118 :   pg_node_t *pn = pg_get_node (node_index);
     583             : 
     584        1118 :   n->format_buffer = format_udp_header;
     585        1118 :   n->unformat_buffer = unformat_udp_header;
     586        1118 :   pn->unformat_edit = unformat_pg_udp_header;
     587        1118 : }
     588             : 
     589             : clib_error_t *
     590         559 : udp_local_init (vlib_main_t * vm)
     591             : {
     592         559 :   udp_main_t *um = &udp_main;
     593             :   int i;
     594             : 
     595             :   {
     596             :     clib_error_t *error;
     597         559 :     error = vlib_call_init_function (vm, udp_init);
     598         559 :     if (error)
     599           0 :       clib_error_report (error);
     600             :   }
     601             : 
     602             : 
     603        1677 :   for (i = 0; i < 2; i++)
     604             :     {
     605        1118 :       um->dst_port_info_by_name[i] = hash_create_string (0, sizeof (uword));
     606        1118 :       um->dst_port_info_by_dst_port[i] = hash_create (0, sizeof (uword));
     607             :     }
     608             : 
     609         559 :   udp_setup_node (vm, udp4_local_node.index);
     610         559 :   udp_setup_node (vm, udp6_local_node.index);
     611             : 
     612         559 :   um->punt_unknown4 = 0;
     613         559 :   um->punt_unknown6 = 0;
     614             : 
     615         559 :   um->next_by_dst_port4 = sparse_vec_new
     616             :     ( /* elt bytes */ sizeof (um->next_by_dst_port4[0]),
     617             :      /* bits in index */ BITS (((udp_header_t *) 0)->dst_port));
     618             : 
     619         559 :   um->next_by_dst_port6 = sparse_vec_new
     620             :     ( /* elt bytes */ sizeof (um->next_by_dst_port6[0]),
     621             :      /* bits in index */ BITS (((udp_header_t *) 0)->dst_port));
     622             : 
     623             : #define _(n,s) udp_add_dst_port (um, UDP_DST_PORT_##s, #s, 1 /* is_ip4 */);
     624         559 :   foreach_udp4_dst_port
     625             : #undef _
     626             : #define _(n,s) udp_add_dst_port (um, UDP_DST_PORT_##s, #s, 0 /* is_ip4 */);
     627         559 :     foreach_udp6_dst_port
     628             : #undef _
     629         559 :     ip4_register_protocol (IP_PROTOCOL_UDP, udp4_local_node.index);
     630             :   /* Note: ip6 differs from ip4, UDP is hotwired to ip6-udp-lookup */
     631         559 :   return 0;
     632             : }
     633             : 
     634       17919 : VLIB_INIT_FUNCTION (udp_local_init);
     635             : #endif /* CLIB_MARCH_VARIANT */
     636             : 
     637             : /*
     638             :  * fd.io coding-style-patch-verification: ON
     639             :  *
     640             :  * Local Variables:
     641             :  * eval: (c-set-style "gnu")
     642             :  * End:
     643             :  */

Generated by: LCOV version 1.14