LCOV - code coverage report
Current view: top level - plugins/vrrp - vrrp.h (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 46 63 73.0 %
Date: 2023-10-26 01:39:38 Functions: 10 13 76.9 %

          Line data    Source code
       1             : 
       2             : /*
       3             :  * vrrp.h - vrrp plug-in header file
       4             :  *
       5             :  * Copyright 2019-2020 Rubicon Communications, LLC (Netgate)
       6             :  *
       7             :  * SPDX-License-Identifier: Apache-2.0
       8             :  *
       9             :  */
      10             : #ifndef __included_vrrp_h__
      11             : #define __included_vrrp_h__
      12             : 
      13             : #include <vnet/vnet.h>
      14             : #include <vnet/ip/ip.h>
      15             : #include <vnet/ethernet/ethernet.h>
      16             : 
      17             : #include <vppinfra/hash.h>
      18             : #include <vppinfra/error.h>
      19             : 
      20             : /* VRRP configuration */
      21             : typedef enum vrrp_vr_flags
      22             : {
      23             :   VRRP_VR_PREEMPT = 0x1,
      24             :   VRRP_VR_ACCEPT = 0x2,
      25             :   VRRP_VR_UNICAST = 0x4,
      26             :   VRRP_VR_IPV6 = 0x8,
      27             : } vrrp_vr_flags_t;
      28             : 
      29             : typedef struct vrrp_vr_key
      30             : {
      31             :   u32 sw_if_index;
      32             :   u8 vr_id;
      33             :   u8 is_ipv6;
      34             : } vrrp_vr_key_t;
      35             : 
      36             : /* *INDENT-OFF* */
      37             : typedef CLIB_PACKED
      38             : (struct vrrp4_arp_key {
      39             :   union {
      40             :     struct {
      41             :       u32 sw_if_index;
      42             :       ip4_address_t addr;
      43             :     };
      44             :     u64 as_u64;
      45             :   };
      46             : }) vrrp4_arp_key_t;
      47             : /* *INDENT-ON* */
      48             : 
      49             : /* *INDENT-OFF* */
      50             : typedef CLIB_PACKED
      51             : (struct vrrp6_nd_key {
      52             :   u32 sw_if_index;
      53             :   ip6_address_t addr;
      54             : }) vrrp6_nd_key_t;
      55             : /* *INDENT-ON* */
      56             : 
      57             : typedef struct vrrp_vr_tracking_if
      58             : {
      59             :   u32 sw_if_index;
      60             :   u8 priority;
      61             : } vrrp_vr_tracking_if_t;
      62             : 
      63             : typedef struct vrrp_vr_tracking
      64             : {
      65             :   vrrp_vr_tracking_if_t *interfaces;
      66             :   u32 interfaces_dec;
      67             : } vrrp_vr_tracking_t;
      68             : 
      69             : typedef struct vrrp_vr_config
      70             : {
      71             :   u32 sw_if_index;
      72             :   u8 vr_id;
      73             :   u8 priority;
      74             :   u16 adv_interval;
      75             :   vrrp_vr_flags_t flags;
      76             :   ip46_address_t *vr_addrs;
      77             :   ip46_address_t *peer_addrs;
      78             : } vrrp_vr_config_t;
      79             : 
      80             : #define foreach_vrrp_vr_state           \
      81             : _(0, INIT, "Initialize")              \
      82             : _(1, BACKUP, "Backup")                        \
      83             : _(2, MASTER, "Master")                        \
      84             : _(3, INTF_DOWN, "Interface Down")
      85             : 
      86             : /* VRRP runtime data */
      87             : typedef enum vrrp_vr_state
      88             : {
      89             : #define _(v,f,n) VRRP_VR_STATE_##f = v,
      90             :   foreach_vrrp_vr_state
      91             : #undef _
      92             : } vrrp_vr_state_t;
      93             : 
      94             : typedef struct vrrp_vr_runtime
      95             : {
      96             :   vrrp_vr_state_t state;
      97             :   u16 master_adv_int;
      98             :   u16 skew;
      99             :   u16 master_down_int;
     100             :   mac_address_t mac;
     101             :   f64 last_sent;
     102             :   u32 timer_index;
     103             : } vrrp_vr_runtime_t;
     104             : 
     105             : /* Per-VR data */
     106             : typedef struct vrrp_vr
     107             : {
     108             :   vrrp_vr_config_t config;
     109             :   vrrp_vr_runtime_t runtime;
     110             :   vrrp_vr_tracking_t tracking;
     111             :   u32 stat_index;
     112             : } vrrp_vr_t;
     113             : 
     114             : /* Timers */
     115             : typedef enum vrrp_vr_timer_type
     116             : {
     117             :   VRRP_VR_TIMER_ADV,
     118             :   VRRP_VR_TIMER_MASTER_DOWN,
     119             : } vrrp_vr_timer_type_t;
     120             : 
     121             : typedef struct vrrp_vr_timer
     122             : {
     123             :   u32 vr_index;
     124             :   f64 expire_time;              /* monotonic, relative to vlib_time_now() */
     125             :   vrrp_vr_timer_type_t type;
     126             : } vrrp_vr_timer_t;
     127             : 
     128             : typedef struct
     129             : {
     130             :   /* vectors of vr indices which are configured on this interface
     131             :    * 0 -> ipv4, 1 -> ipv6 */
     132             :   u32 *vr_indices[2];
     133             : 
     134             :   /* vector of VR indices which track the state of this interface
     135             :    * 0 -> ipv4, 1*/
     136             :   u32 *tracking_vrs[2];
     137             : 
     138             :   /* multicast adjacency indices. 0 -> ipv4, 1 -> ipv6 */
     139             :   adj_index_t mcast_adj_index[2];
     140             : 
     141             :   /* number of VRs in master state on sw intf. 0 -> ipv4, 1 -> ipv6 */
     142             :   u8 n_master_vrs[2];
     143             : 
     144             : } vrrp_intf_t;
     145             : 
     146             : typedef struct
     147             : {
     148             :   /* API message ID base */
     149             :   u16 msg_id_base;
     150             : 
     151             :   /* pool of VRs */
     152             :   vrrp_vr_t *vrs;
     153             : 
     154             :   /* pool of timers and ordered vector of pool indices */
     155             :   vrrp_vr_timer_t *vr_timers;
     156             :   u32 *pending_timers;
     157             : 
     158             :   /* number of running VRs - don't register for VRRP proto if not running */
     159             :   u16 n_vrs_started;
     160             : 
     161             :   /* hash mapping a VR key to a pool entry */
     162             :   mhash_t vr_index_by_key;
     163             : 
     164             :   /* hashes mapping sw_if_index and address to a vr index */
     165             :   uword *vrrp4_arp_lookup;
     166             :   uword *vrrp6_nd_lookup;
     167             : 
     168             :   /* vector of interface data indexed by sw_if_index */
     169             :   vrrp_intf_t *vrrp_intfs;
     170             : 
     171             :   /* convenience */
     172             :   vlib_main_t *vlib_main;
     173             :   vnet_main_t *vnet_main;
     174             :   ethernet_main_t *ethernet_main;
     175             : 
     176             :   u32 intf_output_node_idx;
     177             : } vrrp_main_t;
     178             : 
     179             : extern vrrp_main_t vrrp_main;
     180             : 
     181             : extern vlib_node_registration_t vrrp_node;
     182             : extern vlib_node_registration_t vrrp_periodic_node;
     183             : 
     184             : /* Periodic function events */
     185             : #define VRRP_EVENT_VR_TIMER_UPDATE 1
     186             : #define VRRP_EVENT_VR_STOP 2
     187             : #define VRRP_EVENT_PERIODIC_ENABLE_DISABLE 3
     188             : 
     189             : /* global error counter types */
     190             : #define foreach_vrrp_err_counter                                              \
     191             :   _ (CHKSUM, 0)                                                               \
     192             :   _ (VERSION, 1)                                                              \
     193             :   _ (VRID, 2)                                                                 \
     194             :   _ (TTL, 3)                                                                  \
     195             :   _ (ADDR_LIST, 4)                                                            \
     196             :   _ (PKT_LEN, 5)
     197             : 
     198             : typedef enum vrrp_err_counter_
     199             : {
     200             : #define _(sym, val) VRRP_ERR_COUNTER_##sym = val,
     201             :   foreach_vrrp_err_counter
     202             : #undef _
     203             : } vrrp_err_counter_t;
     204             : 
     205             : #define VRRP_ERR_COUNTER_MAX 6
     206             : 
     207             : /* per-instance stats */
     208             : #define foreach_vrrp_stat_counter                                             \
     209             :   _ (MASTER_TRANS, 0)                                                         \
     210             :   _ (ADV_SENT, 1)                                                             \
     211             :   _ (ADV_RCVD, 2)                                                             \
     212             :   _ (PRIO0_SENT, 3)                                                           \
     213             :   _ (PRIO0_RCVD, 4)
     214             : 
     215             : typedef enum vrrp_stat_counter_
     216             : {
     217             : #define _(sym, val) VRRP_STAT_COUNTER_##sym = val,
     218             :   foreach_vrrp_stat_counter
     219             : #undef _
     220             : } vrrp_stat_counter_t;
     221             : 
     222             : #define VRRP_STAT_COUNTER_MAX 5
     223             : 
     224             : clib_error_t *vrrp_plugin_api_hookup (vlib_main_t * vm);
     225             : 
     226             : int vrrp_vr_add_del (u8 is_add, vrrp_vr_config_t *conf, index_t *ret_index);
     227             : int vrrp_vr_update (index_t *vrrp_index, vrrp_vr_config_t *vr_conf);
     228             : int vrrp_vr_del (index_t vrrp_index);
     229             : int vrrp_vr_start_stop (u8 is_start, vrrp_vr_key_t * vr_key);
     230             : extern u8 *format_vrrp_vr (u8 * s, va_list * args);
     231             : extern u8 *format_vrrp_vr_key (u8 * s, va_list * args);
     232             : extern u8 *format_vrrp_vr_state (u8 * s, va_list * args);
     233             : extern u8 *format_vrrp_packet_hdr (u8 * s, va_list * args);
     234             : void vrrp_vr_timer_set (vrrp_vr_t * vr, vrrp_vr_timer_type_t type);
     235             : void vrrp_vr_timer_cancel (vrrp_vr_t * vr);
     236             : void vrrp_vr_transition (vrrp_vr_t * vr, vrrp_vr_state_t new_state,
     237             :                          void *data);
     238             : int vrrp_vr_set_peers (vrrp_vr_key_t * key, ip46_address_t * peers);
     239             : int vrrp_vr_multicast_group_join (vrrp_vr_t * vr);
     240             : int vrrp_adv_send (vrrp_vr_t * vr, int shutdown);
     241             : int vrrp_garp_or_na_send (vrrp_vr_t * vr);
     242             : u16 vrrp_adv_csum (void *l3_hdr, void *payload, u8 is_ipv6, u16 len);
     243             : int vrrp_vr_tracking_if_add_del (vrrp_vr_t * vr, u32 sw_if_index,
     244             :                                  u8 priority, u8 is_add);
     245             : int vrrp_vr_tracking_ifs_add_del (vrrp_vr_t * vr,
     246             :                                   vrrp_vr_tracking_if_t * track_ifs,
     247             :                                   u8 is_add);
     248             : void vrrp_vr_event (vrrp_vr_t * vr, vrrp_vr_state_t new_state);
     249             : 
     250             : // stats
     251             : void vrrp_incr_err_counter (vrrp_err_counter_t err_type);
     252             : void vrrp_incr_stat_counter (vrrp_stat_counter_t stat_type, u32 stat_index);
     253             : 
     254             : always_inline void
     255           0 : vrrp_vr_skew_compute (vrrp_vr_t * vr)
     256             : {
     257           0 :   vrrp_vr_config_t *vrc = &vr->config;
     258           0 :   vrrp_vr_runtime_t *vrt = &vr->runtime;
     259             : 
     260           0 :   vrt->skew = (((256 - vrc->priority) * vrt->master_adv_int) / 256);
     261           0 : }
     262             : 
     263             : always_inline void
     264           0 : vrrp_vr_master_down_compute (vrrp_vr_t * vr)
     265             : {
     266           0 :   vrrp_vr_runtime_t *vrt = &vr->runtime;
     267             : 
     268           0 :   vrt->master_down_int = (3 * vrt->master_adv_int) + vrt->skew;
     269           0 : }
     270             : 
     271             : always_inline vrrp_vr_t *
     272           4 : vrrp_vr_lookup (u32 sw_if_index, u8 vr_id, u8 is_ipv6)
     273             : {
     274           4 :   vrrp_main_t *vmp = &vrrp_main;
     275             :   vrrp_vr_key_t key;
     276             :   uword *p;
     277             : 
     278           4 :   clib_memset (&key, 0, sizeof (key));
     279             : 
     280           4 :   key.sw_if_index = sw_if_index;
     281           4 :   key.vr_id = vr_id;
     282           4 :   key.is_ipv6 = (is_ipv6 != 0);
     283             : 
     284           4 :   p = mhash_get (&vmp->vr_index_by_key, &key);
     285           4 :   if (p)
     286           4 :     return pool_elt_at_index (vmp->vrs, p[0]);
     287             : 
     288           0 :   return 0;
     289             : }
     290             : 
     291             : always_inline vrrp_vr_t *
     292           8 : vrrp_vr_lookup_index (u32 vr_index)
     293             : {
     294           8 :   vrrp_main_t *vmp = &vrrp_main;
     295             : 
     296           8 :   if (pool_is_free_index (vmp->vrs, vr_index))
     297           0 :     return 0;
     298             : 
     299           8 :   return pool_elt_at_index (vmp->vrs, vr_index);
     300             : }
     301             : 
     302             : always_inline u32
     303           4 : vrrp_vr_lookup_address (u32 sw_if_index, u8 is_ipv6, void *addr)
     304             : {
     305           4 :   vrrp_main_t *vmp = &vrrp_main;
     306             :   uword *p;
     307             :   vrrp4_arp_key_t key4;
     308             :   vrrp6_nd_key_t key6;
     309             : 
     310           4 :   if (is_ipv6)
     311             :     {
     312           2 :       key6.sw_if_index = sw_if_index;
     313           2 :       key6.addr = ((ip6_address_t *) addr)[0];
     314           2 :       p = hash_get_mem (vmp->vrrp6_nd_lookup, &key6);
     315             :     }
     316             :   else
     317             :     {
     318           2 :       key4.sw_if_index = sw_if_index;
     319           2 :       key4.addr = ((ip4_address_t *) addr)[0];
     320           2 :       p = hash_get (vmp->vrrp4_arp_lookup, key4.as_u64);
     321             :     }
     322             : 
     323           4 :   if (p)
     324           2 :     return p[0];
     325             : 
     326           2 :   return ~0;
     327             : }
     328             : 
     329             : always_inline vrrp_intf_t *
     330       89740 : vrrp_intf_get (u32 sw_if_index)
     331             : {
     332       89740 :   vrrp_main_t *vrm = &vrrp_main;
     333             : 
     334       89740 :   if (sw_if_index == ~0)
     335           0 :     return NULL;
     336             : 
     337       89740 :   vec_validate (vrm->vrrp_intfs, sw_if_index);
     338       89740 :   return vec_elt_at_index (vrm->vrrp_intfs, sw_if_index);
     339             : }
     340             : 
     341             : always_inline int
     342          14 : vrrp_intf_num_vrs (u32 sw_if_index, u8 is_ipv6)
     343             : {
     344          14 :   vrrp_intf_t *intf = vrrp_intf_get (sw_if_index);
     345             : 
     346          14 :   if (intf)
     347          14 :     return vec_len (intf->vr_indices[is_ipv6]);
     348             : 
     349           0 :   return 0;
     350             : }
     351             : 
     352             : always_inline u8
     353          46 : vrrp_vr_is_ipv6 (vrrp_vr_t * vr)
     354             : {
     355          46 :   return ((vr->config.flags & VRRP_VR_IPV6) != 0);
     356             : }
     357             : 
     358             : always_inline u8
     359          10 : vrrp_vr_is_unicast (vrrp_vr_t * vr)
     360             : {
     361          10 :   return ((vr->config.flags & VRRP_VR_UNICAST) != 0);
     362             : }
     363             : 
     364             : always_inline u8
     365           2 : vrrp_vr_is_owner (vrrp_vr_t * vr)
     366             : {
     367           2 :   return (vr->config.priority == 255);
     368             : }
     369             : 
     370             : always_inline u8
     371             : vrrp_vr_n_vr_addrs (vrrp_vr_t * vr)
     372             : {
     373             :   return vec_len (vr->config.vr_addrs);
     374             : }
     375             : 
     376             : always_inline u8
     377             : vrrp_vr_n_peer_addrs (vrrp_vr_t * vr)
     378             : {
     379             :   return vec_len (vr->config.peer_addrs);
     380             : }
     381             : 
     382             : always_inline u8
     383           8 : vrrp_vr_accept_mode_enabled (vrrp_vr_t * vr)
     384             : {
     385           8 :   return ((vr->config.flags & VRRP_VR_ACCEPT) != 0);
     386             : }
     387             : 
     388             : always_inline u32
     389           0 : vrrp_vr_index (vrrp_vr_t * vr)
     390             : {
     391           0 :   vrrp_main_t *vmp = &vrrp_main;
     392             : 
     393           0 :   return vr - vmp->vrs;
     394             : }
     395             : 
     396             : always_inline u8
     397           2 : vrrp_vr_priority (vrrp_vr_t * vr)
     398             : {
     399             :   u8 rv;
     400             : 
     401           2 :   if (vr->tracking.interfaces_dec < (u32) vr->config.priority)
     402           2 :     rv = vr->config.priority - vr->tracking.interfaces_dec;
     403             :   else
     404           0 :     rv = 1;
     405             : 
     406           2 :   return rv;
     407             : }
     408             : 
     409             : #endif /* __included_vrrp_h__ */
     410             : 
     411             : /*
     412             :  * fd.io coding-style-patch-verification: ON
     413             :  *
     414             :  * Local Variables:
     415             :  * eval: (c-set-style "gnu")
     416             :  * End:
     417             :  */

Generated by: LCOV version 1.14