summaryrefslogtreecommitdiffstats
path: root/src/vnet/bonding/node.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/vnet/bonding/node.h')
-rw-r--r--src/vnet/bonding/node.h451
1 files changed, 451 insertions, 0 deletions
diff --git a/src/vnet/bonding/node.h b/src/vnet/bonding/node.h
new file mode 100644
index 00000000000..74f3b1a356a
--- /dev/null
+++ b/src/vnet/bonding/node.h
@@ -0,0 +1,451 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef __included_vnet_bonding_node_h__
+#define __included_vnet_bonding_node_h__
+
+#include <vlib/vlib.h>
+#include <vlib/unix/unix.h>
+#include <vppinfra/format.h>
+#include <vppinfra/hash.h>
+#include <vnet/ethernet/ethernet.h>
+#include <vnet/interface.h>
+
+#define LACP_FAST_PERIODIC_TIMER 1.0
+#define LACP_SHORT_TIMOUT_TIME (LACP_FAST_PERIODIC_TIMER * 3)
+#define LACP_SLOW_PERIODIC_TIMER 30.0
+#define LACP_LONG_TIMOUT_TIME (LACP_SLOW_PERIODIC_TIMER * 3)
+
+#ifndef MIN
+#define MIN(x,y) (((x)<(y))?(x):(y))
+#endif
+
+#define foreach_bond_mode \
+ _ (1, ROUND_ROBIN, "round-robin") \
+ _ (2, ACTIVE_BACKUP, "active-backup") \
+ _ (3, XOR, "xor") \
+ _ (4, BROADCAST, "broadcast") \
+ _ (5, LACP, "lacp")
+
+typedef enum
+{
+#define _(v, f, s) BOND_MODE_##f = v,
+ foreach_bond_mode
+#undef _
+} bond_mode_t;
+
+/* configurable load-balances */
+#define foreach_bond_lb \
+ _ (2, L23, "l23", l23) \
+ _ (1, l34 , "l34", l34) \
+ _ (0, L2, "l2", l2)
+
+/* load-balance functions implemented in bond-output */
+#define foreach_bond_lb_algo \
+ _ (0, L2, "l2", l2) \
+ _ (1, l34 , "l34", l34) \
+ _ (2, L23, "l23", l23) \
+ _ (3, RR, "round-robin", round_robin) \
+ _ (4, BC, "broadcast", broadcast) \
+ _ (5, AB, "active-backup", active_backup)
+
+typedef enum
+{
+#define _(v, f, s, p) BOND_LB_##f = v,
+ foreach_bond_lb_algo
+#undef _
+} bond_load_balance_t;
+
+typedef struct
+{
+ u8 hw_addr_set;
+ u8 hw_addr[6];
+ u8 mode;
+ u8 lb;
+ /* return */
+ u32 sw_if_index;
+ int rv;
+ clib_error_t *error;
+} bond_create_if_args_t;
+
+typedef struct
+{
+ /* slave's sw_if_index */
+ u32 slave;
+ /* bond's sw_if_index */
+ u32 group;
+ u8 is_passive;
+ u8 is_long_timeout;
+ /* return */
+ int rv;
+ clib_error_t *error;
+} bond_enslave_args_t;
+
+typedef struct
+{
+ u32 slave;
+ /* return */
+ int rv;
+ clib_error_t *error;
+} bond_detach_slave_args_t;
+
+/** BOND interface details struct */
+typedef struct
+{
+ u32 sw_if_index;
+ u8 interface_name[64];
+ u8 mode;
+ u8 lb;
+ u32 active_slaves;
+ u32 slaves;
+} bond_interface_details_t;
+
+/** slave interface details struct */
+typedef struct
+{
+ u32 sw_if_index;
+ u8 interface_name[64];
+ u8 is_passive;
+ u8 is_long_timeout;
+ u32 active_slaves;
+} slave_interface_details_t;
+
+typedef CLIB_PACKED (struct
+ {
+ u16 system_priority;
+ u8 system[6];
+ u16 key; u16 port_priority; u16 port_number;
+ u8 state;
+ }) lacp_port_info_t;
+
+typedef struct
+{
+ u8 admin_up;
+ u8 mode;
+ u8 lb;
+
+ /* the last slave index for the rr lb */
+ u32 lb_rr_last_index;
+
+ u32 dev_instance;
+ u32 hw_if_index;
+ u32 sw_if_index;
+
+ /* Configured slaves */
+ u32 *slaves;
+
+ /* Slaves that are in DISTRIBUTING state */
+ u32 *active_slaves;
+
+ /* rapidly find an active slave */
+ uword *active_slave_by_sw_if_index;
+
+ lacp_port_info_t partner;
+ lacp_port_info_t actor;
+ u8 individual_aggregator;
+
+ u32 group;
+ uword *port_number_bitmap;
+ u8 use_custom_mac;
+ u8 hw_address[6];
+} bond_if_t;
+
+typedef struct
+{
+ u8 persistent_hw_address[6];
+
+ /* neighbor's vlib software interface index */
+ u32 sw_if_index;
+
+ /* Neighbor time-to-live (usually 3s) */
+ f32 ttl_in_seconds;
+
+ /* 1 = interface is configured with long timeout (60s) */
+ u8 is_long_timeout;
+
+ /* 1 = debug is on; 0 = debug is off */
+ u8 debug;
+
+ /* tx packet template id for this neighbor */
+ u8 packet_template_index;
+
+ /* Info we actually keep about each neighbor */
+
+ /* Jenkins hash optimization: avoid tlv scan, send short keepalive msg */
+ u8 last_packet_signature_valid;
+ uword last_packet_signature;
+
+ /* last received lacp packet, for the J-hash optimization */
+ u8 *last_rx_pkt;
+
+ /* last marker packet */
+ u8 *last_marker_pkt;
+
+ /* neighbor vlib hw_if_index */
+ u32 hw_if_index;
+
+ /* actor does not initiate the protocol exchange */
+ u8 is_passive;
+
+ /* Partner port information */
+ lacp_port_info_t partner;
+ lacp_port_info_t partner_admin;;
+
+ /* Partner port information */
+ lacp_port_info_t actor;
+ lacp_port_info_t actor_admin;
+
+ /* Need To Transmit flag */
+ u8 ntt;
+
+ /* Link has been established and Aggregate Port is operable */
+ u8 port_enabled;
+
+ /* Initialization or reinitialization of the lacp protocol entity */
+ u8 begin;
+
+ /* Aggregation Port is operating the lacp */
+ u8 lacp_enabled;
+
+ /* MUX to indicate to the Selection Logic wait_while_timer expired */
+ u8 ready_n;
+
+ /* Selection Logic indicates al Aggregation Ports attached */
+ u8 ready;
+
+ /* Selection Logic selected an Aggregator */
+ int selected;
+
+ /* RX machine indicates an Aggregation Port in PORT_DISABLED state */
+ u8 port_moved;
+
+ /* timer used to detect whether received protocol information has expired */
+ f64 current_while_timer;
+
+ /* timer used to detect actor churn states */
+ f64 actor_churn_timer;
+
+ /* time last lacpdu was sent */
+ f64 last_lacpdu_time;
+
+ /* timer used to generate periodic transmission */
+ f64 periodic_timer;
+
+ /* timer used to detect partner churn states */
+ f64 partner_churn_timer;
+
+ /* provides hysteresis before performing an aggregation change */
+ f64 wait_while_timer;
+
+ /* Implemention variables, not in the spec */
+ int rx_state;
+ int tx_state;
+ int mux_state;
+ int ptx_state;
+
+ /* actor admin key */
+ u32 group;
+
+ u32 marker_tx_id;
+
+ u32 bif_dev_instance;
+
+ u8 loopback_port;
+
+ /* bond mode */
+ u8 mode;
+
+ clib_spinlock_t lockp;
+} slave_if_t;
+
+typedef void (*lacp_enable_disable_func) (vlib_main_t * vm, bond_if_t * bif,
+ slave_if_t * sif, u8 enable);
+
+typedef struct
+{
+ /* pool of bonding interfaces */
+ bond_if_t *interfaces;
+
+ /* pool of lacp neighbors */
+ slave_if_t *neighbors;
+
+ /* rapidly find a neighbor by vlib software interface index */
+ uword *neighbor_by_sw_if_index;
+
+ /* rapidly find a bond by vlib software interface index */
+ uword *bond_by_sw_if_index;
+
+ /* convenience variables */
+ vlib_main_t *vlib_main;
+ vnet_main_t *vnet_main;
+
+ /* lacp plugin is loaded */
+ u8 lacp_plugin_loaded;
+
+ lacp_enable_disable_func lacp_enable_disable;
+} bond_main_t;
+
+/* bond packet trace capture */
+typedef struct
+{
+ ethernet_header_t ethernet;
+ u32 sw_if_index;
+ u32 bond_sw_if_index;
+} bond_packet_trace_t;
+
+typedef u32 (*load_balance_func) (vlib_main_t * vm,
+ vlib_node_runtime_t * node, bond_if_t * bif,
+ vlib_buffer_t * b0);
+
+typedef struct
+{
+ load_balance_func load_balance;
+} bond_load_balance_func_t;
+
+extern vlib_node_registration_t bond_input_node;
+extern vnet_device_class_t bond_dev_class;
+extern bond_main_t bond_main;
+
+void bond_disable_collecting_distributing (vlib_main_t * vm,
+ slave_if_t * sif);
+void bond_enable_collecting_distributing (vlib_main_t * vm, slave_if_t * sif);
+u8 *format_bond_interface_name (u8 * s, va_list * args);
+
+void bond_create_if (vlib_main_t * vm, bond_create_if_args_t * args);
+int bond_delete_if (vlib_main_t * vm, u32 sw_if_index);
+void bond_enslave (vlib_main_t * vm, bond_enslave_args_t * args);
+void bond_detach_slave (vlib_main_t * vm, bond_detach_slave_args_t * args);
+int bond_dump_ifs (bond_interface_details_t ** out_bondids);
+int bond_dump_slave_ifs (slave_interface_details_t ** out_slaveids,
+ u32 bond_sw_if_index);
+
+static inline uword
+unformat_bond_mode (unformat_input_t * input, va_list * args)
+{
+ u8 *r = va_arg (*args, u8 *);
+
+ if (0);
+#define _(v, f, s) else if (unformat (input, s)) *r = BOND_MODE_##f;
+ foreach_bond_mode
+#undef _
+ else
+ return 0;
+
+ return 1;
+}
+
+static inline u8 *
+format_bond_mode (u8 * s, va_list * args)
+{
+ u32 i = va_arg (*args, u32);
+ u8 *t = 0;
+
+ switch (i)
+ {
+#define _(v, f, s) case BOND_MODE_##f: t = (u8 *) s; break;
+ foreach_bond_mode
+#undef _
+ default:
+ return format (s, "unknown");
+ }
+ return format (s, "%s", t);
+}
+
+static inline uword
+unformat_bond_load_balance (unformat_input_t * input, va_list * args)
+{
+ u8 *r = va_arg (*args, u8 *);
+
+ if (0);
+#define _(v, f, s, p) else if (unformat (input, s)) *r = BOND_LB_##f;
+ foreach_bond_lb
+#undef _
+ else
+ return 0;
+
+ return 1;
+}
+
+static inline u8 *
+format_bond_load_balance (u8 * s, va_list * args)
+{
+ u32 i = va_arg (*args, u32);
+ u8 *t = 0;
+
+ switch (i)
+ {
+#define _(v, f, s, p) case BOND_LB_##f: t = (u8 *) s; break;
+ foreach_bond_lb_algo
+#undef _
+ default:
+ return format (s, "unknown");
+ }
+ return format (s, "%s", t);
+}
+
+static inline void
+bond_register_callback (lacp_enable_disable_func func)
+{
+ bond_main_t *bm = &bond_main;
+
+ bm->lacp_plugin_loaded = 1;
+ bm->lacp_enable_disable = func;
+}
+
+static inline bond_if_t *
+bond_get_master_by_sw_if_index (u32 sw_if_index)
+{
+ bond_main_t *bm = &bond_main;
+ uword *p;
+
+ p = hash_get (bm->bond_by_sw_if_index, sw_if_index);
+ if (!p)
+ {
+ return 0;
+ }
+ return pool_elt_at_index (bm->interfaces, p[0]);
+}
+
+static inline bond_if_t *
+bond_get_master_by_dev_instance (u32 dev_instance)
+{
+ bond_main_t *bm = &bond_main;
+
+ return pool_elt_at_index (bm->interfaces, dev_instance);
+}
+
+static inline slave_if_t *
+bond_get_slave_by_sw_if_index (u32 sw_if_index)
+{
+ bond_main_t *bm = &bond_main;
+ slave_if_t *sif = 0;
+ uword *p;
+
+ p = hash_get (bm->neighbor_by_sw_if_index, sw_if_index);
+ if (p)
+ {
+ sif = pool_elt_at_index (bm->neighbors, p[0]);
+ }
+ return sif;
+}
+
+#endif /* __included_vnet_bonding_node_h__ */
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */