2 * Copyright (c) 2017 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:
7 * http://www.apache.org/licenses/LICENSE-2.0
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.
15 #ifndef __included_vnet_bonding_node_h__
16 #define __included_vnet_bonding_node_h__
18 #include <vlib/vlib.h>
19 #include <vlib/unix/unix.h>
20 #include <vppinfra/format.h>
21 #include <vppinfra/hash.h>
22 #include <vnet/ethernet/ethernet.h>
23 #include <vnet/interface.h>
24 #include <vnet/hash/hash.h>
26 #define LACP_FAST_PERIODIC_TIMER 1.0
27 #define LACP_SHORT_TIMOUT_TIME (LACP_FAST_PERIODIC_TIMER * 3)
28 #define LACP_SLOW_PERIODIC_TIMER 30.0
29 #define LACP_LONG_TIMOUT_TIME (LACP_SLOW_PERIODIC_TIMER * 3)
32 #define MIN(x,y) (((x)<(y))?(x):(y))
35 #define BOND_MODULO_SHORTCUT(a) \
38 #define foreach_bond_mode \
39 _ (1, ROUND_ROBIN, "round-robin") \
40 _ (2, ACTIVE_BACKUP, "active-backup") \
42 _ (4, BROADCAST, "broadcast") \
47 #define _(v, f, s) BOND_MODE_##f = v,
52 /* configurable load-balances */
53 #define foreach_bond_lb \
54 _ (2, L23, "l23", l23) \
55 _ (1, L34 , "l34", l34) \
58 /* load-balance functions implemented in bond-output */
59 #define foreach_bond_lb_algo \
61 _ (1, L34 , "l34", l34) \
62 _ (2, L23, "l23", l23) \
63 _ (3, RR, "round-robin", round_robin) \
64 _ (4, BC, "broadcast", broadcast) \
65 _ (5, AB, "active-backup", active_backup)
69 #define _(v, f, s, p) BOND_LB_##f = v,
72 } bond_load_balance_t;
76 BOND_SEND_GARP_NA = 1,
77 } bond_send_garp_na_process_event_t;
92 } bond_create_if_args_t;
96 /* member's sw_if_index */
98 /* bond's sw_if_index */
105 } bond_add_member_args_t;
113 } bond_detach_member_args_t;
122 } bond_set_intf_weight_args_t;
124 /** BOND interface details struct */
129 u8 interface_name[64];
135 } bond_interface_details_t;
137 /** member interface details struct */
141 u8 interface_name[64];
147 } member_interface_details_t;
149 typedef CLIB_PACKED (struct
153 u16 key; u16 port_priority; u16 port_number;
159 CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
160 u32 buffers[VLIB_FRAME_SIZE];
162 } bond_per_port_queue_t;
166 bond_per_port_queue_t *per_port_queue;
168 } bond_per_thread_data_t;
176 /* the last member index for the rr lb */
177 u32 lb_rr_last_index;
179 /* Real device instance in interface vector */
182 /* Interface ID being shown to user */
188 /* Configured members */
191 /* Members that are in DISTRIBUTING state */
194 lacp_port_info_t partner;
195 lacp_port_info_t actor;
196 u8 individual_aggregator;
198 /* If the flag numa_only is set, it means that only members
199 on local numa node works for lacp mode if have at least one,
200 otherwise it works as usual. */
204 /* How many members on local numa node are there in lacp mode? */
208 uword *port_number_bitmap;
212 clib_spinlock_t lockp;
213 vnet_hash_fn_t hash_func;
218 u8 persistent_hw_address[6];
220 /* neighbor's vlib software interface index */
223 /* Neighbor time-to-live (usually 3s) */
226 /* 1 = interface is configured with long timeout (60s) */
229 /* 1 = debug is on; 0 = debug is off */
232 /* tx packet template id for this neighbor */
233 u8 packet_template_index;
235 /* Info we actually keep about each neighbor */
237 /* Jenkins hash optimization: avoid tlv scan, send short keepalive msg */
238 u8 last_packet_signature_valid;
239 uword last_packet_signature;
241 /* last received lacp packet, for the J-hash optimization */
244 /* last marker packet */
247 /* neighbor vlib hw_if_index */
250 /* weight -- valid only for active backup */
253 /* actor does not initiate the protocol exchange */
256 /* Partner port information */
257 lacp_port_info_t partner;
258 lacp_port_info_t partner_admin;;
260 /* Actor port information */
261 lacp_port_info_t actor;
262 lacp_port_info_t actor_admin;
264 /* Need To Transmit flag */
267 /* Link has been established and Aggregate Port is operable */
270 /* Initialization or reinitialization of the lacp protocol entity */
273 /* Aggregation Port is operating the lacp */
276 /* MUX to indicate to the Selection Logic wait_while_timer expired */
279 /* Selection Logic indicates al Aggregation Ports attached */
282 /* Selection Logic selected an Aggregator */
285 /* RX machine indicates an Aggregation Port in PORT_DISABLED state */
288 /* timer used to detect whether received protocol information has expired */
289 f64 current_while_timer;
291 /* timer used to detect actor churn states */
292 f64 actor_churn_timer;
294 /* time last lacpdu was sent */
295 f64 last_lacpdu_sent_time;
297 /* time last lacpdu was received */
298 f64 last_lacpdu_recd_time;
300 /* time last marker pdu was sent */
301 f64 last_marker_pdu_sent_time;
303 /* time last marker pdu was received */
304 f64 last_marker_pdu_recd_time;
306 /* timer used to generate periodic transmission */
309 /* timer used to detect partner churn states */
310 f64 partner_churn_timer;
312 /* provides hysteresis before performing an aggregation change */
313 f64 wait_while_timer;
315 /* Implemention variables, not in the spec */
321 /* actor admin key */
326 u32 bif_dev_instance;
333 /* good lacp pdu received */
336 /* bad lacp pdu received */
337 u64 bad_pdu_received;
342 /* good marker pdu received */
343 u64 marker_pdu_received;
345 /* bad marker pdu received */
346 u64 marker_bad_pdu_received;
351 /* member is numa node */
355 typedef void (*lacp_enable_disable_func) (vlib_main_t * vm, bond_if_t * bif,
356 member_if_t * mif, u8 enable);
366 /* pool of bonding interfaces */
367 bond_if_t *interfaces;
369 /* record used interface IDs */
372 /* pool of member interfaces */
373 member_if_t *neighbors;
375 /* rapidly find a bond by vlib software interface index */
376 uword *bond_by_sw_if_index;
378 /* convenience variables */
379 vlib_main_t *vlib_main;
380 vnet_main_t *vnet_main;
382 /* lacp plugin is loaded */
383 u8 lacp_plugin_loaded;
385 lacp_enable_disable_func lacp_enable_disable;
387 uword *member_by_sw_if_index;
389 bond_per_thread_data_t *per_thread_data;
391 lacp_stats_t **stats;
394 /* bond packet trace capture */
397 ethernet_header_t ethernet;
399 u32 bond_sw_if_index;
400 } bond_packet_trace_t;
402 typedef u32 (*load_balance_func) (vlib_main_t * vm,
403 vlib_node_runtime_t * node, bond_if_t * bif,
404 vlib_buffer_t * b0, uword member_count);
408 load_balance_func load_balance;
409 } bond_load_balance_func_t;
411 extern vlib_node_registration_t bond_input_node;
412 extern vlib_node_registration_t bond_process_node;
413 extern vnet_device_class_t bond_dev_class;
414 extern bond_main_t bond_main;
416 void bond_disable_collecting_distributing (vlib_main_t * vm,
418 void bond_enable_collecting_distributing (vlib_main_t * vm,
420 u8 *format_bond_interface_name (u8 * s, va_list * args);
422 void bond_set_intf_weight (vlib_main_t * vm,
423 bond_set_intf_weight_args_t * args);
424 void bond_create_if (vlib_main_t * vm, bond_create_if_args_t * args);
425 int bond_delete_if (vlib_main_t * vm, u32 sw_if_index);
426 void bond_add_member (vlib_main_t * vm, bond_add_member_args_t * args);
427 void bond_detach_member (vlib_main_t * vm, bond_detach_member_args_t * args);
428 int bond_dump_ifs (bond_interface_details_t ** out_bondids);
429 int bond_dump_member_ifs (member_interface_details_t ** out_memberids,
430 u32 bond_sw_if_index);
433 unformat_bond_mode (unformat_input_t * input, va_list * args)
435 u8 *r = va_arg (*args, u8 *);
438 #define _(v, f, s) else if (unformat (input, s)) *r = BOND_MODE_##f;
448 format_bond_mode (u8 * s, va_list * args)
450 u32 i = va_arg (*args, u32);
455 #define _(v, f, s) case BOND_MODE_##f: t = (u8 *) s; break;
459 return format (s, "unknown");
461 return format (s, "%s", t);
465 unformat_bond_load_balance (unformat_input_t * input, va_list * args)
467 u8 *r = va_arg (*args, u8 *);
470 #define _(v, f, s, p) else if (unformat (input, s)) *r = BOND_LB_##f;
480 format_bond_load_balance (u8 * s, va_list * args)
482 u32 i = va_arg (*args, u32);
487 #define _(v, f, s, p) case BOND_LB_##f: t = (u8 *) s; break;
491 return format (s, "unknown");
493 return format (s, "%s", t);
497 bond_register_callback (lacp_enable_disable_func func)
499 bond_main_t *bm = &bond_main;
501 bm->lacp_plugin_loaded = 1;
502 bm->lacp_enable_disable = func;
505 static inline bond_if_t *
506 bond_get_bond_if_by_sw_if_index (u32 sw_if_index)
508 bond_main_t *bm = &bond_main;
511 p = hash_get (bm->bond_by_sw_if_index, sw_if_index);
516 return pool_elt_at_index (bm->interfaces, p[0]);
519 static inline bond_if_t *
520 bond_get_bond_if_by_dev_instance (u32 dev_instance)
522 bond_main_t *bm = &bond_main;
524 return pool_elt_at_index (bm->interfaces, dev_instance);
527 static inline member_if_t *
528 bond_get_member_by_sw_if_index (u32 sw_if_index)
530 bond_main_t *bm = &bond_main;
531 member_if_t *mif = 0;
534 if (sw_if_index < vec_len (bm->member_by_sw_if_index))
536 p = bm->member_by_sw_if_index[sw_if_index];
538 mif = pool_elt_at_index (bm->neighbors, p >> 1);
544 #endif /* __included_vnet_bonding_node_h__ */
547 * fd.io coding-style-patch-verification: ON
550 * eval: (c-set-style "gnu")