docs: Use newer Ubuntu LTS in tutorial
[vpp.git] / src / vnet / interface_funcs.h
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  * interface_funcs.h: VNET interfaces/sub-interfaces exported functions
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 #ifndef included_vnet_interface_funcs_h
41 #define included_vnet_interface_funcs_h
42
43 always_inline vnet_hw_interface_t *
44 vnet_get_hw_interface (vnet_main_t * vnm, u32 hw_if_index)
45 {
46   return pool_elt_at_index (vnm->interface_main.hw_interfaces, hw_if_index);
47 }
48
49 always_inline vnet_hw_interface_t *
50 vnet_get_hw_interface_or_null (vnet_main_t * vnm, u32 hw_if_index)
51 {
52   if (!pool_is_free_index (vnm->interface_main.hw_interfaces, hw_if_index))
53     return pool_elt_at_index (vnm->interface_main.hw_interfaces, hw_if_index);
54   return (NULL);
55 }
56
57 always_inline vnet_sw_interface_t *
58 vnet_get_sw_interface (vnet_main_t * vnm, u32 sw_if_index)
59 {
60   return pool_elt_at_index (vnm->interface_main.sw_interfaces, sw_if_index);
61 }
62
63 always_inline vnet_sw_interface_t *
64 vnet_get_sw_interface_or_null (vnet_main_t * vnm, u32 sw_if_index)
65 {
66   if (!pool_is_free_index (vnm->interface_main.sw_interfaces, sw_if_index))
67     return pool_elt_at_index (vnm->interface_main.sw_interfaces, sw_if_index);
68   return (NULL);
69 }
70
71 always_inline vnet_sw_interface_t *
72 vnet_get_hw_sw_interface (vnet_main_t * vnm, u32 hw_if_index)
73 {
74   vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, hw_if_index);
75   vnet_sw_interface_t *sw = vnet_get_sw_interface (vnm, hw->sw_if_index);
76   ASSERT (sw->type == VNET_SW_INTERFACE_TYPE_HARDWARE);
77   return sw;
78 }
79
80 always_inline vnet_sw_interface_t *
81 vnet_get_sup_sw_interface (vnet_main_t * vnm, u32 sw_if_index)
82 {
83   vnet_sw_interface_t *sw = vnet_get_sw_interface (vnm, sw_if_index);
84   if (sw->type == VNET_SW_INTERFACE_TYPE_SUB ||
85       sw->type == VNET_SW_INTERFACE_TYPE_PIPE ||
86       sw->type == VNET_SW_INTERFACE_TYPE_P2P)
87     sw = vnet_get_sw_interface (vnm, sw->sup_sw_if_index);
88   return sw;
89 }
90
91 always_inline vnet_hw_interface_t *
92 vnet_get_sup_hw_interface (vnet_main_t * vnm, u32 sw_if_index)
93 {
94   vnet_sw_interface_t *sw = vnet_get_sup_sw_interface (vnm, sw_if_index);
95   ASSERT ((sw->type == VNET_SW_INTERFACE_TYPE_HARDWARE) ||
96           (sw->type == VNET_SW_INTERFACE_TYPE_PIPE));
97   return vnet_get_hw_interface (vnm, sw->hw_if_index);
98 }
99
100 always_inline vnet_hw_interface_t *
101 vnet_get_sup_hw_interface_api_visible_or_null (vnet_main_t * vnm,
102                                                u32 sw_if_index)
103 {
104   vnet_sw_interface_t *si;
105   if (PREDICT_FALSE (pool_is_free_index (vnm->interface_main.sw_interfaces,
106                                          sw_if_index)))
107     return NULL;
108   si = vnet_get_sup_sw_interface (vnm, sw_if_index);
109   if (PREDICT_FALSE (si->flags & VNET_SW_INTERFACE_FLAG_HIDDEN))
110     return NULL;
111   ASSERT ((si->type == VNET_SW_INTERFACE_TYPE_HARDWARE) ||
112           (si->type == VNET_SW_INTERFACE_TYPE_PIPE));
113   return vnet_get_hw_interface (vnm, si->hw_if_index);
114 }
115
116 always_inline vnet_hw_interface_class_t *
117 vnet_get_hw_interface_class (vnet_main_t * vnm, u32 hw_class_index)
118 {
119   return vec_elt_at_index (vnm->interface_main.hw_interface_classes,
120                            hw_class_index);
121 }
122
123 always_inline vnet_device_class_t *
124 vnet_get_device_class (vnet_main_t * vnm, u32 dev_class_index)
125 {
126   return vec_elt_at_index (vnm->interface_main.device_classes,
127                            dev_class_index);
128 }
129
130 static inline u8 *
131 vnet_get_sw_interface_tag (vnet_main_t * vnm, u32 sw_if_index)
132 {
133   uword *p;
134   p = hash_get (vnm->interface_tag_by_sw_if_index, sw_if_index);
135   if (p)
136     return ((u8 *) p[0]);
137   return 0;
138 }
139
140 static inline void
141 vnet_set_sw_interface_tag (vnet_main_t * vnm, u8 * tag, u32 sw_if_index)
142 {
143   uword *p;
144   p = hash_get (vnm->interface_tag_by_sw_if_index, sw_if_index);
145   if (p)
146     {
147       u8 *oldtag = (u8 *) p[0];
148       hash_unset (vnm->interface_tag_by_sw_if_index, sw_if_index);
149       vec_free (oldtag);
150     }
151
152   hash_set (vnm->interface_tag_by_sw_if_index, sw_if_index, tag);
153 }
154
155 static inline void
156 vnet_clear_sw_interface_tag (vnet_main_t * vnm, u32 sw_if_index)
157 {
158   uword *p;
159   p = hash_get (vnm->interface_tag_by_sw_if_index, sw_if_index);
160   if (p)
161     {
162       u8 *oldtag = (u8 *) p[0];
163       hash_unset (vnm->interface_tag_by_sw_if_index, sw_if_index);
164       vec_free (oldtag);
165     }
166 }
167
168 /**
169  * Walk return code
170  */
171 typedef enum walk_rc_t_
172 {
173   WALK_STOP,
174   WALK_CONTINUE,
175 } walk_rc_t;
176
177 /**
178  * Call back walk type for walking SW indices on a HW interface
179  */
180 typedef walk_rc_t (*vnet_hw_sw_interface_walk_t) (vnet_main_t * vnm,
181                                                   u32 sw_if_index, void *ctx);
182
183 /**
184  * @brief
185  * Walk the SW interfaces on a HW interface - this is the super
186  * interface and any sub-interfaces.
187  */
188 void vnet_hw_interface_walk_sw (vnet_main_t * vnm,
189                                 u32 hw_if_index,
190                                 vnet_hw_sw_interface_walk_t fn, void *ctx);
191
192 /**
193  * Call back walk type for walking SW indices on a HW interface
194  */
195 typedef walk_rc_t (*vnet_sw_interface_walk_t) (vnet_main_t * vnm,
196                                                vnet_sw_interface_t * si,
197                                                void *ctx);
198
199 /**
200  * @brief
201  * Walk all the SW interfaces in the system.
202  */
203 void vnet_sw_interface_walk (vnet_main_t * vnm,
204                              vnet_sw_interface_walk_t fn, void *ctx);
205
206
207 /**
208  * Call back walk type for walking all HW indices
209  */
210 typedef walk_rc_t (*vnet_hw_interface_walk_t) (vnet_main_t * vnm,
211                                                u32 hw_if_index, void *ctx);
212
213 /**
214  * @brief
215  * Walk all the HW interface
216  */
217 void vnet_hw_interface_walk (vnet_main_t * vnm,
218                              vnet_hw_interface_walk_t fn, void *ctx);
219
220 /* Register a hardware interface instance. */
221 u32 vnet_register_interface (vnet_main_t * vnm,
222                              u32 dev_class_index,
223                              u32 dev_instance,
224                              u32 hw_class_index, u32 hw_instance);
225
226 /**
227  * Set interface output node - for interface registered without its output/tx
228  * nodes created because its VNET_DEVICE_CLASS did not specify any tx_function.
229  * This is typically the case for tunnel interfaces.
230  */
231 void vnet_set_interface_output_node (vnet_main_t * vnm,
232                                      u32 hw_if_index, u32 node_index);
233
234 void vnet_set_interface_l3_output_node (vlib_main_t *vm, u32 sw_if_index,
235                                         u8 *output_node);
236 void vnet_reset_interface_l3_output_node (vlib_main_t *vm, u32 sw_if_index);
237
238 /* Creates a software interface given template. */
239 clib_error_t *vnet_create_sw_interface (vnet_main_t * vnm,
240                                         vnet_sw_interface_t * template,
241                                         u32 * sw_if_index);
242
243 void vnet_delete_hw_interface (vnet_main_t * vnm, u32 hw_if_index);
244 void vnet_delete_sw_interface (vnet_main_t * vnm, u32 sw_if_index);
245 int vnet_sw_interface_is_p2p (vnet_main_t * vnm, u32 sw_if_index);
246 int vnet_sw_interface_is_nbma (vnet_main_t * vnm, u32 sw_if_index);
247
248 always_inline vnet_sw_interface_flags_t
249 vnet_sw_interface_get_flags (vnet_main_t * vnm, u32 sw_if_index)
250 {
251   vnet_sw_interface_t *sw = vnet_get_sw_interface (vnm, sw_if_index);
252   return sw->flags;
253 }
254
255 always_inline uword
256 vnet_sw_interface_is_valid (vnet_main_t * vnm, u32 sw_if_index)
257 {
258   return !pool_is_free_index (vnm->interface_main.sw_interfaces, sw_if_index);
259 }
260
261 always_inline uword
262 vnet_hw_interface_is_valid (vnet_main_t * vnm, u32 hw_if_index)
263 {
264   return !pool_is_free_index (vnm->interface_main.hw_interfaces, hw_if_index);
265 }
266
267
268 always_inline uword
269 vnet_sw_interface_is_admin_up (vnet_main_t * vnm, u32 sw_if_index)
270 {
271   return (vnet_sw_interface_get_flags (vnm, sw_if_index) &
272           VNET_SW_INTERFACE_FLAG_ADMIN_UP) != 0;
273 }
274
275 always_inline uword
276 vnet_swif_is_api_visible (vnet_sw_interface_t * si)
277 {
278   return !(si->flags & VNET_SW_INTERFACE_FLAG_HIDDEN);
279 }
280
281 always_inline uword
282 vnet_sw_interface_is_api_visible (vnet_main_t * vnm, u32 sw_if_index)
283 {
284   vnet_sw_interface_t *si = vnet_get_sw_interface (vnm, sw_if_index);
285   return vnet_swif_is_api_visible (si);
286 }
287
288 always_inline uword
289 vnet_sw_interface_is_api_valid (vnet_main_t * vnm, u32 sw_if_index)
290 {
291   return !pool_is_free_index (vnm->interface_main.sw_interfaces, sw_if_index)
292     && vnet_sw_interface_is_api_visible (vnm, sw_if_index);
293 }
294
295 always_inline const u8 *
296 vnet_sw_interface_get_hw_address (vnet_main_t * vnm, u32 sw_if_index)
297 {
298   vnet_hw_interface_t *hw = vnet_get_sup_hw_interface (vnm, sw_if_index);
299   return hw->hw_address;
300 }
301
302 always_inline uword
303 vnet_hw_interface_get_flags (vnet_main_t * vnm, u32 hw_if_index)
304 {
305   vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, hw_if_index);
306   return hw->flags;
307 }
308
309 always_inline u32
310 vnet_hw_interface_get_mtu (vnet_main_t * vnm, u32 hw_if_index)
311 {
312   vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, hw_if_index);
313   return hw->max_frame_size - hw->frame_overhead;
314 }
315
316 always_inline u32
317 vnet_sw_interface_get_mtu (vnet_main_t * vnm, u32 sw_if_index, vnet_mtu_t af)
318 {
319   vnet_sw_interface_t *sw = vnet_get_sw_interface (vnm, sw_if_index);
320   u32 mtu;
321   mtu = sw->mtu[af] > 0 ? sw->mtu[af] : sw->mtu[VNET_MTU_L3];
322   if (mtu == 0)
323     return 9000;                /* $$$ Deal with interface-types not setting MTU */
324   return mtu;
325 }
326
327 always_inline uword
328 vnet_hw_interface_is_link_up (vnet_main_t * vnm, u32 hw_if_index)
329 {
330   return ((vnet_hw_interface_get_flags (vnm, hw_if_index) &
331            VNET_HW_INTERFACE_FLAG_LINK_UP) != 0);
332 }
333
334 always_inline uword
335 vnet_sw_interface_is_link_up (vnet_main_t * vnm, u32 sw_if_index)
336 {
337   vnet_sw_interface_t *sw = vnet_get_sup_sw_interface (vnm, sw_if_index);
338
339   return (vnet_hw_interface_is_link_up (vnm, sw->hw_if_index));
340 }
341
342 always_inline uword
343 vnet_sw_interface_is_up (vnet_main_t * vnm, u32 sw_if_index)
344 {
345   return (vnet_sw_interface_is_admin_up (vnm, sw_if_index) &&
346           vnet_sw_interface_is_link_up (vnm, sw_if_index));
347 }
348
349 always_inline uword
350 vnet_sw_interface_is_sub (vnet_main_t *vnm, u32 sw_if_index)
351 {
352   vnet_sw_interface_t *sw = vnet_get_sw_interface (vnm, sw_if_index);
353
354   return (sw->sw_if_index != sw->sup_sw_if_index);
355 }
356
357 clib_error_t *vnet_sw_interface_supports_addressing (vnet_main_t *vnm,
358                                                      u32 sw_if_index);
359
360 always_inline vlib_frame_t *
361 vnet_get_frame_to_sw_interface (vnet_main_t * vnm, u32 sw_if_index)
362 {
363   vnet_hw_interface_t *hw = vnet_get_sup_hw_interface (vnm, sw_if_index);
364   return vlib_get_frame_to_node (vlib_get_main (), hw->output_node_index);
365 }
366
367 always_inline void
368 vnet_put_frame_to_sw_interface (vnet_main_t * vnm, u32 sw_if_index,
369                                 vlib_frame_t * f)
370 {
371   vnet_hw_interface_t *hw = vnet_get_sup_hw_interface (vnm, sw_if_index);
372   return vlib_put_frame_to_node (vlib_get_main (), hw->output_node_index, f);
373 }
374
375 always_inline void
376 vnet_hw_interface_set_link_speed (vnet_main_t * vnm, u32 hw_if_index,
377                                   u32 link_speed)
378 {
379   vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, hw_if_index);
380   hw->link_speed = link_speed;
381 }
382
383 /* Change interface flags (e.g. up, down, enable, disable). */
384 clib_error_t *vnet_hw_interface_set_flags (vnet_main_t * vnm, u32 hw_if_index,
385                                            vnet_hw_interface_flags_t flags);
386
387 /* Change interface flags (e.g. up, down, enable, disable). */
388 clib_error_t *vnet_sw_interface_set_flags (vnet_main_t * vnm, u32 sw_if_index,
389                                            vnet_sw_interface_flags_t flags);
390
391 void vnet_sw_interface_admin_up (vnet_main_t * vnm, u32 sw_if_index);
392 void vnet_sw_interface_admin_down (vnet_main_t * vnm, u32 sw_if_index);
393
394 /* Change interface class. */
395 clib_error_t *vnet_hw_interface_set_class (vnet_main_t * vnm, u32 hw_if_index,
396                                            u32 new_hw_class_index);
397
398 /* Redirect rx pkts to node */
399 int vnet_hw_interface_rx_redirect_to_node (vnet_main_t * vnm, u32 hw_if_index,
400                                            u32 node_index);
401
402 void vnet_hw_interface_init_for_class (vnet_main_t * vnm, u32 hw_if_index,
403                                        u32 hw_class_index, u32 hw_instance);
404
405 /* Rename interface */
406 clib_error_t *vnet_rename_interface (vnet_main_t * vnm, u32 hw_if_index,
407                                      char *new_name);
408
409 /* Add/delete secondary interface mac address*/
410 clib_error_t *vnet_hw_interface_add_del_mac_address (vnet_main_t * vnm,
411                                                      u32 hw_if_index,
412                                                      const u8 * mac_address,
413                                                      u8 is_add);
414
415 /* Change interface mac address*/
416 clib_error_t *vnet_hw_interface_change_mac_address (vnet_main_t * vnm,
417                                                     u32 hw_if_index,
418                                                     const u8 * mac_address);
419
420 /* Change rx-mode */
421 clib_error_t *set_hw_interface_change_rx_mode (vnet_main_t * vnm,
422                                                u32 hw_if_index,
423                                                u8 queue_id_valid,
424                                                u32 queue_id,
425                                                vnet_hw_if_rx_mode mode);
426
427 /* Set rx-placement on the interface */
428 clib_error_t *set_hw_interface_rx_placement (u32 hw_if_index, u32 queue_id,
429                                              u32 thread_index, u8 is_main);
430 /* Set tx-queue placement on the interface */
431 int set_hw_interface_tx_queue (u32 hw_if_index, u32 queue_id, uword *bitmap);
432
433 /* Set the Max Frame Size on the HW interface */
434 clib_error_t *vnet_hw_interface_set_max_frame_size (vnet_main_t *vnm,
435                                                     u32 hw_if_index,
436                                                     u32 max_frame_size);
437 /* Set the MTU on the HW interface */
438 clib_error_t *vnet_hw_interface_set_mtu (vnet_main_t *vnm, u32 hw_if_index,
439                                          u32 mtu);
440
441 /* Set the MTU on the SW interface */
442 void vnet_sw_interface_set_mtu (vnet_main_t * vnm, u32 sw_if_index, u32 mtu);
443 void vnet_sw_interface_set_protocol_mtu (vnet_main_t * vnm, u32 sw_if_index,
444                                          u32 mtu[]);
445
446 /* update the unnumbered state of an interface */
447 int vnet_sw_interface_update_unnumbered (u32 sw_if_index, u32 ip_sw_if_index,
448                                          u8 enable);
449
450 int vnet_sw_interface_stats_collect_enable_disable (u32 sw_if_index,
451                                                     u8 enable);
452 void vnet_sw_interface_ip_directed_broadcast (vnet_main_t * vnm,
453                                               u32 sw_if_index, u8 enable);
454
455 /* set interface rss queues */
456 clib_error_t *vnet_hw_interface_set_rss_queues (vnet_main_t * vnm,
457                                                 vnet_hw_interface_t * hi,
458                                                 clib_bitmap_t * bitmap);
459
460 void vnet_hw_if_update_runtime_data (vnet_main_t *vnm, u32 hw_if_index);
461
462 /* Formats sw/hw interface. */
463 format_function_t format_vnet_hw_interface;
464 format_function_t format_vnet_hw_if_rx_mode;
465 format_function_t format_vnet_hw_if_index_name;
466 format_function_t format_vnet_sw_interface;
467 format_function_t format_vnet_sw_interface_name;
468 format_function_t format_vnet_sw_interface_name_override;
469 format_function_t format_vnet_sw_if_index_name;
470 format_function_t format_vnet_sw_interface_flags;
471
472 /* Parses sw/hw interface name -> index. */
473 unformat_function_t unformat_vnet_sw_interface;
474 unformat_function_t unformat_vnet_hw_interface;
475 unformat_function_t unformat_vnet_buffer_flags;
476 unformat_function_t unformat_vnet_buffer_offload_flags;
477
478 /* Parses interface flags (up, down, enable, disable, etc.) */
479 unformat_function_t unformat_vnet_hw_interface_flags;
480 unformat_function_t unformat_vnet_sw_interface_flags;
481
482 /* VLAN tag-rewrite */
483 format_function_t format_vtr;
484
485 /* Node runtime for interface output function. */
486 struct vnet_dev_tx_queue;
487 typedef struct
488 {
489   u32 hw_if_index;
490   u32 sw_if_index;
491   u32 dev_instance;
492   u8 is_deleted;
493   struct vnet_dev_tx_queue *tx_queue;
494 } vnet_interface_output_runtime_t;
495
496 /* Interface output function. */
497 word vnet_sw_interface_compare (vnet_main_t * vnm, uword sw_if_index0,
498                                 uword sw_if_index1);
499 word vnet_hw_interface_compare (vnet_main_t * vnm, uword hw_if_index0,
500                                 uword hw_if_index1);
501
502 typedef enum
503 {
504   VNET_INTERFACE_OUTPUT_NEXT_DROP,
505   VNET_INTERFACE_OUTPUT_NEXT_TX,
506 } vnet_interface_output_next_t;
507
508 typedef enum
509 {
510   VNET_INTERFACE_TX_NEXT_DROP,
511   VNET_INTERFACE_TX_N_NEXT,
512 } vnet_interface_tx_next_t;
513
514 #define VNET_SIMULATED_ETHERNET_TX_NEXT_ETHERNET_INPUT VNET_INTERFACE_TX_N_NEXT
515 #define VNET_SIMULATED_ETHERNET_TX_NEXT_L2_INPUT (VNET_SIMULATED_ETHERNET_TX_NEXT_ETHERNET_INPUT + 1)
516
517 typedef enum
518 {
519   VNET_INTERFACE_OUTPUT_ERROR_INTERFACE_DOWN,
520   VNET_INTERFACE_OUTPUT_ERROR_INTERFACE_DELETED,
521   VNET_INTERFACE_OUTPUT_ERROR_NO_TX_QUEUE,
522 } vnet_interface_output_error_t;
523
524 /* Format for interface output traces. */
525 u8 *format_vnet_interface_output_trace (u8 * s, va_list * va);
526
527 serialize_function_t serialize_vnet_interface_state,
528   unserialize_vnet_interface_state;
529
530 /**
531  * @brief Add buffer (vlib_buffer_t) to the trace
532  *
533  * @param *pm - pcap_main_t
534  * @param *vm - vlib_main_t
535  * @param buffer_index - u32
536  * @param n_bytes_in_trace - u32
537  *
538  */
539 static inline void
540 pcap_add_buffer (pcap_main_t *pm, struct vlib_main_t *vm, u32 buffer_index,
541                  u32 n_bytes_in_trace)
542 {
543   vlib_buffer_t *b = vlib_get_buffer (vm, buffer_index);
544   u32 n = vlib_buffer_length_in_chain (vm, b);
545   i32 n_left = clib_min (n_bytes_in_trace, n);
546   f64 time_now = vlib_time_now (vm);
547   void *d;
548
549   if (PREDICT_TRUE (pm->n_packets_captured < pm->n_packets_to_capture))
550     {
551       time_now += vm->clib_time.init_reference_time;
552       clib_spinlock_lock_if_init (&pm->lock);
553       d = pcap_add_packet (pm, time_now, n_left, n);
554       while (1)
555         {
556           u32 copy_length = clib_min ((u32) n_left, b->current_length);
557           clib_memcpy_fast (d, b->data + b->current_data, copy_length);
558           n_left -= b->current_length;
559           if (n_left <= 0)
560             break;
561           d += b->current_length;
562           ASSERT (b->flags & VLIB_BUFFER_NEXT_PRESENT);
563           b = vlib_get_buffer (vm, b->next_buffer);
564         }
565       clib_spinlock_unlock_if_init (&pm->lock);
566     }
567 }
568
569 typedef struct
570 {
571   vnet_hw_if_caps_t val;
572   vnet_hw_if_caps_t mask;
573 } vnet_hw_if_caps_change_t;
574
575 void vnet_hw_if_change_caps (vnet_main_t *vnm, u32 hw_if_index,
576                              vnet_hw_if_caps_change_t *caps);
577
578 static_always_inline void
579 vnet_hw_if_set_caps (vnet_main_t *vnm, u32 hw_if_index, vnet_hw_if_caps_t caps)
580 {
581   vnet_hw_if_caps_change_t cc = { .val = caps, .mask = caps };
582   vnet_hw_if_change_caps (vnm, hw_if_index, &cc);
583 }
584
585 static_always_inline void
586 vnet_hw_if_unset_caps (vnet_main_t *vnm, u32 hw_if_index,
587                        vnet_hw_if_caps_t caps)
588 {
589   vnet_hw_if_caps_change_t cc = { .val = 0, .mask = caps };
590   vnet_hw_if_change_caps (vnm, hw_if_index, &cc);
591 }
592
593 #endif /* included_vnet_interface_funcs_h */
594
595 /*
596  * fd.io coding-style-patch-verification: ON
597  *
598  * Local Variables:
599  * eval: (c-set-style "gnu")
600  * End:
601  */