FD.io VPP  v19.04.4-rc0-5-ge88582fac
Vector Packet Processing
igmp_timer.c
Go to the documentation of this file.
1 /*
2  *------------------------------------------------------------------
3  * Copyright (c) 2017 Cisco and/or its affiliates.
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *------------------------------------------------------------------
16  */
17 
18 #include <igmp/igmp_timer.h>
19 #include <igmp/igmp.h>
20 
21 /**
22  * Default timer values as per RFC
23  */
24 
26  [IGMP_TIMER_QUERY] = 60,
27  [IGMP_TIMER_SRC] = (3 * 60),
28  [IGMP_TIMER_LEAVE] = 60,
29  [IGMP_TIMER_REPORT_INTERVAL] = 1,
30 };
31 
32 #define IGMP_N_TIMERS (IGMP_TIMER_REPORT_INTERVAL+1)
33 
34 /**
35  * Timer
36  */
37 typedef struct igmp_timer_t_
38 {
39  /** Expiration timer */
41 
42  /** Call-back function to invoke on expiry */
44 
45  /** index of the object that scheduled the timer */
47 
48  /** Data registered by the client and passed back when the timer expires */
49  void *data;
50 } igmp_timer_t;
51 
52 enum
53 {
56 
57 /**
58  * pool of timers
59  */
61 
62 /**
63  * Vector of pending timers
64  */
66 
67 u32
69 {
70  ASSERT (t < IGMP_N_TIMERS);
71  return (igmp_default_timer_values[t]);
72 }
73 
74 void
76 {
77  ASSERT (t < IGMP_N_TIMERS);
79 }
80 
81 
82 static int
83 igmp_timer_compare (const void *_v1, const void *_v2)
84 {
85  const u32 *i1 = _v1, *i2 = _v2;
86  const igmp_timer_t *t1, *t2;
87  f64 dt;
88 
89  t1 = pool_elt_at_index (timer_pool, *i1);
90  t2 = pool_elt_at_index (timer_pool, *i2);
91 
92  dt = t2->exp_time - t1->exp_time;
93 
94  return (dt < 0 ? -1 : (dt > 0 ? +1 : 0));
95 }
96 
97 /** \brief igmp get next timer
98  @param im - igmp main
99 
100  Get next timer.
101 */
102 u32
104 {
105  if (0 == vec_len (pending_timers))
106  return (IGMP_TIMER_ID_INVALID);
107 
108  return (pending_timers[vec_len (pending_timers) - 1]);
109 }
110 
111 void *
113 {
114  igmp_timer_t *timer;
115 
116  timer = pool_elt_at_index (timer_pool, tid);
117 
118  return (timer->data);
119 }
120 
121 void
123 {
124  igmp_timer_t *timer;
125 
126  timer = pool_elt_at_index (timer_pool, tid);
127 
128  timer->data = data;
129 }
130 
131 int
133 {
134  return (IGMP_TIMER_ID_INVALID == tid);
135 }
136 
137 /** \brief igmp timer process
138  @param vm - vlib main
139  @param rt - vlib runtime node
140  @param f - vlib frame
141 
142  Handle igmp timers.
143 */
144 static uword
146  vlib_frame_t * f)
147 {
148  uword *event_data = 0, event_type;
149  igmp_timer_id_t tid;
150  igmp_timer_t *timer;
151 
152  tid = IGMP_TIMER_ID_INVALID;
153 
154  while (1)
155  {
156  /* suspend util timer expires */
157  if (IGMP_TIMER_ID_INVALID != tid)
158  {
159  timer = pool_elt_at_index (timer_pool, tid);
161  (vm, timer->exp_time - vlib_time_now (vm));
162  }
163  else
165 
166  event_type = vlib_process_get_events (vm, &event_data);
167  vec_reset_length (event_data);
168 
169  if (event_type == IGMP_PROCESS_EVENT_UPDATE_TIMER)
170  goto next_timer;
171 
172  /* timer expired */
173  ASSERT (tid != IGMP_TIMER_ID_INVALID);
174 
175  timer = pool_elt_at_index (timer_pool, tid);
176  ASSERT (timer->func != NULL);
177  timer->func (timer->obj, timer->data);
178 
179  next_timer:
180  tid = igmp_get_next_timer ();
181  }
182  return 0;
183 }
184 
185 /* *INDENT-OFF* */
187 {
188  .function = igmp_timer_process,
189  .type = VLIB_NODE_TYPE_PROCESS,
190  .name = "igmp-timer-process",
191  .n_next_nodes = 0,
192 };
193 /* *INDENT-ON* */
194 
197 {
198  igmp_timer_t *timer;
199  vlib_main_t *vm;
200 
201  ASSERT (fn);
202 
203  vm = vlib_get_main ();
204  pool_get (timer_pool, timer);
205 
206  timer->exp_time = vlib_time_now (vm) + when;
207  timer->obj = obj;
208  timer->func = fn;
209  timer->data = data;
210 
211  vec_add1 (pending_timers, timer - timer_pool);
212 
214 
217 
218  return (timer - timer_pool);
219 }
220 
221 void
223 {
224  if (IGMP_TIMER_ID_INVALID == *tid)
225  return;
227  pool_put_index (timer_pool, *tid);
228  *tid = IGMP_TIMER_ID_INVALID;
229 
233 }
234 
235 u8 *
236 format_igmp_timer_id (u8 * s, va_list * args)
237 {
238  igmp_timer_id_t tid = va_arg (*args, igmp_timer_id_t);
239  igmp_timer_t *timer;
240 
241  if (IGMP_TIMER_ID_INVALID == tid)
242  {
243  s = format (s, "not-running");
244  }
245  else
246  {
247  timer = pool_elt_at_index (timer_pool, tid);
248 
249  s =
250  format (s, "[expires-in:%f]",
251  timer->exp_time - vlib_time_now (vlib_get_main ()));
252  }
253 
254  return (s);
255 }
256 
257 /*
258  * fd.io coding-style-patch-verification: ON
259  *
260  * Local Variables:
261  * eval: (c-set-style "gnu")
262  * End:
263  */
enum igmp_timer_type_t_ igmp_timer_type_t
int igmp_timer_is_running(igmp_timer_id_t tid)
Definition: igmp_timer.c:132
static igmp_timer_type_t igmp_default_timer_values[]
Default timer values as per RFC.
Definition: igmp_timer.c:25
void * data
Data registered by the client and passed back when the timer expires.
Definition: igmp_timer.c:49
igmp_timer_function_t func
Call-back function to invoke on expiry.
Definition: igmp_timer.c:43
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:673
void igmp_timer_retire(igmp_timer_id_t *tid)
Definition: igmp_timer.c:222
static uword * vlib_process_wait_for_event(vlib_main_t *vm)
Definition: node_funcs.h:593
static u32 * pending_timers
Vector of pending timers.
Definition: igmp_timer.c:65
static int igmp_timer_compare(const void *_v1, const void *_v2)
Definition: igmp_timer.c:83
#define NULL
Definition: clib.h:58
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:255
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:522
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:236
unsigned char u8
Definition: types.h:56
igmp_timer_id_t igmp_timer_schedule(f64 when, u32 obj, igmp_timer_function_t fn, void *data)
Schedule a timer to expire in &#39;when&#39; seconds.
Definition: igmp_timer.c:196
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
double f64
Definition: types.h:142
u32 igmp_timer_type_get(igmp_timer_type_t t)
Definition: igmp_timer.c:68
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:516
void * igmp_timer_get_data(igmp_timer_id_t tid)
Definition: igmp_timer.c:112
unsigned int u32
Definition: types.h:88
#define vec_search(v, E)
Search a vector for the index of the entry that matches.
Definition: vec.h:940
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:514
#define IGMP_N_TIMERS
Definition: igmp_timer.c:32
static void vlib_process_signal_event(vlib_main_t *vm, uword node_index, uword type_opaque, uword data)
Definition: node_funcs.h:934
u32 igmp_timer_id_t
The id of a running timer.
Definition: igmp_timer.h:26
#define vec_del1(v, i)
Delete the element at index I.
Definition: vec.h:804
void igmp_timer_type_set(igmp_timer_type_t t, u32 v)
Definition: igmp_timer.c:75
u32 obj
index of the object that scheduled the timer
Definition: igmp_timer.c:46
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
vlib_main_t * vm
Definition: buffer.c:312
void igmp_timer_set_data(igmp_timer_id_t tid, void *data)
Definition: igmp_timer.c:122
static uword igmp_timer_process(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f)
igmp timer process
Definition: igmp_timer.c:145
#define IGMP_TIMER_ID_INVALID
Definition: igmp_timer.h:28
#define pool_put_index(p, i)
Free pool element with given index.
Definition: pool.h:311
#define ASSERT(truth)
vlib_node_registration_t igmp_timer_process_node
(constructor) VLIB_REGISTER_NODE (igmp_timer_process_node)
Definition: igmp_timer.c:186
void(* igmp_timer_function_t)(u32 obj, void *data)
A call-back function invoked when a timer expires;.
Definition: igmp_timer.h:35
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
u32 igmp_get_next_timer(void)
igmp get next timer
Definition: igmp_timer.c:103
u8 * format_igmp_timer_id(u8 *s, va_list *args)
Definition: igmp_timer.c:236
Timer.
Definition: igmp_timer.c:37
#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:980
enum @448 igmp_process_event_t
static igmp_timer_t * timer_pool
pool of timers
Definition: igmp_timer.c:60
f64 exp_time
Expiration timer.
Definition: igmp_timer.c:40
struct igmp_timer_t_ igmp_timer_t
Timer.