FD.io VPP  v21.01.1
Vector Packet Processing
vrrp_periodic.c
Go to the documentation of this file.
1 /*
2  * vrrp_periodic.c - vrrp plug-in periodic function
3  *
4  * Copyright 2019-2020 Rubicon Communications, LLC (Netgate)
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  *
8  */
9 
10 #include <vlib/vlib.h>
11 #include <vppinfra/error.h>
12 #include <vrrp/vrrp.h>
13 #include <vrrp/vrrp_packet.h>
14 
15 static int
16 vrrp_vr_timer_compare (const void *v1, const void *v2)
17 {
18  vrrp_main_t *vmp = &vrrp_main;
19  const u32 *idx1, *idx2;
20  vrrp_vr_timer_t *timer1, *timer2;
21 
22  idx1 = v1;
23  idx2 = v2;
24 
25  timer1 = pool_elt_at_index (vmp->vr_timers, *idx1);
26  timer2 = pool_elt_at_index (vmp->vr_timers, *idx2);
27 
28  /* don't check equality, they are unlikely to be exactly equal and
29  * if it occurs, it won't matter what order they were in.
30  * sort the list in reverse so we can pick the next timer off the end */
31  if (timer1->expire_time > timer2->expire_time)
32  return -1;
33  else
34  return 1;
35 }
36 
37 static u32
39 {
40  vrrp_main_t *vmp = &vrrp_main;
41  int n_timers;
42 
43  n_timers = vec_len (vmp->pending_timers);
44 
45  if (!n_timers)
46  return ~0;
47 
48  return vec_elt (vmp->pending_timers, n_timers - 1);
49 }
50 
51 /* cancel an existing timer. This could happen because:
52  * - adv timer expired on master. another adv should be scheduled.
53  * - a shutdown event is received
54  * - a master is preempted by a higher priority master
55  * - adv received on backup. master down timer should be rescheduled.
56  */
57 void
59 {
60  vrrp_main_t *vmp = &vrrp_main;
61  u32 *t;
62 
63  /* don't search for a timer that was already canceled or never set */
64  if (vr->runtime.timer_index == ~0)
65  return;
66 
67  /* timers stored in descending order, start at the end of the list */
68  /* vec_foreach_backwards does not deal with 0 pointers, check first */
69  if (vmp->pending_timers)
71  {
72  if (*t == vr->runtime.timer_index)
73  {
74  vec_delete (vmp->pending_timers, 1, t - vmp->pending_timers);
75  break;
76  }
77  }
78 
81 
82  vr->runtime.timer_index = ~0;
83 
86 }
87 
88 void
90 {
91  vrrp_main_t *vmp = &vrrp_main;
93  vrrp_vr_timer_t *timer;
94  f64 now;
95 
96  /* Each VR should be waiting on at most 1 timer at any given time.
97  * If there is already a timer set for this VR, cancel it.
98  */
99  if (vr->runtime.timer_index != ~0)
101 
102  pool_get (vmp->vr_timers, timer);
103  vr->runtime.timer_index = timer - vmp->vr_timers;
104 
105  timer->vr_index = vr - vmp->vrs;
106  timer->type = type;
107 
108  now = vlib_time_now (vm);
109 
110  /* RFC 5798 specifies that timers are in centiseconds, so x / 100.0 */
111  switch (type)
112  {
113  case VRRP_VR_TIMER_ADV:
114  timer->expire_time = now + (vr->config.adv_interval / 100.0);
115  break;
117  timer->expire_time = now + (vr->runtime.master_down_int / 100.0);
118  break;
119  default:
120  /* should never reach here */
121  clib_warning ("Unrecognized VRRP timer type (%d)", type);
122  return;
123  }
124 
126 
128 
131 }
132 
133 void
135 {
136  vrrp_main_t *vmp = &vrrp_main;
137  vrrp_vr_timer_t *timer;
138  vrrp_vr_t *vr;
139 
140  if (pool_is_free_index (vmp->vr_timers, timer_index))
141  {
142  clib_warning ("Timeout on free timer index %u", timer_index);
143  return;
144  }
145 
146  timer = pool_elt_at_index (vmp->vr_timers, timer_index);
147  vr = pool_elt_at_index (vmp->vrs, timer->vr_index);
148 
149  switch (timer->type)
150  {
151  case VRRP_VR_TIMER_ADV:
152  vrrp_adv_send (vr, 0);
154  break;
156  vrrp_vr_transition (vr, VRRP_VR_STATE_MASTER, NULL);
157  break;
158  default:
159  clib_warning ("Unrecognized timer type %d", timer->type);
160  return;
161  }
162 
163 }
164 
165 static uword
168 {
169  vrrp_main_t *pm = &vrrp_main;
170  f64 now;
171  f64 timeout = 10.0;
172  uword *event_data = 0;
173  uword event_type;
174  u32 next_timer = ~0;
175  vrrp_vr_timer_t *timer;
176 
177  while (1)
178  {
179  now = vlib_time_now (vm);
180 
181  if (next_timer == ~0)
182  {
184  }
185  else
186  {
187  timer = pool_elt_at_index (pm->vr_timers, next_timer);
188  timeout = timer->expire_time - now;
189 
191  }
192 
193  event_type = vlib_process_get_events (vm, (uword **) & event_data);
194 
195  switch (event_type)
196  {
197  /* Handle VRRP_EVENT_VR_TIMER_UPDATE */
199  next_timer = vrrp_vr_timer_get_next ();
200  break;
201 
202  /* Handle periodic timeouts */
203  case ~0:
204  vrrp_vr_timer_timeout (next_timer);
205  next_timer = vrrp_vr_timer_get_next ();
206  break;
207  }
208  vec_reset_length (event_data);
209  }
210  return 0;
211 }
212 
213 /* *INDENT-OFF* */
215 {
216  .function = vrrp_periodic_process,
217  .type = VLIB_NODE_TYPE_PROCESS,
218  .name = "vrrp-periodic-process",
219 };
220 /* *INDENT-ON* */
221 
222 /*
223  * fd.io coding-style-patch-verification: ON
224  *
225  * Local Variables:
226  * eval: (c-set-style "gnu")
227  * End:
228  */
u32 timer_index
Definition: vrrp.h:102
static f64 vlib_process_wait_for_event_or_clock(vlib_main_t *vm, f64 dt)
Suspend a cooperative multi-tasking thread Waits for an event, or for the indicated number of seconds...
Definition: node_funcs.h:751
static uword * vlib_process_wait_for_event(vlib_main_t *vm)
Definition: node_funcs.h:656
Definition: vrrp.h:106
vrrp_vr_timer_t * vr_timers
Definition: vrrp.h:154
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:334
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:592
vrrp_vr_t * vrs
Definition: vrrp.h:151
#define vec_foreach_backwards(var, vec)
Vector iterator (reverse)
vlib_main_t * vm
Definition: in2out_ed.c:1580
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:251
#define VRRP_EVENT_VR_TIMER_UPDATE
Definition: vrrp.h:184
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
double f64
Definition: types.h:142
void vrrp_vr_timer_timeout(u32 timer_index)
static uword vlib_process_get_events(vlib_main_t *vm, uword **data_vector)
Return the first event type which has occurred and a vector of per-event data of that type...
Definition: node_funcs.h:579
void vrrp_vr_timer_cancel(vrrp_vr_t *vr)
Definition: vrrp_periodic.c:58
vrrp_vr_config_t config
Definition: vrrp.h:108
unsigned int u32
Definition: types.h:88
u16 master_down_int
Definition: vrrp.h:99
vl_api_fib_path_type_t type
Definition: fib_types.api:123
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:546
static void vlib_process_signal_event(vlib_main_t *vm, uword node_index, uword type_opaque, uword data)
Definition: node_funcs.h:1015
static int vrrp_vr_timer_compare(const void *v1, const void *v2)
Definition: vrrp_periodic.c:16
vrrp_vr_runtime_t runtime
Definition: vrrp.h:109
void vrrp_vr_timer_set(vrrp_vr_t *vr, vrrp_vr_timer_type_t type)
Definition: vrrp_periodic.c:89
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:170
enum vrrp_vr_timer_type vrrp_vr_timer_type_t
#define clib_warning(format, args...)
Definition: error.h:59
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:298
vrrp_main_t vrrp_main
Definition: vrrp.c:25
u32 vr_index
Definition: vrrp.h:122
#define pool_put_index(p, i)
Free pool element with given index.
Definition: pool.h:330
#define vec_delete(V, N, M)
Delete N elements starting at element M.
Definition: vec.h:854
int vrrp_adv_send(vrrp_vr_t *vr, int shutdown)
Definition: vrrp_packet.c:272
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
#define vec_elt(v, i)
Get vector value at index i.
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
u64 uword
Definition: types.h:112
#define vec_sort_with_function(vec, f)
Sort a vector using the supplied element comparison function.
Definition: vec.h:1055
static u32 vrrp_vr_timer_get_next(void)
Definition: vrrp_periodic.c:38
vlib_node_registration_t vrrp_periodic_node
(constructor) VLIB_REGISTER_NODE (vrrp_periodic_node)
u16 adv_interval
Definition: vrrp.h:74
f64 expire_time
Definition: vrrp.h:123
vrrp_vr_timer_type_t type
Definition: vrrp.h:124
static uword vrrp_periodic_process(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f)
u32 * pending_timers
Definition: vrrp.h:155
vlib_main_t * vlib_main
Definition: vrrp.h:171
void vrrp_vr_transition(vrrp_vr_t *vr, vrrp_vr_state_t new_state, void *data)
Definition: vrrp.c:282