/*
*------------------------------------------------------------------
* Copyright (c) 2009 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_svm_common_h__
#define __included_svm_common_h__
#include <stdarg.h>
#include <pthread.h>
#include <vppinfra/types.h>
#define SVM_VERSION ((1<<16) | 1) /* set to declare region ready. */
#define SVM_FLAGS_MHEAP (1<<0) /* region contains an mheap */
#define SVM_FLAGS_FILE (1<<1) /* region backed by one or more files */
#define SVM_FLAGS_NODATA (1<<2) /* region will be further subdivided */
#define SVM_FLAGS_NEED_DATA_INIT (1<<3)
#define SVM_PVT_MHEAP_SIZE (128<<10) /* region's private mheap (128k) */
typedef struct svm_region_
{
volatile uword version;
pthread_mutex_t mutex;
pthread_cond_t condvar;
int .highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long *//*
* vrrp.h - vrrp plug-in header file
*
* Copyright 2019-2020 Rubicon Communications, LLC (Netgate)
*
* SPDX-License-Identifier: Apache-2.0
*
*/
#ifndef __included_vrrp_h__
#define __included_vrrp_h__
#include <vnet/vnet.h>
#include <vnet/ip/ip.h>
#include <vnet/ethernet/ethernet.h>
#include <vppinfra/hash.h>
#include <vppinfra/error.h>
/* VRRP configuration */
typedef enum vrrp_vr_flags
{
VRRP_VR_PREEMPT = 0x1,
VRRP_VR_ACCEPT = 0x2,
VRRP_VR_UNICAST = 0x4,
VRRP_VR_IPV6 = 0x8,
} vrrp_vr_flags_t;
typedef struct vrrp_vr_key
{
u32 sw_if_index;
u8 vr_id;
u8 is_ipv6;
} vrrp_vr_key_t;
/* *INDENT-OFF* */
typedef CLIB_PACKED
(struct vrrp4_arp_key {
union {
struct {
u32 sw_if_index;
ip4_address_t addr;
};
u64 as_u64;
};
}) vrrp4_arp_key_t;
/* *INDENT-ON* */
/* *INDENT-OFF* */
typedef CLIB_PACKED
(struct vrrp6_nd_key {
u32 sw_if_index;
ip6_address_t addr;
}) vrrp6_nd_key_t;
/* *INDENT-ON* */
typedef struct vrrp_vr_tracking_if
{
u32 sw_if_index;
u8 priority;
} vrrp_vr_tracking_if_t;
typedef struct vrrp_vr_tracking
{
vrrp_vr_tracking_if_t *interfaces;
u32 interfaces_dec;
} vrrp_vr_tracking_t;
typedef struct vrrp_vr_config
{
u32 sw_if_index;
u8 vr_id;
u8 priority;
u16 adv_interval;
vrrp_vr_flags_t flags;
ip46_address_t *vr_addrs;
ip46_address_t *peer_addrs;
} vrrp_vr_config_t;
#define foreach_vrrp_vr_state \
_(0, INIT, "Initialize") \
_(1, BACKUP, "Backup") \
_(2, MASTER, "Master") \
_(3, INTF_DOWN, "Interface Down")
/* VRRP runtime data */
typedef enum vrrp_vr_state
{
#define _(v,f,n) VRRP_VR_STATE_##f = v,
foreach_vrrp_vr_state
#undef _
} vrrp_vr_state_t;
typedef struct vrrp_vr_runtime
{
vrrp_vr_state_t state;
u16 master_adv_int;
u16 skew;
u16 master_down_int;
mac_address_t mac;
f64 last_sent;
u32 timer_index;
} vrrp_vr_runtime_t;
/* Per-VR data */
typedef struct vrrp_vr
{
vrrp_vr_config_t config;
vrrp_vr_runtime_t runtime;
vrrp_vr_tracking_t tracking;
} vrrp_vr_t;
/* Timers */
typedef enum vrrp_vr_timer_type
{
VRRP_VR_TIMER_ADV,
VRRP_VR_TIMER_MASTER_DOWN,
} vrrp_vr_timer_type_t;
typedef struct vrrp_vr_timer
{
u32 vr_index;
f64 expire_time; /* monotonic, relative to vlib_time_now() */
vrrp_vr_timer_type_t type;
} vrrp_vr_timer_t;
typedef struct
{
/* vectors of vr indices which are configured on this interface
* 0 -> ipv4, 1 -> ipv6 */
u32 *vr_indices[2];
/* vector of VR indices which track the state of this interface
* 0 -> ipv4, 1*/
u32 *tracking_vrs[2];
/* multicast adjacency indices. 0 -> ipv4, 1 -> ipv6 */
adj_index_t mcast_adj_index[2];
/* number of VRs in master state on sw intf. 0 -> ipv4, 1 -> ipv6 */
u8 n_master_vrs[2];
} vrrp_intf_t;
typedef struct
{
/* API message ID base */
u16 msg_id_base;
/* pool of VRs */
vrrp_vr_t *vrs;
/* pool of timers and ordered vector of pool indices */
vrrp_vr_timer_t *vr_timers;
u32 *pending_timers;
/* number of running VRs - don't register for VRRP proto if not running */
u16 n_vrs_started;
/* hash mapping a VR key to a pool entry */
mhash_t vr_index_by_key;
/* hashes mapping sw_if_index and address to a vr index */
uword *vrrp4_arp_lookup;
uword *vrrp6_nd_lookup;
/* vector of interface data indexed by sw_if_index */
vrrp_intf_t *vrrp_intfs;
/* convenience */
vlib_main_t *vlib_main;
vnet_main_t *vnet_main;
ethernet_main_t *ethernet_main;
u32 intf_output_node_idx;
} vrrp_main_t;
extern vrrp_main_t vrrp_main;
extern vlib_node_registration_t vrrp_node;
extern vlib_node_registration_t vrrp_periodic_node;
/* Periodic function events */
#define VRRP_EVENT_VR_TIMER_UPDATE 1
#define VRRP_EVENT_VR_STOP 2
#define VRRP_EVENT_PERIODIC_ENABLE_DISABLE 3
clib_error_t *vrrp_plugin_api_hookup (vlib_main_t * vm);
int vrrp_vr_add_del (u8 is_add, vrrp_vr_config_t * conf);
int vrrp_vr_start_stop (u8 is_start, vrrp_vr_key_t * vr_key);
extern u8 *format_vrrp_vr (u8 * s, va_list * args);
extern u8 *format_vrrp_vr_key (u8 * s, va_list * args);
extern u8 *format_vrrp_vr_state (u8 * s, va_list * args);
extern u8 *format_vrrp_packet_hdr (u8 * s, va_list * args);
void vrrp_vr_timer_set (vrrp_vr_t * vr, vrrp_vr_timer_type_t type);
void vrrp_vr_timer_cancel (vrrp_vr_t * vr);
void vrrp_vr_transition (vrrp_vr_t * vr, vrrp_vr_state_t new_state,
void *data);
int vrrp_vr_set_peers (vrrp_vr_key_t * key, ip46_address_t * peers);
int vrrp_vr_multicast_group_join (vrrp_vr_t * vr);
int vrrp_adv_send (vrrp_vr_t * vr, int shutdown);
int vrrp_garp_or_na_send (vrrp_vr_t * vr);
u16 vrrp_adv_csum (void *l3_hdr, void *payload, u8 is_ipv6, u16 len);
int vrrp_vr_tracking_if_add_del (vrrp_vr_t * vr, u32 sw_if_index,
u8 priority, u8 is_add);
int vrrp_vr_tracking_ifs_add_del (vrrp_vr_t * vr,
vrrp_vr_tracking_if_t * track_ifs,
u8 is_add);
void vrrp_vr_event (vrrp_vr_t * vr, vrrp_vr_state_t new_state);
always_inline void
vrrp_vr_skew_compute (vrrp_vr_t * vr)
{
vrrp_vr_config_t *vrc = &vr->config;
vrrp_vr_runtime_t *vrt = &vr->runtime;
vrt->skew = (((256 - vrc->priority) * vrt->master_adv_int) / 256);
}
always_inline void
vrrp_vr_master_down_compute (vrrp_vr_t * vr)
{
vrrp_vr_runtime_t *vrt = &vr->runtime;
vrt->master_down_int = (3 * vrt->master_adv_int) + vrt->skew;
}
always_inline vrrp_vr_t *
vrrp_vr_lookup (u32 sw_if_index, u8 vr_id, u8 is_ipv6)
{
vrrp_main_t *vmp = &vrrp_main;
vrrp_vr_key_t key;
uword *p;
clib_memset (&key, 0, sizeof (key));
key.sw_if_index = sw_if_index;
key.vr_id = vr_id;
key.is_ipv6 = (is_ipv6 != 0);
p = mhash_get (&vmp->vr_index_by_key, &key);
if (p)
return pool_elt_at_index (vmp->vrs, p[0]);
return 0;
}
always_inline vrrp_vr_t *
vrrp_vr_lookup_index (u32 vr_index)
{
vrrp_main_t *vmp = &vrrp_main;
if (pool_is_free_index (vmp->vrs, vr_index))
return 0;
return pool_elt_at_index (vmp->vrs, vr_index);
}
always_inline u32
vrrp_vr_lookup_address (u32 sw_if_index, u8 is_ipv6, void *addr)
{
vrrp_main_t *vmp = &vrrp_main;
uword *p;
vrrp4_arp_key_t key4;
vrrp6_nd_key_t key6;
if (is_ipv6)
{
key6.sw_if_index = sw_if_index;
key6.addr = ((ip6_address_t *) addr)[0];
p = hash_get_mem (vmp->vrrp6_nd_lookup, &key6);
}
else
{
key4.sw_if_index = sw_if_index;
key4.addr = ((ip4_address_t *) addr)[0];
p = hash_get (vmp->vrrp4_arp_lookup, key4.as_u64);
}
if (p)
return p[0];
return ~0;
}
always_inline vrrp_intf_t *
vrrp_intf_get (u32 sw_if_index)
{
vrrp_main_t *vrm = &vrrp_main;
if (sw_if_index == ~0)
return NULL;
vec_validate (vrm->vrrp_intfs, sw_if_index);
return vec_elt_at_index (vrm->vrrp_intfs, sw_if_index);
}
always_inline int
vrrp_intf_num_vrs (u32 sw_if_index, u8 is_ipv6)
{
vrrp_intf_t *intf = vrrp_intf_get (sw_if_index);
if (intf)
return vec_len (intf->vr_indices[is_ipv6]);
return 0;
}
always_inline u8
vrrp_vr_is_ipv6 (vrrp_vr_t * vr)
{
return ((vr->config.flags & VRRP_VR_IPV6) != 0);
}
always_inline u8
vrrp_vr_is_unicast (vrrp_vr_t * vr)
{
return ((vr->config.flags & VRRP_VR_UNICAST) != 0);
}
always_inline u8
vrrp_vr_is_owner (vrrp_vr_t * vr)
{
return (vr->config.priority == 255);
}
always_inline u8
vrrp_vr_n_vr_addrs (vrrp_vr_t * vr)
{
return vec_len (vr->config.vr_addrs);
}
always_inline u8
vrrp_vr_n_peer_addrs (vrrp_vr_t * vr)
{
return vec_len (vr->config.peer_addrs);
}
always_inline u8
vrrp_vr_accept_mode_enabled (vrrp_vr_t * vr)
{
return ((vr->config.flags & VRRP_VR_ACCEPT) != 0);
}
always_inline u32
vrrp_vr_index (vrrp_vr_t * vr)
{
vrrp_main_t *vmp = &vrrp_main;
return vr - vmp->vrs;
}
always_inline u8
vrrp_vr_priority (vrrp_vr_t * vr)
{
u8 rv;
if (vr->tracking.interfaces_dec < (u32) vr->config.priority)
rv = vr->config.priority - vr->tracking.interfaces_dec;
else
rv = 1;
return rv;
}
#endif /* __included_vrrp_h__ */
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "gnu")
* End:
*/