1cb9cadadSEd Warnicke/*
2cb9cadadSEd Warnicke * Copyright (c) 2015 Cisco and/or its affiliates.
3cb9cadadSEd Warnicke * Licensed under the Apache License, Version 2.0 (the "License");
4cb9cadadSEd Warnicke * you may not use this file except in compliance with the License.
5cb9cadadSEd Warnicke * You may obtain a copy of the License at:
6cb9cadadSEd Warnicke *
7cb9cadadSEd Warnicke *     http://www.apache.org/licenses/LICENSE-2.0
8cb9cadadSEd Warnicke *
9cb9cadadSEd Warnicke * Unless required by applicable law or agreed to in writing, software
10cb9cadadSEd Warnicke * distributed under the License is distributed on an "AS IS" BASIS,
11cb9cadadSEd Warnicke * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12cb9cadadSEd Warnicke * See the License for the specific language governing permissions and
13cb9cadadSEd Warnicke * limitations under the License.
14cb9cadadSEd Warnicke */
15cb9cadadSEd Warnicke/*
16cb9cadadSEd Warnicke * hdlc_node.c: hdlc packet processing
17cb9cadadSEd Warnicke *
18cb9cadadSEd Warnicke * Copyright (c) 2010 Eliot Dresselhaus
19cb9cadadSEd Warnicke *
20cb9cadadSEd Warnicke * Permission is hereby granted, free of charge, to any person obtaining
21cb9cadadSEd Warnicke * a copy of this software and associated documentation files (the
22cb9cadadSEd Warnicke * "Software"), to deal in the Software without restriction, including
23cb9cadadSEd Warnicke * without limitation the rights to use, copy, modify, merge, publish,
24cb9cadadSEd Warnicke * distribute, sublicense, and/or sell copies of the Software, and to
25cb9cadadSEd Warnicke * permit persons to whom the Software is furnished to do so, subject to
26cb9cadadSEd Warnicke * the following conditions:
27cb9cadadSEd Warnicke *
28cb9cadadSEd Warnicke * The above copyright notice and this permission notice shall be
29cb9cadadSEd Warnicke * included in all copies or substantial portions of the Software.
30cb9cadadSEd Warnicke *
31cb9cadadSEd Warnicke *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
32cb9cadadSEd Warnicke *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
33cb9cadadSEd Warnicke *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
34cb9cadadSEd Warnicke *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
35cb9cadadSEd Warnicke *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
36cb9cadadSEd Warnicke *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
37cb9cadadSEd Warnicke *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38cb9cadadSEd Warnicke */
39cb9cadadSEd Warnicke
40cb9cadadSEd Warnicke#include <vlib/vlib.h>
41cb9cadadSEd Warnicke#include <vnet/pg/pg.h>
42cb9cadadSEd Warnicke#include <vnet/hdlc/hdlc.h>
43cb9cadadSEd Warnicke#include <vppinfra/sparse_vec.h>
44cb9cadadSEd Warnicke
45cb9cadadSEd Warnicke#define foreach_hdlc_input_next			\
46cb9cadadSEd Warnicke  _ (PUNT, "error-punt")			\
47cb9cadadSEd Warnicke  _ (DROP, "error-drop")
48cb9cadadSEd Warnicke
49cc42db82SSwarup Nayaktypedef enum
50cc42db82SSwarup Nayak{
51cb9cadadSEd Warnicke#define _(s,n) HDLC_INPUT_NEXT_##s,
52cb9cadadSEd Warnicke  foreach_hdlc_input_next
53cb9cadadSEd Warnicke#undef _
54cc42db82SSwarup Nayak    HDLC_INPUT_N_NEXT,
55cb9cadadSEd Warnicke} hdlc_input_next_t;
56cb9cadadSEd Warnicke
57cc42db82SSwarup Nayaktypedef struct
58cc42db82SSwarup Nayak{
59cb9cadadSEd Warnicke  u8 packet_data[32];
60cb9cadadSEd Warnicke} hdlc_input_trace_t;
61cb9cadadSEd Warnicke
62cc42db82SSwarup Nayakstatic u8 *
63cc42db82SSwarup Nayakformat_hdlc_input_trace (u8 * s, va_list * va)
64cb9cadadSEd Warnicke{
65cb9cadadSEd Warnicke  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *);
66cb9cadadSEd Warnicke  CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *);
67cc42db82SSwarup Nayak  hdlc_input_trace_t *t = va_arg (*va, hdlc_input_trace_t *);
68cb9cadadSEd Warnicke
69cb9cadadSEd Warnicke  s = format (s, "%U", format_hdlc_header, t->packet_data);
70cb9cadadSEd Warnicke
71cb9cadadSEd Warnicke  return s;
72cb9cadadSEd Warnicke}
73cb9cadadSEd Warnicke
74cc42db82SSwarup Nayaktypedef struct
75cc42db82SSwarup Nayak{
76cb9cadadSEd Warnicke  /* Sparse vector mapping hdlc protocol in network byte order
77cb9cadadSEd Warnicke     to next index. */
78cc42db82SSwarup Nayak  u16 *next_by_protocol;
79cb9cadadSEd Warnicke
80cc42db82SSwarup Nayak  u32 *sparse_index_by_next_index;
81cb9cadadSEd Warnicke} hdlc_input_runtime_t;
82cb9cadadSEd Warnicke
83cb9cadadSEd Warnickestatic uword
84cb9cadadSEd Warnickehdlc_input (vlib_main_t * vm,
85cc42db82SSwarup Nayak	    vlib_node_runtime_t * node, vlib_frame_t * from_frame)
86cb9cadadSEd Warnicke{
87cc42db82SSwarup Nayak  hdlc_input_runtime_t *rt = (void *) node->runtime_data;
88cc42db82SSwarup Nayak  u32 n_left_from, next_index, i_next, *from, *to_next;
89cb9cadadSEd Warnicke
90cb9cadadSEd Warnicke  from = vlib_frame_vector_args (from_frame);
91cb9cadadSEd Warnicke  n_left_from = from_frame->n_vectors;
92cb9cadadSEd Warnicke
93cb9cadadSEd Warnicke  if (node->flags & VLIB_NODE_FLAG_TRACE)
94cb9cadadSEd Warnicke    vlib_trace_frame_buffers_only (vm, node,
95cb9cadadSEd Warnicke				   from,
96cb9cadadSEd Warnicke				   n_left_from,
97cb9cadadSEd Warnicke				   sizeof (from[0]),
98cb9cadadSEd Warnicke				   sizeof (hdlc_input_trace_t));
99cb9cadadSEd Warnicke
100cb9cadadSEd Warnicke  next_index = node->cached_next_index;
101cb9cadadSEd Warnicke  i_next = vec_elt (rt->sparse_index_by_next_index, next_index);
102cb9cadadSEd Warnicke
103cb9cadadSEd Warnicke  while (n_left_from > 0)
104cb9cadadSEd Warnicke    {
105cb9cadadSEd Warnicke      u32 n_left_to_next;
106cb9cadadSEd Warnicke
107cc42db82SSwarup Nayak      vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
108cb9cadadSEd Warnicke
109cb9cadadSEd Warnicke      while (n_left_from >= 4 && n_left_to_next >= 2)
110cb9cadadSEd Warnicke	{
111cb9cadadSEd Warnicke	  u32 bi0, bi1;
112cc42db82SSwarup Nayak	  vlib_buffer_t *b0, *b1;
113cc42db82SSwarup Nayak	  hdlc_header_t *h0, *h1;
114cb9cadadSEd Warnicke	  u32 i0, i1, len0, len1, protocol0, protocol1, enqueue_code;
115cb9cadadSEd Warnicke
116cb9cadadSEd Warnicke	  /* Prefetch next iteration. */
117cb9cadadSEd Warnicke	  {
118cc42db82SSwarup Nayak	    vlib_buffer_t *b2, *b3;
119cb9cadadSEd Warnicke
120cb9cadadSEd Warnicke	    b2 = vlib_get_buffer (vm, from[2]);
121cb9cadadSEd Warnicke	    b3 = vlib_get_buffer (vm, from[3]);
122cb9cadadSEd Warnicke
123cb9cadadSEd Warnicke	    vlib_prefetch_buffer_header (b2, LOAD);
124cb9cadadSEd Warnicke	    vlib_prefetch_buffer_header (b3, LOAD);
125cb9cadadSEd Warnicke
126cb9cadadSEd Warnicke	    CLIB_PREFETCH (b2->data, sizeof (h0[0]), LOAD);
127cb9cadadSEd Warnicke	    CLIB_PREFETCH (b3->data, sizeof (h1[0]), LOAD);
128cb9cadadSEd Warnicke	  }
129cb9cadadSEd Warnicke
130cb9cadadSEd Warnicke	  bi0 = from[0];
131cb9cadadSEd Warnicke	  bi1 = from[1];
132cb9cadadSEd Warnicke	  to_next[0] = bi0;
133cb9cadadSEd Warnicke	  to_next[1] = bi1;
134cb9cadadSEd Warnicke	  from += 2;
135cb9cadadSEd Warnicke	  to_next += 2;
136cb9cadadSEd Warnicke	  n_left_to_next -= 2;
137cb9cadadSEd Warnicke	  n_left_from -= 2;
138cb9cadadSEd Warnicke
139cb9cadadSEd Warnicke	  b0 = vlib_get_buffer (vm, bi0);
140cb9cadadSEd Warnicke	  b1 = vlib_get_buffer (vm, bi1);
141cb9cadadSEd Warnicke
14221dc4eceSZhiyong Yang	  h0 = vlib_buffer_get_current (b0);
14321dc4eceSZhiyong Yang	  h1 = vlib_buffer_get_current (b1);
144cb9cadadSEd Warnicke
145cb9cadadSEd Warnicke	  protocol0 = h0->protocol;
146cb9cadadSEd Warnicke	  protocol1 = h1->protocol;
147cb9cadadSEd Warnicke
148cb9cadadSEd Warnicke	  /* Add padding bytes for OSI protocols. */
149cb9cadadSEd Warnicke	  len0 = sizeof (h0[0]);
150cb9cadadSEd Warnicke	  len1 = sizeof (h1[0]);
151cc42db82SSwarup Nayak
152cb9cadadSEd Warnicke	  len0 += protocol0 == clib_host_to_net_u16 (HDLC_PROTOCOL_osi);
153cb9cadadSEd Warnicke	  len1 += protocol1 == clib_host_to_net_u16 (HDLC_PROTOCOL_osi);
154cb9cadadSEd Warnicke
15521dc4eceSZhiyong Yang	  vlib_buffer_advance (b0, len0);
15621dc4eceSZhiyong Yang	  vlib_buffer_advance (b1, len1);
157cb9cadadSEd Warnicke
158cb9cadadSEd Warnicke	  /* Index sparse array with network byte order. */
159cc42db82SSwarup Nayak	  sparse_vec_index2 (rt->next_by_protocol, protocol0, protocol1, &i0,
160cc42db82SSwarup Nayak			     &i1);
161cb9cadadSEd Warnicke
162cc42db82SSwarup Nayak	  b0->error =
163cc42db82SSwarup Nayak	    node->errors[i0 ==
164cc42db82SSwarup Nayak			 SPARSE_VEC_INVALID_INDEX ?
165cc42db82SSwarup Nayak			 HDLC_ERROR_UNKNOWN_PROTOCOL : HDLC_ERROR_NONE];
166cc42db82SSwarup Nayak	  b1->error =
167cc42db82SSwarup Nayak	    node->errors[i1 ==
168cc42db82SSwarup Nayak			 SPARSE_VEC_INVALID_INDEX ?
169cc42db82SSwarup Nayak			 HDLC_ERROR_UNKNOWN_PROTOCOL : HDLC_ERROR_NONE];
170cb9cadadSEd Warnicke
171cc42db82SSwarup Nayak	  enqueue_code = (i0 != i_next) + 2 * (i1 != i_next);
172cb9cadadSEd Warnicke
173cb9cadadSEd Warnicke	  if (PREDICT_FALSE (enqueue_code != 0))
174cb9cadadSEd Warnicke	    {
175cb9cadadSEd Warnicke	      switch (enqueue_code)
176cb9cadadSEd Warnicke		{
177cb9cadadSEd Warnicke		case 1:
178cb9cadadSEd Warnicke		  /* A B A */
179cb9cadadSEd Warnicke		  to_next[-2] = bi1;
180cb9cadadSEd Warnicke		  to_next -= 1;
181cb9cadadSEd Warnicke		  n_left_to_next += 1;
182cc42db82SSwarup Nayak		  vlib_set_next_frame_buffer (vm, node,
183cc42db82SSwarup Nayak					      vec_elt (rt->next_by_protocol,
184cc42db82SSwarup Nayak						       i0), bi0);
185cb9cadadSEd Warnicke		  break;
186cb9cadadSEd Warnicke
187cb9cadadSEd Warnicke		case 2:
188cb9cadadSEd Warnicke		  /* A A B */
189cb9cadadSEd Warnicke		  to_next -= 1;
190cb9cadadSEd Warnicke		  n_left_to_next += 1;
191cc42db82SSwarup Nayak		  vlib_set_next_frame_buffer (vm, node,
192cc42db82SSwarup Nayak					      vec_elt (rt->next_by_protocol,
193cc42db82SSwarup Nayak						       i1), bi1);
194cb9cadadSEd Warnicke		  break;
195cb9cadadSEd Warnicke
196cb9cadadSEd Warnicke		case 3:
197cb9cadadSEd Warnicke		  /* A B B or A B C */
198cb9cadadSEd Warnicke		  to_next -= 2;
199cb9cadadSEd Warnicke		  n_left_to_next += 2;
200cc42db82SSwarup Nayak		  vlib_set_next_frame_buffer (vm, node,
201cc42db82SSwarup Nayak					      vec_elt (rt->next_by_protocol,
202cc42db82SSwarup Nayak						       i0), bi0);
203cc42db82SSwarup Nayak		  vlib_set_next_frame_buffer (vm, node,
204cc42db82SSwarup Nayak					      vec_elt (rt->next_by_protocol,
205cc42db82SSwarup Nayak						       i1), bi1);
206cb9cadadSEd Warnicke		  if (i0 == i1)
207cb9cadadSEd Warnicke		    {
208cb9cadadSEd Warnicke		      vlib_put_next_frame (vm, node, next_index,
209cb9cadadSEd Warnicke					   n_left_to_next);
210cb9cadadSEd Warnicke		      i_next = i1;
211cb9cadadSEd Warnicke		      next_index = vec_elt (rt->next_by_protocol, i_next);
212cc42db82SSwarup Nayak		      vlib_get_next_frame (vm, node, next_index, to_next,
213cc42db82SSwarup Nayak					   n_left_to_next);
214cb9cadadSEd Warnicke		    }
215cb9cadadSEd Warnicke		}
216cb9cadadSEd Warnicke	    }
217cb9cadadSEd Warnicke	}
218cc42db82SSwarup Nayak
219cb9cadadSEd Warnicke      while (n_left_from > 0 && n_left_to_next > 0)
220cb9cadadSEd Warnicke	{
221cb9cadadSEd Warnicke	  u32 bi0;
222cc42db82SSwarup Nayak	  vlib_buffer_t *b0;
223cc42db82SSwarup Nayak	  hdlc_header_t *h0;
224cb9cadadSEd Warnicke	  u32 i0, len0, protocol0;
225cb9cadadSEd Warnicke
226cb9cadadSEd Warnicke	  bi0 = from[0];
227cb9cadadSEd Warnicke	  to_next[0] = bi0;
228cb9cadadSEd Warnicke	  from += 1;
229cb9cadadSEd Warnicke	  to_next += 1;
230cb9cadadSEd Warnicke	  n_left_from -= 1;
231cb9cadadSEd Warnicke	  n_left_to_next -= 1;
232cb9cadadSEd Warnicke
233cb9cadadSEd Warnicke	  b0 = vlib_get_buffer (vm, bi0);
234cb9cadadSEd Warnicke
23521dc4eceSZhiyong Yang	  h0 = vlib_buffer_get_current (b0);
236cb9cadadSEd Warnicke
237cb9cadadSEd Warnicke	  protocol0 = h0->protocol;
238cb9cadadSEd Warnicke
239cb9cadadSEd Warnicke	  /* Add padding bytes for OSI protocols. */
240cb9cadadSEd Warnicke	  len0 = sizeof (h0[0]);
241cb9cadadSEd Warnicke	  len0 += protocol0 == clib_host_to_net_u16 (HDLC_PROTOCOL_osi);
242cb9cadadSEd Warnicke
24321dc4eceSZhiyong Yang	  vlib_buffer_advance (b0, len0);
244cb9cadadSEd Warnicke
245cb9cadadSEd Warnicke	  i0 = sparse_vec_index (rt->next_by_protocol, protocol0);
246cb9cadadSEd Warnicke
247cc42db82SSwarup Nayak	  b0->error =
248cc42db82SSwarup Nayak	    node->errors[i0 ==
249cc42db82SSwarup Nayak			 SPARSE_VEC_INVALID_INDEX ?
250cc42db82SSwarup Nayak			 HDLC_ERROR_UNKNOWN_PROTOCOL : HDLC_ERROR_NONE];
251cc42db82SSwarup Nayak
252cb9cadadSEd Warnicke	  /* Sent packet to wrong next? */
253cb9cadadSEd Warnicke	  if (PREDICT_FALSE (i0 != i_next))
254cb9cadadSEd Warnicke	    {
255cb9cadadSEd Warnicke	      /* Return old frame; remove incorrectly enqueued packet. */
256cb9cadadSEd Warnicke	      vlib_put_next_frame (vm, node, next_index, n_left_to_next + 1);
257cb9cadadSEd Warnicke
258cb9cadadSEd Warnicke	      /* Send to correct next. */
259cb9cadadSEd Warnicke	      i_next = i0;
260cb9cadadSEd Warnicke	      next_index = vec_elt (rt->next_by_protocol, i_next);
261cb9cadadSEd Warnicke	      vlib_get_next_frame (vm, node, next_index,
262cb9cadadSEd Warnicke				   to_next, n_left_to_next);
263cb9cadadSEd Warnicke
264cb9cadadSEd Warnicke	      to_next[0] = bi0;
265cb9cadadSEd Warnicke	      to_next += 1;
266cb9cadadSEd Warnicke	      n_left_to_next -= 1;
267cb9cadadSEd Warnicke	    }
268cb9cadadSEd Warnicke	}
269cb9cadadSEd Warnicke
270cb9cadadSEd Warnicke      vlib_put_next_frame (vm, node, next_index, n_left_to_next);
271cb9cadadSEd Warnicke    }
272cb9cadadSEd Warnicke
273cb9cadadSEd Warnicke  return from_frame->n_vectors;
274cb9cadadSEd Warnicke}
275cb9cadadSEd Warnicke
276cc42db82SSwarup Nayakstatic char *hdlc_error_strings[] = {
277cb9cadadSEd Warnicke#define hdlc_error(n,s) s,
278cb9cadadSEd Warnicke#include "error.def"
279cb9cadadSEd Warnicke#undef hdlc_error
280cb9cadadSEd Warnicke};
281cb9cadadSEd Warnicke
282cc42db82SSwarup Nayak/* *INDENT-OFF* */
283cb9cadadSEd WarnickeVLIB_REGISTER_NODE (hdlc_input_node) = {
284cb9cadadSEd Warnicke  .function = hdlc_input,
285cb9cadadSEd Warnicke  .name = "hdlc-input",
286cb9cadadSEd Warnicke  /* Takes a vector of packets. */
287cb9cadadSEd Warnicke  .vector_size = sizeof (u32),
288cb9cadadSEd Warnicke
289cb9cadadSEd Warnicke  .runtime_data_bytes = sizeof (hdlc_input_runtime_t),
290cb9cadadSEd Warnicke
291cb9cadadSEd Warnicke  .n_errors = HDLC_N_ERROR,
292cb9cadadSEd Warnicke  .error_strings = hdlc_error_strings,
293cb9cadadSEd Warnicke
294cb9cadadSEd Warnicke  .n_next_nodes = HDLC_INPUT_N_NEXT,
295cb9cadadSEd Warnicke  .next_nodes = {
296cb9cadadSEd Warnicke#define _(s,n) [HDLC_INPUT_NEXT_##s] = n,
297cb9cadadSEd Warnicke    foreach_hdlc_input_next
298cb9cadadSEd Warnicke#undef _
299cb9cadadSEd Warnicke  },
300cb9cadadSEd Warnicke
301cb9cadadSEd Warnicke  .format_buffer = format_hdlc_header_with_length,
302cb9cadadSEd Warnicke  .format_trace = format_hdlc_input_trace,
303cb9cadadSEd Warnicke  .unformat_buffer = unformat_hdlc_header,
304cb9cadadSEd Warnicke};
305cc42db82SSwarup Nayak/* *INDENT-ON* */
306cb9cadadSEd Warnicke
307cc42db82SSwarup Nayakstatic clib_error_t *
308cc42db82SSwarup Nayakhdlc_input_runtime_init (vlib_main_t * vm)
309cb9cadadSEd Warnicke{
310cc42db82SSwarup Nayak  hdlc_input_runtime_t *rt;
311cb9cadadSEd Warnicke  rt = vlib_node_get_runtime_data (vm, hdlc_input_node.index);
312cb9cadadSEd Warnicke
313cb9cadadSEd Warnicke  rt->next_by_protocol = sparse_vec_new
314cc42db82SSwarup Nayak    ( /* elt bytes */ sizeof (rt->next_by_protocol[0]),
315cb9cadadSEd Warnicke     /* bits in index */ BITS (((hdlc_header_t *) 0)->protocol));
316cb9cadadSEd Warnicke
317cb9cadadSEd Warnicke  vec_validate (rt->sparse_index_by_next_index, HDLC_INPUT_NEXT_DROP);
318cb9cadadSEd Warnicke  vec_validate (rt->sparse_index_by_next_index, HDLC_INPUT_NEXT_PUNT);
319cb9cadadSEd Warnicke  rt->sparse_index_by_next_index[HDLC_INPUT_NEXT_DROP]
320cb9cadadSEd Warnicke    = SPARSE_VEC_INVALID_INDEX;
321cb9cadadSEd Warnicke  rt->sparse_index_by_next_index[HDLC_INPUT_NEXT_PUNT]
322cb9cadadSEd Warnicke    = SPARSE_VEC_INVALID_INDEX;
323cb9cadadSEd Warnicke
324cb9cadadSEd Warnicke  return 0;
325cb9cadadSEd Warnicke}
326cb9cadadSEd Warnicke
327cc42db82SSwarup Nayakstatic clib_error_t *
328cc42db82SSwarup Nayakhdlc_input_init (vlib_main_t * vm)
329e9f929b5SDamjan Marion{
330e9f929b5SDamjan Marion
331e9f929b5SDamjan Marion  {
332cc42db82SSwarup Nayak    clib_error_t *error = vlib_call_init_function (vm, hdlc_init);
333e9f929b5SDamjan Marion    if (error)
334e9f929b5SDamjan Marion      clib_error_report (error);
335e9f929b5SDamjan Marion  }
336e9f929b5SDamjan Marion
337e9f929b5SDamjan Marion  hdlc_setup_node (vm, hdlc_input_node.index);
338e9f929b5SDamjan Marion  hdlc_input_runtime_init (vm);
339e9f929b5SDamjan Marion
340e9f929b5SDamjan Marion  return 0;
341e9f929b5SDamjan Marion}
342e9f929b5SDamjan Marion
343cb9cadadSEd WarnickeVLIB_INIT_FUNCTION (hdlc_input_init);
344e9f929b5SDamjan MarionVLIB_WORKER_INIT_FUNCTION (hdlc_input_runtime_init);
345cb9cadadSEd Warnicke
346cb9cadadSEd Warnickevoid
347cb9cadadSEd Warnickehdlc_register_input_protocol (vlib_main_t * vm,
348cc42db82SSwarup Nayak			      hdlc_protocol_t protocol, u32 node_index)
349cb9cadadSEd Warnicke{
350cc42db82SSwarup Nayak  hdlc_main_t *em = &hdlc_main;
351cc42db82SSwarup Nayak  hdlc_protocol_info_t *pi;
352cc42db82SSwarup Nayak  hdlc_input_runtime_t *rt;
353cc42db82SSwarup Nayak  u16 *n;
354cb9cadadSEd Warnicke  u32 i;
355cb9cadadSEd Warnicke
356cb9cadadSEd Warnicke  {
357cc42db82SSwarup Nayak    clib_error_t *error = vlib_call_init_function (vm, hdlc_input_init);
358cb9cadadSEd Warnicke    if (error)
359cb9cadadSEd Warnicke      clib_error_report (error);
360cb9cadadSEd Warnicke  }
361cb9cadadSEd Warnicke
362cb9cadadSEd Warnicke  pi = hdlc_get_protocol_info (em, protocol);
363cb9cadadSEd Warnicke  pi->node_index = node_index;
364cc42db82SSwarup Nayak  pi->next_index = vlib_node_add_next (vm, hdlc_input_node.index, node_index);
365cb9cadadSEd Warnicke
366cb9cadadSEd Warnicke  /* Setup hdlc protocol -> next index sparse vector mapping. */
367cb9cadadSEd Warnicke  rt = vlib_node_get_runtime_data (vm, hdlc_input_node.index);
368cc42db82SSwarup Nayak  n =
369cc42db82SSwarup Nayak    sparse_vec_validate (rt->next_by_protocol,
370cc42db82SSwarup Nayak			 clib_host_to_net_u16 (protocol));
371cb9cadadSEd Warnicke  n[0] = pi->next_index;
372cb9cadadSEd Warnicke
373cb9cadadSEd Warnicke  /* Rebuild next index -> sparse index inverse mapping when sparse vector
374cb9cadadSEd Warnicke     is updated. */
375cb9cadadSEd Warnicke  vec_validate (rt->sparse_index_by_next_index, pi->next_index);
376cb9cadadSEd Warnicke  for (i = 1; i < vec_len (rt->next_by_protocol); i++)
377cb9cadadSEd Warnicke    rt->sparse_index_by_next_index[rt->next_by_protocol[i]] = i;
378cb9cadadSEd Warnicke}
379cc42db82SSwarup Nayak
380cc42db82SSwarup Nayak/*
381cc42db82SSwarup Nayak * fd.io coding-style-patch-verification: ON
382cc42db82SSwarup Nayak *
383cc42db82SSwarup Nayak * Local Variables:
384cc42db82SSwarup Nayak * eval: (c-set-style "gnu")
385cc42db82SSwarup Nayak * End:
386cc42db82SSwarup Nayak */
387