FD.io VPP  v19.08-27-gf4dcae4
Vector Packet Processing
lb.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <lb/lb.h>
17 #include <vnet/plugin/plugin.h>
18 #include <vpp/app/version.h>
19 #include <vnet/api_errno.h>
20 #include <vnet/udp/udp.h>
21 #include <vppinfra/lock.h>
22 
23 //GC runs at most once every so many seconds
24 #define LB_GARBAGE_RUN 60
25 
26 //After so many seconds. It is assumed that inter-core race condition will not occur.
27 #define LB_CONCURRENCY_TIMEOUT 10
28 
30 
31 #define lb_get_writer_lock() clib_spinlock_lock (&lb_main.writer_lock)
32 #define lb_put_writer_lock() clib_spinlock_unlock (&lb_main.writer_lock)
33 
34 static void lb_as_stack (lb_as_t *as);
35 
36 
37 const static char * const lb_dpo_gre4_ip4[] = { "lb4-gre4" , NULL };
38 const static char * const lb_dpo_gre4_ip6[] = { "lb6-gre4" , NULL };
39 const static char* const * const lb_dpo_gre4_nodes[DPO_PROTO_NUM] =
40  {
43  };
44 
45 const static char * const lb_dpo_gre6_ip4[] = { "lb4-gre6" , NULL };
46 const static char * const lb_dpo_gre6_ip6[] = { "lb6-gre6" , NULL };
47 const static char* const * const lb_dpo_gre6_nodes[DPO_PROTO_NUM] =
48  {
51  };
52 
53 const static char * const lb_dpo_gre4_ip4_port[] = { "lb4-gre4-port" , NULL };
54 const static char * const lb_dpo_gre4_ip6_port[] = { "lb6-gre4-port" , NULL };
55 const static char* const * const lb_dpo_gre4_port_nodes[DPO_PROTO_NUM] =
56  {
59  };
60 
61 const static char * const lb_dpo_gre6_ip4_port[] = { "lb4-gre6-port" , NULL };
62 const static char * const lb_dpo_gre6_ip6_port[] = { "lb6-gre6-port" , NULL };
63 const static char* const * const lb_dpo_gre6_port_nodes[DPO_PROTO_NUM] =
64  {
67  };
68 
69 const static char * const lb_dpo_l3dsr_ip4[] = {"lb4-l3dsr" , NULL};
70 const static char* const * const lb_dpo_l3dsr_nodes[DPO_PROTO_NUM] =
71  {
73  };
74 
75 const static char * const lb_dpo_l3dsr_ip4_port[] = {"lb4-l3dsr-port" , NULL};
76 const static char* const * const lb_dpo_l3dsr_port_nodes[DPO_PROTO_NUM] =
77  {
79  };
80 
81 const static char * const lb_dpo_nat4_ip4_port[] = { "lb4-nat4-port" , NULL };
82 const static char* const * const lb_dpo_nat4_port_nodes[DPO_PROTO_NUM] =
83  {
85  };
86 
87 const static char * const lb_dpo_nat6_ip6_port[] = { "lb6-nat6-port" , NULL };
88 const static char* const * const lb_dpo_nat6_port_nodes[DPO_PROTO_NUM] =
89  {
91  };
92 
94 {
95  return (u32) (vlib_time_now(vm) + 10000);
96 }
97 
98 u8 *format_lb_main (u8 * s, va_list * args)
99 {
101  lb_main_t *lbm = &lb_main;
102  s = format(s, "lb_main");
103  s = format(s, " ip4-src-address: %U \n", format_ip4_address, &lbm->ip4_src_address);
104  s = format(s, " ip6-src-address: %U \n", format_ip6_address, &lbm->ip6_src_address);
105  s = format(s, " #vips: %u\n", pool_elts(lbm->vips));
106  s = format(s, " #ass: %u\n", pool_elts(lbm->ass) - 1);
107 
108  u32 thread_index;
109  for(thread_index = 0; thread_index < tm->n_vlib_mains; thread_index++ ) {
110  lb_hash_t *h = lbm->per_cpu[thread_index].sticky_ht;
111  if (h) {
112  s = format(s, "core %d\n", thread_index);
113  s = format(s, " timeout: %ds\n", h->timeout);
114  s = format(s, " usage: %d / %d\n", lb_hash_elts(h, lb_hash_time_now(vlib_get_main())), lb_hash_size(h));
115  }
116  }
117 
118  return s;
119 }
120 
121 static char *lb_vip_type_strings[] = {
122  [LB_VIP_TYPE_IP6_GRE6] = "ip6-gre6",
123  [LB_VIP_TYPE_IP6_GRE4] = "ip6-gre4",
124  [LB_VIP_TYPE_IP4_GRE6] = "ip4-gre6",
125  [LB_VIP_TYPE_IP4_GRE4] = "ip4-gre4",
126  [LB_VIP_TYPE_IP4_L3DSR] = "ip4-l3dsr",
127  [LB_VIP_TYPE_IP4_NAT4] = "ip4-nat4",
128  [LB_VIP_TYPE_IP6_NAT6] = "ip6-nat6",
129 };
130 
131 u8 *format_lb_vip_type (u8 * s, va_list * args)
132 {
133  lb_vip_type_t vipt = va_arg (*args, lb_vip_type_t);
134  u32 i;
135  for (i=0; i<LB_VIP_N_TYPES; i++)
136  if (vipt == i)
137  return format(s, lb_vip_type_strings[i]);
138  return format(s, "_WRONG_TYPE_");
139 }
140 
141 uword unformat_lb_vip_type (unformat_input_t * input, va_list * args)
142 {
143  lb_vip_type_t *vipt = va_arg (*args, lb_vip_type_t *);
144  u32 i;
145  for (i=0; i<LB_VIP_N_TYPES; i++)
146  if (unformat(input, lb_vip_type_strings[i])) {
147  *vipt = i;
148  return 1;
149  }
150  return 0;
151 }
152 
153 u8 *format_lb_vip (u8 * s, va_list * args)
154 {
155  lb_vip_t *vip = va_arg (*args, lb_vip_t *);
156  s = format(s, "%U %U new_size:%u #as:%u%s",
157  format_lb_vip_type, vip->type,
159  vip->new_flow_table_mask + 1,
160  pool_elts(vip->as_indexes),
161  (vip->flags & LB_VIP_FLAGS_USED)?"":" removed");
162 
163  if (vip->port != 0)
164  {
165  s = format(s, " protocol:%u port:%u ", vip->protocol, vip->port);
166  }
167 
168  if (vip->type == LB_VIP_TYPE_IP4_L3DSR)
169  {
170  s = format(s, " dscp:%u", vip->encap_args.dscp);
171  }
172  else if ((vip->type == LB_VIP_TYPE_IP4_NAT4)
173  || (vip->type == LB_VIP_TYPE_IP6_NAT6))
174  {
175  s = format (s, " type:%s port:%u target_port:%u",
176  (vip->encap_args.srv_type == LB_SRV_TYPE_CLUSTERIP)?"clusterip":
177  "nodeport",
178  ntohs(vip->port), ntohs(vip->encap_args.target_port));
179  }
180 
181  return s;
182 }
183 
184 u8 *format_lb_as (u8 * s, va_list * args)
185 {
186  lb_as_t *as = va_arg (*args, lb_as_t *);
187  return format(s, "%U %s", format_ip46_address,
188  &as->address, IP46_TYPE_ANY,
189  (as->flags & LB_AS_FLAGS_USED)?"used":"removed");
190 }
191 
192 u8 *format_lb_vip_detailed (u8 * s, va_list * args)
193 {
194  lb_main_t *lbm = &lb_main;
195  lb_vip_t *vip = va_arg (*args, lb_vip_t *);
196  u32 indent = format_get_indent (s);
197 
198  s = format(s, "%U %U [%lu] %U%s\n"
199  "%U new_size:%u\n",
200  format_white_space, indent,
201  format_lb_vip_type, vip->type,
202  vip - lbm->vips,
204  (vip->flags & LB_VIP_FLAGS_USED)?"":" removed",
205  format_white_space, indent,
206  vip->new_flow_table_mask + 1);
207 
208  if (vip->port != 0)
209  {
210  s = format(s, "%U protocol:%u port:%u\n",
211  format_white_space, indent,
212  vip->protocol, vip->port);
213  }
214 
215  if (vip->type == LB_VIP_TYPE_IP4_L3DSR)
216  {
217  s = format(s, "%U dscp:%u\n",
218  format_white_space, indent,
219  vip->encap_args.dscp);
220  }
221  else if ((vip->type == LB_VIP_TYPE_IP4_NAT4)
222  || (vip->type == LB_VIP_TYPE_IP6_NAT6))
223  {
224  s = format (s, "%U type:%s port:%u target_port:%u",
225  format_white_space, indent,
226  (vip->encap_args.srv_type == LB_SRV_TYPE_CLUSTERIP)?"clusterip":
227  "nodeport",
228  ntohs(vip->port), ntohs(vip->encap_args.target_port));
229  }
230 
231  //Print counters
232  s = format(s, "%U counters:\n",
233  format_white_space, indent);
234  u32 i;
235  for (i=0; i<LB_N_VIP_COUNTERS; i++)
236  s = format(s, "%U %s: %Lu\n",
237  format_white_space, indent,
238  lbm->vip_counters[i].name,
239  vlib_get_simple_counter(&lbm->vip_counters[i], vip - lbm->vips));
240 
241 
242  s = format(s, "%U #as:%u\n",
243  format_white_space, indent,
244  pool_elts(vip->as_indexes));
245 
246  //Let's count the buckets for each AS
247  u32 *count = 0;
248  vec_validate(count, pool_len(lbm->ass)); //Possibly big alloc for not much...
249  lb_new_flow_entry_t *nfe;
250  vec_foreach(nfe, vip->new_flow_table)
251  count[nfe->as_index]++;
252 
253  lb_as_t *as;
254  u32 *as_index;
255  pool_foreach(as_index, vip->as_indexes, {
256  as = &lbm->ass[*as_index];
257  s = format(s, "%U %U %u buckets %Lu flows dpo:%u %s\n",
258  format_white_space, indent,
259  format_ip46_address, &as->address, IP46_TYPE_ANY,
260  count[as - lbm->ass],
261  vlib_refcount_get(&lbm->as_refcount, as - lbm->ass),
262  as->dpo.dpoi_index,
263  (as->flags & LB_AS_FLAGS_USED)?"used":" removed");
264  });
265 
266  vec_free(count);
267  return s;
268 }
269 
270 typedef struct {
275 
276 static int lb_pseudorand_compare(void *a, void *b)
277 {
278  lb_as_t *asa, *asb;
279  lb_main_t *lbm = &lb_main;
280  asa = &lbm->ass[((lb_pseudorand_t *)a)->as_index];
281  asb = &lbm->ass[((lb_pseudorand_t *)b)->as_index];
282  return memcmp(&asa->address, &asb->address, sizeof(asb->address));
283 }
284 
286 {
287  lb_main_t *lbm = &lb_main;
288  lb_snat4_key_t m_key4;
289  clib_bihash_kv_8_8_t kv4, value4;
290  lb_snat6_key_t m_key6;
291  clib_bihash_kv_24_8_t kv6, value6;
292  lb_snat_mapping_t *m = 0;
294 
295  u32 now = (u32) vlib_time_now(vlib_get_main());
297  return;
298 
299  vip->last_garbage_collection = now;
300  lb_as_t *as;
301  u32 *as_index;
302  pool_foreach(as_index, vip->as_indexes, {
303  as = &lbm->ass[*as_index];
304  if (!(as->flags & LB_AS_FLAGS_USED) && //Not used
305  clib_u32_loop_gt(now, as->last_used + LB_CONCURRENCY_TIMEOUT) &&
306  (vlib_refcount_get(&lbm->as_refcount, as - lbm->ass) == 0))
307  { //Not referenced
308 
309  if (lb_vip_is_nat4_port(vip)) {
310  m_key4.addr = as->address.ip4;
311  m_key4.port = vip->encap_args.target_port;
312  m_key4.protocol = 0;
313  m_key4.fib_index = 0;
314 
315  kv4.key = m_key4.as_u64;
316  if(!clib_bihash_search_8_8(&lbm->mapping_by_as4, &kv4, &value4))
317  m = pool_elt_at_index (lbm->snat_mappings, value4.value);
318  ASSERT (m);
319 
320  kv4.value = m - lbm->snat_mappings;
321  clib_bihash_add_del_8_8(&lbm->mapping_by_as4, &kv4, 0);
322  pool_put (lbm->snat_mappings, m);
323  } else if (lb_vip_is_nat6_port(vip)) {
324  m_key6.addr.as_u64[0] = as->address.ip6.as_u64[0];
325  m_key6.addr.as_u64[1] = as->address.ip6.as_u64[1];
326  m_key6.port = vip->encap_args.target_port;
327  m_key6.protocol = 0;
328  m_key6.fib_index = 0;
329 
330  kv6.key[0] = m_key6.as_u64[0];
331  kv6.key[1] = m_key6.as_u64[1];
332  kv6.key[2] = m_key6.as_u64[2];
333 
334  if (!clib_bihash_search_24_8 (&lbm->mapping_by_as6, &kv6, &value6))
335  m = pool_elt_at_index (lbm->snat_mappings, value6.value);
336  ASSERT (m);
337 
338  kv6.value = m - lbm->snat_mappings;
339  clib_bihash_add_del_24_8(&lbm->mapping_by_as6, &kv6, 0);
340  pool_put (lbm->snat_mappings, m);
341  }
342  fib_entry_child_remove(as->next_hop_fib_entry_index,
343  as->next_hop_child_index);
344  fib_table_entry_delete_index(as->next_hop_fib_entry_index,
345  FIB_SOURCE_RR);
346  as->next_hop_fib_entry_index = FIB_NODE_INDEX_INVALID;
347 
348  pool_put(vip->as_indexes, as_index);
349  pool_put(lbm->ass, as);
350  }
351  });
352 }
353 
355 {
356  lb_main_t *lbm = &lb_main;
358  lb_vip_t *vip;
359  u32 *to_be_removed_vips = 0, *i;
360  pool_foreach(vip, lbm->vips, {
361  lb_vip_garbage_collection(vip);
362 
363  if (!(vip->flags & LB_VIP_FLAGS_USED) &&
364  (pool_elts(vip->as_indexes) == 0)) {
365  vec_add1(to_be_removed_vips, vip - lbm->vips);
366  }
367  });
368 
369  vec_foreach(i, to_be_removed_vips) {
370  vip = &lbm->vips[*i];
371  pool_put(lbm->vips, vip);
372  pool_free(vip->as_indexes);
373  }
374 
375  vec_free(to_be_removed_vips);
377 }
378 
380 {
381  lb_main_t *lbm = &lb_main;
382  lb_new_flow_entry_t *old_table;
383  u32 i, *as_index;
384  lb_new_flow_entry_t *new_flow_table = 0;
385  lb_as_t *as;
386  lb_pseudorand_t *pr, *sort_arr = 0;
387 
388  CLIB_SPINLOCK_ASSERT_LOCKED (&lbm->writer_lock); // We must have the lock
389 
390  //Check if some AS is configured or not
391  i = 0;
392  pool_foreach(as_index, vip->as_indexes, {
393  as = &lbm->ass[*as_index];
394  if (as->flags & LB_AS_FLAGS_USED) { //Not used anymore
395  i = 1;
396  goto out; //Not sure 'break' works in this macro-loop
397  }
398  });
399 
400 out:
401  if (i == 0) {
402  //Only the default. i.e. no AS
403  vec_validate(new_flow_table, vip->new_flow_table_mask);
404  for (i=0; i<vec_len(new_flow_table); i++)
405  new_flow_table[i].as_index = 0;
406 
407  goto finished;
408  }
409 
410  //First, let's sort the ASs
411  vec_alloc(sort_arr, pool_elts(vip->as_indexes));
412 
413  i = 0;
414  pool_foreach(as_index, vip->as_indexes, {
415  as = &lbm->ass[*as_index];
416  if (!(as->flags & LB_AS_FLAGS_USED)) //Not used anymore
417  continue;
418 
419  sort_arr[i].as_index = as - lbm->ass;
420  i++;
421  });
422  _vec_len(sort_arr) = i;
423 
425 
426  //Now let's pseudo-randomly generate permutations
427  vec_foreach(pr, sort_arr) {
428  lb_as_t *as = &lbm->ass[pr->as_index];
429 
430  u64 seed = clib_xxhash(as->address.as_u64[0] ^
431  as->address.as_u64[1]);
432  /* We have 2^n buckets.
433  * skip must be prime with 2^n.
434  * So skip must be odd.
435  * MagLev actually state that M should be prime,
436  * but this has a big computation cost (% operation).
437  * Using 2^n is more better (& operation).
438  */
439  pr->skip = ((seed & 0xffffffff) | 1) & vip->new_flow_table_mask;
440  pr->last = (seed >> 32) & vip->new_flow_table_mask;
441  }
442 
443  //Let's create a new flow table
444  vec_validate(new_flow_table, vip->new_flow_table_mask);
445  for (i=0; i<vec_len(new_flow_table); i++)
446  new_flow_table[i].as_index = 0;
447 
448  u32 done = 0;
449  while (1) {
450  vec_foreach(pr, sort_arr) {
451  while (1) {
452  u32 last = pr->last;
453  pr->last = (pr->last + pr->skip) & vip->new_flow_table_mask;
454  if (new_flow_table[last].as_index == 0) {
455  new_flow_table[last].as_index = pr->as_index;
456  break;
457  }
458  }
459  done++;
460  if (done == vec_len(new_flow_table))
461  goto finished;
462  }
463  }
464 
465 finished:
466  vec_free(sort_arr);
467 
468  old_table = vip->new_flow_table;
469  vip->new_flow_table = new_flow_table;
470  vec_free(old_table);
471 }
472 
474  u32 per_cpu_sticky_buckets, u32 flow_timeout)
475 {
476  lb_main_t *lbm = &lb_main;
477 
478  if (!is_pow2(per_cpu_sticky_buckets))
479  return VNET_API_ERROR_INVALID_MEMORY_SIZE;
480 
481  lb_get_writer_lock(); //Not exactly necessary but just a reminder that it exists for my future self
484  lbm->per_cpu_sticky_buckets = per_cpu_sticky_buckets;
485  lbm->flow_timeout = flow_timeout;
487  return 0;
488 }
489 
490 
491 
492 static
493 int lb_vip_port_find_index(ip46_address_t *prefix, u8 plen,
494  u8 protocol, u16 port,
495  lb_lkp_type_t lkp_type,
496  u32 *vip_index)
497 {
498  lb_main_t *lbm = &lb_main;
499  lb_vip_t *vip;
500  /* This must be called with the lock owned */
502  ip46_prefix_normalize(prefix, plen);
503  pool_foreach(vip, lbm->vips, {
504  if ((vip->flags & LB_AS_FLAGS_USED) &&
505  vip->plen == plen &&
506  vip->prefix.as_u64[0] == prefix->as_u64[0] &&
507  vip->prefix.as_u64[1] == prefix->as_u64[1])
508  {
509  if((lkp_type == LB_LKP_SAME_IP_PORT &&
510  vip->protocol == protocol &&
511  vip->port == port) ||
512  (lkp_type == LB_LKP_ALL_PORT_IP &&
513  vip->port == 0) ||
514  (lkp_type == LB_LKP_DIFF_IP_PORT &&
515  (vip->protocol != protocol ||
516  vip->port != port) ) )
517  {
518  *vip_index = vip - lbm->vips;
519  return 0;
520  }
521  }
522  });
523  return VNET_API_ERROR_NO_SUCH_ENTRY;
524 }
525 
526 static
527 int lb_vip_port_find_index_with_lock(ip46_address_t *prefix, u8 plen,
528  u8 protocol, u16 port, u32 *vip_index)
529 {
530  return lb_vip_port_find_index(prefix, plen, protocol, port,
531  LB_LKP_SAME_IP_PORT, vip_index);
532 }
533 
534 static
535 int lb_vip_port_find_all_port_vip(ip46_address_t *prefix, u8 plen,
536  u32 *vip_index)
537 {
538  return lb_vip_port_find_index(prefix, plen, ~0, 0,
539  LB_LKP_ALL_PORT_IP, vip_index);
540 }
541 
542 /* Find out per-port-vip entry with different protocol and port */
543 static
544 int lb_vip_port_find_diff_port(ip46_address_t *prefix, u8 plen,
545  u8 protocol, u16 port, u32 *vip_index)
546 {
547  return lb_vip_port_find_index(prefix, plen, protocol, port,
548  LB_LKP_DIFF_IP_PORT, vip_index);
549 }
550 
551 int lb_vip_find_index(ip46_address_t *prefix, u8 plen, u8 protocol,
552  u16 port, u32 *vip_index)
553 {
554  int ret;
556  ret = lb_vip_port_find_index_with_lock(prefix, plen,
557  protocol, port, vip_index);
559  return ret;
560 }
561 
562 static int lb_as_find_index_vip(lb_vip_t *vip, ip46_address_t *address, u32 *as_index)
563 {
564  lb_main_t *lbm = &lb_main;
565  /* This must be called with the lock owned */
567  lb_as_t *as;
568  u32 *asi;
569  pool_foreach(asi, vip->as_indexes, {
570  as = &lbm->ass[*asi];
571  if (as->vip_index == (vip - lbm->vips) &&
572  as->address.as_u64[0] == address->as_u64[0] &&
573  as->address.as_u64[1] == address->as_u64[1])
574  {
575  *as_index = as - lbm->ass;
576  return 0;
577  }
578  });
579  return -1;
580 }
581 
582 int lb_vip_add_ass(u32 vip_index, ip46_address_t *addresses, u32 n)
583 {
584  lb_main_t *lbm = &lb_main;
586  lb_vip_t *vip;
587  if (!(vip = lb_vip_get_by_index(vip_index))) {
589  return VNET_API_ERROR_NO_SUCH_ENTRY;
590  }
591 
593  u32 *to_be_added = 0;
594  u32 *to_be_updated = 0;
595  u32 i;
596  u32 *ip;
598 
599  //Sanity check
600  while (n--) {
601 
602  if (!lb_as_find_index_vip(vip, &addresses[n], &i)) {
603  if (lbm->ass[i].flags & LB_AS_FLAGS_USED) {
604  vec_free(to_be_added);
605  vec_free(to_be_updated);
607  return VNET_API_ERROR_VALUE_EXIST;
608  }
609  vec_add1(to_be_updated, i);
610  goto next;
611  }
612 
613  if (ip46_address_type(&addresses[n]) != type) {
614  vec_free(to_be_added);
615  vec_free(to_be_updated);
617  return VNET_API_ERROR_INVALID_ADDRESS_FAMILY;
618  }
619 
620  if (n) {
621  u32 n2 = n;
622  while(n2--) //Check for duplicates
623  if (addresses[n2].as_u64[0] == addresses[n].as_u64[0] &&
624  addresses[n2].as_u64[1] == addresses[n].as_u64[1])
625  goto next;
626  }
627 
628  vec_add1(to_be_added, n);
629 
630 next:
631  continue;
632  }
633 
634  //Update reused ASs
635  vec_foreach(ip, to_be_updated) {
636  lbm->ass[*ip].flags = LB_AS_FLAGS_USED;
637  }
638  vec_free(to_be_updated);
639 
640  //Create those who have to be created
641  vec_foreach(ip, to_be_added) {
642  lb_as_t *as;
643  u32 *as_index;
644  pool_get(lbm->ass, as);
645  as->address = addresses[*ip];
646  as->flags = LB_AS_FLAGS_USED;
647  as->vip_index = vip_index;
648  pool_get(vip->as_indexes, as_index);
649  *as_index = as - lbm->ass;
650 
651  /*
652  * become a child of the FIB entry
653  * so we are informed when its forwarding changes
654  */
655  fib_prefix_t nh = {};
656  if (lb_encap_is_ip4(vip)) {
657  nh.fp_addr.ip4 = as->address.ip4;
658  nh.fp_len = 32;
660  } else {
661  nh.fp_addr.ip6 = as->address.ip6;
662  nh.fp_len = 128;
664  }
665 
668  &nh,
673  lbm->fib_node_type,
674  as - lbm->ass);
675 
676  lb_as_stack(as);
677 
678  if ( lb_vip_is_nat4_port(vip) || lb_vip_is_nat6_port(vip) )
679  {
680  /* Add SNAT static mapping */
681  pool_get (lbm->snat_mappings, m);
682  clib_memset (m, 0, sizeof (*m));
683  if (lb_vip_is_nat4_port(vip)) {
684  lb_snat4_key_t m_key4;
686  m_key4.addr = as->address.ip4;
687  m_key4.port = vip->encap_args.target_port;
688  m_key4.protocol = 0;
689  m_key4.fib_index = 0;
690 
692  {
693  m->src_ip.ip4 = vip->prefix.ip4;
694  }
695  else if (vip->encap_args.srv_type == LB_SRV_TYPE_NODEPORT)
696  {
697  m->src_ip.ip4 = lbm->ip4_src_address;
698  }
699  m->src_ip_is_ipv6 = 0;
700  m->as_ip.ip4 = as->address.ip4;
701  m->as_ip_is_ipv6 = 0;
702  m->src_port = vip->port;
704  m->vrf_id = 0;
705  m->fib_index = 0;
706 
707  kv4.key = m_key4.as_u64;
708  kv4.value = m - lbm->snat_mappings;
709  clib_bihash_add_del_8_8(&lbm->mapping_by_as4, &kv4, 1);
710  } else {
711  lb_snat6_key_t m_key6;
713  m_key6.addr.as_u64[0] = as->address.ip6.as_u64[0];
714  m_key6.addr.as_u64[1] = as->address.ip6.as_u64[1];
715  m_key6.port = vip->encap_args.target_port;
716  m_key6.protocol = 0;
717  m_key6.fib_index = 0;
718 
720  {
721  m->src_ip.ip6.as_u64[0] = vip->prefix.ip6.as_u64[0];
722  m->src_ip.ip6.as_u64[1] = vip->prefix.ip6.as_u64[1];
723  }
724  else if (vip->encap_args.srv_type == LB_SRV_TYPE_NODEPORT)
725  {
726  m->src_ip.ip6.as_u64[0] = lbm->ip6_src_address.as_u64[0];
727  m->src_ip.ip6.as_u64[1] = lbm->ip6_src_address.as_u64[1];
728  }
729  m->src_ip_is_ipv6 = 1;
730  m->as_ip.ip6.as_u64[0] = as->address.ip6.as_u64[0];
731  m->as_ip.ip6.as_u64[1] = as->address.ip6.as_u64[1];
732  m->as_ip_is_ipv6 = 1;
733  m->src_port = vip->port;
735  m->vrf_id = 0;
736  m->fib_index = 0;
737 
738  kv6.key[0] = m_key6.as_u64[0];
739  kv6.key[1] = m_key6.as_u64[1];
740  kv6.key[2] = m_key6.as_u64[2];
741  kv6.value = m - lbm->snat_mappings;
742  clib_bihash_add_del_24_8(&lbm->mapping_by_as6, &kv6, 1);
743  }
744  }
745  }
746  vec_free(to_be_added);
747 
748  //Recompute flows
750 
751  //Garbage collection maybe
753 
755  return 0;
756 }
757 
758 int
759 lb_flush_vip_as (u32 vip_index, u32 as_index)
760 {
761  u32 thread_index;
763  lb_main_t *lbm = &lb_main;
764 
765  for(thread_index = 0; thread_index < tm->n_vlib_mains; thread_index++ ) {
766  lb_hash_t *h = lbm->per_cpu[thread_index].sticky_ht;
767  if (h != NULL) {
768  u32 i;
769  lb_hash_bucket_t *b;
770 
771  lb_hash_foreach_entry(h, b, i) {
772  if ((vip_index == ~0)
773  || ((b->vip[i] == vip_index) && (as_index == ~0))
774  || ((b->vip[i] == vip_index) && (b->value[i] == as_index)))
775  {
776  vlib_refcount_add(&lbm->as_refcount, thread_index, b->value[i], -1);
777  vlib_refcount_add(&lbm->as_refcount, thread_index, 0, 1);
778  b->vip[i] = ~0;
779  b->value[i] = 0;
780  }
781  }
782  if (vip_index == ~0)
783  {
784  lb_hash_free(h);
785  lbm->per_cpu[thread_index].sticky_ht = 0;
786  }
787  }
788  }
789 
790  return 0;
791 }
792 
793 int lb_vip_del_ass_withlock(u32 vip_index, ip46_address_t *addresses, u32 n,
794  u8 flush)
795 {
796  lb_main_t *lbm = &lb_main;
797  u32 now = (u32) vlib_time_now(vlib_get_main());
798  u32 *ip = 0;
799  u32 as_index = 0;
800 
801  lb_vip_t *vip;
802  if (!(vip = lb_vip_get_by_index(vip_index))) {
803  return VNET_API_ERROR_NO_SUCH_ENTRY;
804  }
805 
806  u32 *indexes = NULL;
807  while (n--) {
808  if (lb_as_find_index_vip(vip, &addresses[n], &as_index)) {
809  vec_free(indexes);
810  return VNET_API_ERROR_NO_SUCH_ENTRY;
811  }
812 
813  if (n) { //Check for duplicates
814  u32 n2 = n - 1;
815  while(n2--) {
816  if (addresses[n2].as_u64[0] == addresses[n].as_u64[0] &&
817  addresses[n2].as_u64[1] == addresses[n].as_u64[1])
818  goto next;
819  }
820  }
821 
822  vec_add1(indexes, as_index);
823 next:
824  continue;
825  }
826 
827  //Garbage collection maybe
829 
830  if (indexes != NULL) {
831  vec_foreach(ip, indexes) {
832  lbm->ass[*ip].flags &= ~LB_AS_FLAGS_USED;
833  lbm->ass[*ip].last_used = now;
834 
835  if(flush)
836  {
837  /* flush flow table for deleted ASs*/
838  lb_flush_vip_as(vip_index, *ip);
839  }
840  }
841 
842  //Recompute flows
844  }
845 
846  vec_free(indexes);
847  return 0;
848 }
849 
850 int lb_vip_del_ass(u32 vip_index, ip46_address_t *addresses, u32 n, u8 flush)
851 {
853  int ret = lb_vip_del_ass_withlock(vip_index, addresses, n, flush);
855 
856  return ret;
857 }
858 
859 static int
861 {
862  /*
863  * Check for dynamically allocated instance number.
864  */
865  u32 bit;
866 
868 
870 
871  return bit;
872 }
873 
874 static int
876 {
877 
878  if (clib_bitmap_get (lbm->vip_prefix_indexes, instance) == 0)
879  {
880  return -1;
881  }
882 
884  instance, 0);
885 
886  return 0;
887 }
888 
889 /**
890  * Add the VIP adjacency to the ip4 or ip6 fib
891  */
892 static void lb_vip_add_adjacency(lb_main_t *lbm, lb_vip_t *vip,
893  u32 *vip_prefix_index)
894 {
895  dpo_proto_t proto = 0;
896  dpo_type_t dpo_type = 0;
897  u32 vip_idx = 0;
898 
899  if (vip->port != 0)
900  {
901  /* for per-port vip, if VIP adjacency has been added,
902  * no need to add adjacency. */
903  if (!lb_vip_port_find_diff_port(&(vip->prefix), vip->plen,
904  vip->protocol, vip->port, &vip_idx))
905  {
906  return;
907  }
908 
909  /* Allocate an index for per-port vip */
910  *vip_prefix_index = lb_vip_prefix_index_alloc(lbm);
911  }
912  else
913  {
914  *vip_prefix_index = vip - lbm->vips;
915  }
916 
917  dpo_id_t dpo = DPO_INVALID;
918  fib_prefix_t pfx = {};
919  if (lb_vip_is_ip4(vip->type)) {
920  pfx.fp_addr.ip4 = vip->prefix.ip4;
921  pfx.fp_len = vip->plen - 96;
923  proto = DPO_PROTO_IP4;
924  } else {
925  pfx.fp_addr.ip6 = vip->prefix.ip6;
926  pfx.fp_len = vip->plen;
928  proto = DPO_PROTO_IP6;
929  }
930 
931  if (lb_vip_is_gre4(vip))
932  dpo_type = lbm->dpo_gre4_type;
933  else if (lb_vip_is_gre6(vip))
934  dpo_type = lbm->dpo_gre6_type;
935  else if (lb_vip_is_gre4_port(vip))
936  dpo_type = lbm->dpo_gre4_port_type;
937  else if (lb_vip_is_gre6_port(vip))
938  dpo_type = lbm->dpo_gre6_port_type;
939  else if (lb_vip_is_l3dsr(vip))
940  dpo_type = lbm->dpo_l3dsr_type;
941  else if (lb_vip_is_l3dsr_port(vip))
942  dpo_type = lbm->dpo_l3dsr_port_type;
943  else if(lb_vip_is_nat4_port(vip))
944  dpo_type = lbm->dpo_nat4_port_type;
945  else if (lb_vip_is_nat6_port(vip))
946  dpo_type = lbm->dpo_nat6_port_type;
947 
948  dpo_set(&dpo, dpo_type, proto, *vip_prefix_index);
950  &pfx,
953  &dpo);
954  dpo_reset(&dpo);
955 }
956 
957 /**
958  * Add the VIP filter entry
959  */
961  u32 vip_prefix_index, u32 vip_idx)
962 {
965 
966  key.vip_prefix_index = vip_prefix_index;
967  key.protocol = vip->protocol;
968  key.port = clib_host_to_net_u16(vip->port);
969  key.rsv = 0;
970 
971  kv.key = key.as_u64;
972  kv.value = vip_idx;
973  clib_bihash_add_del_8_8(&lbm->vip_index_per_port, &kv, 1);
974 
975  return 0;
976 }
977 
978 /**
979  * Del the VIP filter entry
980  */
982 {
985  lb_vip_t *m = 0;
986 
988  key.protocol = vip->protocol;
989  key.port = clib_host_to_net_u16(vip->port);
990  key.rsv = 0;
991 
992  kv.key = key.as_u64;
993  if(clib_bihash_search_8_8(&lbm->vip_index_per_port, &kv, &value) != 0)
994  {
995  clib_warning("looking up vip_index_per_port failed.");
996  return VNET_API_ERROR_NO_SUCH_ENTRY;
997  }
998  m = pool_elt_at_index (lbm->vips, value.value);
999  ASSERT (m);
1000 
1001  kv.value = m - lbm->vips;
1002  clib_bihash_add_del_8_8(&lbm->vip_index_per_port, &kv, 0);
1003 
1004  return 0;
1005 }
1006 
1007 /**
1008  * Deletes the adjacency associated with the VIP
1009  */
1010 static void lb_vip_del_adjacency(lb_main_t *lbm, lb_vip_t *vip)
1011 {
1012  fib_prefix_t pfx = {};
1013  u32 vip_idx = 0;
1014 
1015  if (vip->port != 0)
1016  {
1017  /* If this vip adjacency is used by other per-port vip,
1018  * no need to del this adjacency. */
1019  if (!lb_vip_port_find_diff_port(&(vip->prefix), vip->plen,
1020  vip->protocol, vip->port, &vip_idx))
1021  {
1023  return;
1024  }
1025 
1026  /* Return vip_prefix_index for per-port vip */
1028 
1029  }
1030 
1031  if (lb_vip_is_ip4(vip->type)) {
1032  pfx.fp_addr.ip4 = vip->prefix.ip4;
1033  pfx.fp_len = vip->plen - 96;
1034  pfx.fp_proto = FIB_PROTOCOL_IP4;
1035  } else {
1036  pfx.fp_addr.ip6 = vip->prefix.ip6;
1037  pfx.fp_len = vip->plen;
1038  pfx.fp_proto = FIB_PROTOCOL_IP6;
1039  }
1041 }
1042 
1043 int lb_vip_add(lb_vip_add_args_t args, u32 *vip_index)
1044 {
1045  lb_main_t *lbm = &lb_main;
1047  lb_vip_t *vip;
1048  lb_vip_type_t type = args.type;
1049  u32 vip_prefix_index = 0;
1050 
1052  ip46_prefix_normalize(&(args.prefix), args.plen);
1053 
1054  if (!lb_vip_port_find_index_with_lock(&(args.prefix), args.plen,
1055  args.protocol, args.port,
1056  vip_index))
1057  {
1059  return VNET_API_ERROR_VALUE_EXIST;
1060  }
1061 
1062  /* Make sure we can't add a per-port VIP entry
1063  * when there already is an all-port VIP for the same prefix. */
1064  if ((args.port != 0) &&
1065  !lb_vip_port_find_all_port_vip(&(args.prefix), args.plen, vip_index))
1066  {
1068  return VNET_API_ERROR_VALUE_EXIST;
1069  }
1070 
1071  /* Make sure we can't add a all-port VIP entry
1072  * when there already is an per-port VIP for the same prefix. */
1073  if ((args.port == 0) &&
1074  !lb_vip_port_find_diff_port(&(args.prefix), args.plen,
1075  args.protocol, args.port, vip_index))
1076  {
1078  return VNET_API_ERROR_VALUE_EXIST;
1079  }
1080 
1081  /* Make sure all VIP for a given prefix (using different ports) have the same type. */
1082  if ((args.port != 0) &&
1083  !lb_vip_port_find_diff_port(&(args.prefix), args.plen,
1084  args.protocol, args.port, vip_index)
1085  && (args.type != lbm->vips[*vip_index].type))
1086  {
1088  return VNET_API_ERROR_INVALID_ARGUMENT;
1089  }
1090 
1091  if (!is_pow2(args.new_length)) {
1093  return VNET_API_ERROR_INVALID_MEMORY_SIZE;
1094  }
1095 
1096  if (ip46_prefix_is_ip4(&(args.prefix), args.plen) &&
1097  !lb_vip_is_ip4(type)) {
1099  return VNET_API_ERROR_INVALID_ADDRESS_FAMILY;
1100  }
1101 
1102  if ((!ip46_prefix_is_ip4(&(args.prefix), args.plen)) &&
1103  !lb_vip_is_ip6(type)) {
1105  return VNET_API_ERROR_INVALID_ADDRESS_FAMILY;
1106  }
1107 
1108  if ((type == LB_VIP_TYPE_IP4_L3DSR) &&
1109  (args.encap_args.dscp >= 64) )
1110  {
1112  return VNET_API_ERROR_VALUE_EXIST;
1113  }
1114 
1115  //Allocate
1116  pool_get(lbm->vips, vip);
1117 
1118  //Init
1119  memcpy (&(vip->prefix), &(args.prefix), sizeof(args.prefix));
1120  vip->plen = args.plen;
1121  if (args.port != 0)
1122  {
1123  vip->protocol = args.protocol;
1124  vip->port = args.port;
1125  }
1126  else
1127  {
1128  vip->protocol = (u8)~0;
1129  vip->port = 0;
1130  }
1132  vip->type = args.type;
1133 
1134  if (args.type == LB_VIP_TYPE_IP4_L3DSR) {
1135  vip->encap_args.dscp = args.encap_args.dscp;
1136  }
1137  else if ((args.type == LB_VIP_TYPE_IP4_NAT4)
1138  ||(args.type == LB_VIP_TYPE_IP6_NAT6)) {
1139  vip->encap_args.srv_type = args.encap_args.srv_type;
1140  vip->encap_args.target_port =
1141  clib_host_to_net_u16(args.encap_args.target_port);
1142  }
1143 
1144  vip->flags = LB_VIP_FLAGS_USED;
1145  vip->as_indexes = 0;
1146 
1147  //Validate counters
1148  u32 i;
1149  for (i = 0; i < LB_N_VIP_COUNTERS; i++) {
1150  vlib_validate_simple_counter(&lbm->vip_counters[i], vip - lbm->vips);
1151  vlib_zero_simple_counter(&lbm->vip_counters[i], vip - lbm->vips);
1152  }
1153 
1154  //Configure new flow table
1155  vip->new_flow_table_mask = args.new_length - 1;
1156  vip->new_flow_table = 0;
1157 
1158  //Update flow hash table
1160 
1161  //Create adjacency to direct traffic
1162  lb_vip_add_adjacency(lbm, vip, &vip_prefix_index);
1163 
1164  if ( (lb_vip_is_nat4_port(vip) || lb_vip_is_nat6_port(vip))
1166  {
1167  u32 key;
1168  uword * entry;
1169 
1170  //Create maping from nodeport to vip_index
1171  key = clib_host_to_net_u16(args.port);
1172  entry = hash_get_mem (lbm->vip_index_by_nodeport, &key);
1173  if (entry) {
1175  return VNET_API_ERROR_VALUE_EXIST;
1176  }
1177 
1178  hash_set_mem (lbm->vip_index_by_nodeport, &key, vip - lbm->vips);
1179 
1180  /* receive packets destined to NodeIP:NodePort */
1181  udp_register_dst_port (vm, args.port, lb4_nodeport_node.index, 1);
1182  udp_register_dst_port (vm, args.port, lb6_nodeport_node.index, 0);
1183  }
1184 
1185  *vip_index = vip - lbm->vips;
1186  //Create per-port vip filtering table
1187  if (args.port != 0)
1188  {
1189  lb_vip_add_port_filter(lbm, vip, vip_prefix_index, *vip_index);
1190  vip->vip_prefix_index = vip_prefix_index;
1191  }
1192 
1194  return 0;
1195 }
1196 
1197 int lb_vip_del(u32 vip_index)
1198 {
1199  lb_main_t *lbm = &lb_main;
1200  lb_vip_t *vip;
1201  int rv = 0;
1202 
1203  /* Does not remove default vip, i.e. vip_index = 0 */
1204  if (vip_index == 0)
1205  return VNET_API_ERROR_INVALID_VALUE;
1206 
1208  if (!(vip = lb_vip_get_by_index(vip_index))) {
1210  return VNET_API_ERROR_NO_SUCH_ENTRY;
1211  }
1212 
1213  //FIXME: This operation is actually not working
1214  //We will need to remove state before performing this.
1215 
1216  {
1217  //Remove all ASs
1218  ip46_address_t *ass = 0;
1219  lb_as_t *as;
1220  u32 *as_index;
1221 
1222  pool_foreach(as_index, vip->as_indexes, {
1223  as = &lbm->ass[*as_index];
1224  vec_add1(ass, as->address);
1225  });
1226  if (vec_len(ass))
1227  lb_vip_del_ass_withlock(vip_index, ass, vec_len(ass), 0);
1228  vec_free(ass);
1229  }
1230 
1231  //Delete adjacency
1232  lb_vip_del_adjacency(lbm, vip);
1233 
1234  //Delete per-port vip filtering entry
1235  if (vip->port != 0)
1236  {
1237  rv = lb_vip_del_port_filter(lbm, vip);
1238  }
1239 
1240  //Set the VIP as unused
1241  vip->flags &= ~LB_VIP_FLAGS_USED;
1242 
1244  return rv;
1245 }
1246 
1247 /* *INDENT-OFF* */
1248 VLIB_PLUGIN_REGISTER () = {
1249  .version = VPP_BUILD_VER,
1250  .description = "Load Balancer (LB)",
1251 };
1252 /* *INDENT-ON* */
1253 
1254 u8 *format_lb_dpo (u8 * s, va_list * va)
1255 {
1256  index_t index = va_arg (*va, index_t);
1257  CLIB_UNUSED(u32 indent) = va_arg (*va, u32);
1258  lb_main_t *lbm = &lb_main;
1259  lb_vip_t *vip = pool_elt_at_index (lbm->vips, index);
1260  return format (s, "%U", format_lb_vip, vip);
1261 }
1262 
1263 static void lb_dpo_lock (dpo_id_t *dpo) {}
1264 static void lb_dpo_unlock (dpo_id_t *dpo) {}
1265 
1266 static fib_node_t *
1268 {
1269  lb_main_t *lbm = &lb_main;
1270  lb_as_t *as = pool_elt_at_index (lbm->ass, index);
1271  return (&as->fib_node);
1272 }
1273 
1274 static void
1276 {
1277 }
1278 
1279 static lb_as_t *
1281 {
1282  return ((lb_as_t*)(((char*)node) -
1283  STRUCT_OFFSET_OF(lb_as_t, fib_node)));
1284 }
1285 
1286 static void
1288 {
1289  lb_main_t *lbm = &lb_main;
1290  lb_vip_t *vip = &lbm->vips[as->vip_index];
1291  dpo_type_t dpo_type = 0;
1292 
1293  if (lb_vip_is_gre4(vip))
1294  dpo_type = lbm->dpo_gre4_type;
1295  else if (lb_vip_is_gre6(vip))
1296  dpo_type = lbm->dpo_gre6_type;
1297  else if (lb_vip_is_gre4_port(vip))
1298  dpo_type = lbm->dpo_gre4_port_type;
1299  else if (lb_vip_is_gre6_port(vip))
1300  dpo_type = lbm->dpo_gre6_port_type;
1301  else if (lb_vip_is_l3dsr(vip))
1302  dpo_type = lbm->dpo_l3dsr_type;
1303  else if (lb_vip_is_l3dsr_port(vip))
1304  dpo_type = lbm->dpo_l3dsr_port_type;
1305  else if(lb_vip_is_nat4_port(vip))
1306  dpo_type = lbm->dpo_nat4_port_type;
1307  else if (lb_vip_is_nat6_port(vip))
1308  dpo_type = lbm->dpo_nat6_port_type;
1309 
1310  dpo_stack(dpo_type,
1312  &as->dpo,
1315 }
1316 
1320 {
1322  return (FIB_NODE_BACK_WALK_CONTINUE);
1323 }
1324 
1326 {
1327  if (is_del)
1328  {
1329  vnet_feature_enable_disable ("ip4-unicast", "lb-nat4-in2out",
1330  sw_if_index, 0, 0, 0);
1331  }
1332  else
1333  {
1334  vnet_feature_enable_disable ("ip4-unicast", "lb-nat4-in2out",
1335  sw_if_index, 1, 0, 0);
1336  }
1337 
1338  return 0;
1339 }
1340 
1342 {
1343  if (is_del)
1344  {
1345  vnet_feature_enable_disable ("ip6-unicast", "lb-nat6-in2out",
1346  sw_if_index, 0, 0, 0);
1347  }
1348  else
1349  {
1350  vnet_feature_enable_disable ("ip6-unicast", "lb-nat6-in2out",
1351  sw_if_index, 1, 0, 0);
1352  }
1353 
1354  return 0;
1355 }
1356 
1357 clib_error_t *
1359 {
1361  lb_main_t *lbm = &lb_main;
1362  lbm->vnet_main = vnet_get_main ();
1363  lbm->vlib_main = vm;
1364 
1365  lb_vip_t *default_vip;
1366  lb_as_t *default_as;
1367  fib_node_vft_t lb_fib_node_vft = {
1369  .fnv_last_lock = lb_fib_node_last_lock_gone,
1370  .fnv_back_walk = lb_fib_node_back_walk_notify,
1371  };
1372  dpo_vft_t lb_vft = {
1373  .dv_lock = lb_dpo_lock,
1374  .dv_unlock = lb_dpo_unlock,
1375  .dv_format = format_lb_dpo,
1376  };
1377 
1378  //Allocate and init default VIP.
1379  lbm->vips = 0;
1380  pool_get(lbm->vips, default_vip);
1381  default_vip->new_flow_table_mask = 0;
1382  default_vip->prefix.ip6.as_u64[0] = 0xffffffffffffffffL;
1383  default_vip->prefix.ip6.as_u64[1] = 0xffffffffffffffffL;
1384  default_vip->protocol = ~0;
1385  default_vip->port = 0;
1386  default_vip->flags = LB_VIP_FLAGS_USED;
1387 
1388  lbm->per_cpu = 0;
1389  vec_validate(lbm->per_cpu, tm->n_vlib_mains - 1);
1393  lbm->ip4_src_address.as_u32 = 0xffffffff;
1394  lbm->ip6_src_address.as_u64[0] = 0xffffffffffffffffL;
1395  lbm->ip6_src_address.as_u64[1] = 0xffffffffffffffffL;
1402  lbm->dpo_l3dsr_type = dpo_register_new_type(&lb_vft,
1410  lbm->fib_node_type = fib_node_register_new_type(&lb_fib_node_vft);
1411 
1412  //Init AS reference counters
1414 
1415  //Allocate and init default AS.
1416  lbm->ass = 0;
1417  pool_get(lbm->ass, default_as);
1418  default_as->flags = 0;
1419  default_as->dpo.dpoi_next_node = LB_NEXT_DROP;
1420  default_as->vip_index = ~0;
1421  default_as->address.ip6.as_u64[0] = 0xffffffffffffffffL;
1422  default_as->address.ip6.as_u64[1] = 0xffffffffffffffffL;
1423 
1424  /* Generate a valid flow table for default VIP */
1425  default_vip->as_indexes = NULL;
1427  lb_vip_update_new_flow_table(default_vip);
1429 
1431  = hash_create_mem (0, sizeof(u16), sizeof (uword));
1432 
1433  clib_bihash_init_8_8 (&lbm->vip_index_per_port,
1434  "vip_index_per_port", LB_VIP_PER_PORT_BUCKETS,
1436 
1437  clib_bihash_init_8_8 (&lbm->mapping_by_as4,
1438  "mapping_by_as4", LB_MAPPING_BUCKETS,
1440 
1441  clib_bihash_init_24_8 (&lbm->mapping_by_as6,
1442  "mapping_by_as6", LB_MAPPING_BUCKETS,
1444 
1445 #define _(a,b,c) lbm->vip_counters[c].name = b;
1447 #undef _
1448  return NULL;
1449 }
1450 
u32 skip
Definition: lb.c:273
int lb_vip_del_ass(u32 vip_index, ip46_address_t *addresses, u32 n, u8 flush)
Definition: lb.c:850
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:439
fib_protocol_t fp_proto
protocol type
Definition: fib_types.h:212
dpo_lock_fn_t dv_lock
A reference counting lock function.
Definition: dpo.h:406
static void lb_vip_add_adjacency(lb_main_t *lbm, lb_vip_t *vip, u32 *vip_prefix_index)
Add the VIP adjacency to the ip4 or ip6 fib.
Definition: lb.c:892
u64 as_u64
Definition: lb.h:423
u32 lb_hash_time_now(vlib_main_t *vm)
Definition: lb.c:93
static int lb_vip_port_find_all_port_vip(ip46_address_t *prefix, u8 plen, u32 *vip_index)
Definition: lb.c:535
typedef address
Definition: ip_types.api:83
u64 as_u64[3]
Definition: lb.h:438
int lb_nat4_interface_add_del(u32 sw_if_index, int is_del)
Definition: lb.c:1325
Recursive resolution source.
Definition: fib_entry.h:130
static int lb_pseudorand_compare(void *a, void *b)
Definition: lb.c:276
vnet_main_t * vnet_main
Definition: lb.h:569
Each VIP is configured with a set of application server.
Definition: lb.h:108
#define LB_GARBAGE_RUN
Definition: lb.c:24
#define CLIB_UNUSED(x)
Definition: clib.h:82
A virtual function table regisitered for a DPO type.
Definition: dpo.h:401
#define lb_vip_is_gre6(vip)
Definition: lb.h:354
a
Definition: bitmap.h:538
static bool lb_vip_is_l3dsr(const lb_vip_t *vip)
Definition: lb.h:367
#define lb_vip_is_gre6_port(vip)
Definition: lb.h:362
u32 last
Definition: lb.c:272
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
u32 fib_index
Definition: lb.h:436
u32 per_cpu_sticky_buckets
Number of buckets in the per-cpu sticky hash table.
Definition: lb.h:522
vl_api_fib_path_nh_t nh
Definition: fib_types.api:126
clib_error_t * lb_init(vlib_main_t *vm)
Definition: lb.c:1358
u64 as_u64
Definition: bihash_doc.h:63
u32 fib_entry_child_add(fib_node_index_t fib_entry_index, fib_node_type_t child_type, fib_node_index_t child_index)
Definition: fib_entry.c:556
static void lb_fib_node_last_lock_gone(fib_node_t *node)
Definition: lb.c:1275
u64 as_u64[2]
Definition: ip6_packet.h:51
static void lb_vip_update_new_flow_table(lb_vip_t *vip)
Definition: lb.c:379
unsigned long u64
Definition: types.h:89
static int lb_as_find_index_vip(lb_vip_t *vip, ip46_address_t *address, u32 *as_index)
Definition: lb.c:562
#define LB_VIP_PER_PORT_MEMORY_SIZE
Definition: lb.h:52
static const char *const lb_dpo_gre4_ip6_port[]
Definition: lb.c:54
#define NULL
Definition: clib.h:58
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:258
enum fib_node_back_walk_rc_t_ fib_node_back_walk_rc_t
Return code from a back walk function.
const dpo_id_t * fib_entry_contribute_ip_forwarding(fib_node_index_t fib_entry_index)
Definition: fib_entry.c:507
static int lb_vip_prefix_index_alloc(lb_main_t *lbm)
Definition: lb.c:860
static void lb_vip_del_adjacency(lb_main_t *lbm, lb_vip_t *vip)
Deletes the adjacency associated with the VIP.
Definition: lb.c:1010
int lb_conf(ip4_address_t *ip4_address, ip6_address_t *ip6_address, u32 per_cpu_sticky_buckets, u32 flow_timeout)
Fix global load-balancer parameters.
Definition: lb.c:473
#define lb_get_writer_lock()
Definition: lb.c:31
u8 * format_ip46_prefix(u8 *s, va_list *args)
Definition: util.c:54
int lb_vip_add_ass(u32 vip_index, ip46_address_t *addresses, u32 n)
Definition: lb.c:582
u32 index_t
A Data-Path Object is an object that represents actions that are applied to packets are they are swit...
Definition: dpo.h:41
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:522
ip46_address_t prefix
A Virtual IP represents a given service delivered by a set of application servers.
Definition: lb.h:292
#define clib_u32_loop_gt(a, b)
32 bits integer comparison for running values.
Definition: util.h:38
static u64 clib_xxhash(u64 key)
Definition: xxhash.h:58
static heap_elt_t * last(heap_header_t *h)
Definition: heap.c:53
u16 port
Definition: lb.h:419
static_always_inline void vlib_refcount_init(vlib_refcount_t *r)
Definition: refcount.h:80
int i
static void lb_dpo_lock(dpo_id_t *dpo)
Definition: lb.c:1263
static uword * clib_bitmap_set(uword *ai, uword i, uword value)
Sets the ith bit of a bitmap to new_value Removes trailing zeros from the bitmap. ...
Definition: bitmap.h:167
u32 vip_prefix_index
Definition: lb.h:245
format_function_t format_ip46_address
Definition: format.h:61
static u32 format_get_indent(u8 *s)
Definition: format.h:72
#define hash_set_mem(h, key, value)
Definition: hash.h:275
clib_memset(h->entries, 0, sizeof(h->entries[0])*entries)
#define STRUCT_OFFSET_OF(t, f)
Definition: clib.h:65
#define lb_vip_is_ip4(type)
Definition: lb.h:335
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
static void lb_as_stack(lb_as_t *as)
Definition: lb.c:1287
vl_api_mprefix_t prefix
Definition: ip.api:456
u32 vip[LBHASH_ENTRY_PER_BUCKET]
Definition: lbhash.h:54
#define lb_vip_get_by_index(index)
Definition: lb.h:607
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:236
u32 vip_index
ASs are indexed by address and VIP Index.
Definition: lb.h:127
#define vec_alloc(V, N)
Allocate space for N more elements (no header, unspecified alignment)
Definition: vec.h:280
static const char *const *const lb_dpo_gre6_nodes[DPO_PROTO_NUM]
Definition: lb.c:47
lb_hash_t * sticky_ht
Each CPU has its own sticky flow hash table.
Definition: lb.h:467
unsigned char u8
Definition: types.h:56
#define pool_len(p)
Number of elements in pool vector.
Definition: pool.h:140
fib_node_type_t fib_node_register_new_type(const fib_node_vft_t *vft)
Create a new FIB node type and Register the function table for it.
Definition: fib_node.c:80
static int lb_vip_del_port_filter(lb_main_t *lbm, lb_vip_t *vip)
Del the VIP filter entry.
Definition: lb.c:981
#define LB_MAPPING_BUCKETS
Definition: lb.h:48
#define LB_VIP_FLAGS_USED
Definition: lb.h:326
#define ip46_address_type(ip46)
Definition: util.h:26
ip46_address_t address
Destination address used to tunnel traffic towards that application server.
Definition: lb.h:120
u32 timeout
Definition: lbhash.h:60
static counter_t vlib_get_simple_counter(vlib_simple_counter_main_t *cm, u32 index)
Get the value of a simple counter Scrapes the entire set of per-thread counters.
Definition: counter.h:113
format_function_t format_ip4_address
Definition: format.h:75
#define LB_AS_FLAGS_USED
Definition: lb.h:135
enum dpo_type_t_ dpo_type_t
Common types of data-path objects New types can be dynamically added using dpo_register_new_type() ...
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:493
vl_api_interface_index_t sw_if_index
Definition: gre.api:50
u8 as_ip_is_ipv6
Definition: lb.h:450
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:173
static lb_as_t * lb_as_from_fib_node(fib_node_t *node)
Definition: lb.c:1280
void fib_table_entry_special_remove(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source)
Remove a &#39;special&#39; entry from the FIB.
Definition: fib_table.c:407
VLIB_PLUGIN_REGISTER()
u8 * format_white_space(u8 *s, va_list *va)
Definition: std-formats.c:129
lb_lkp_type_t
Lookup type.
Definition: lb.h:197
#define LB_DEFAULT_PER_CPU_STICKY_BUCKETS
lb-plugin implements a MagLev-like load balancer.
Definition: lb.h:46
#define LB_MAPPING_MEMORY_SIZE
Definition: lb.h:49
lb_main_t lb_main
Definition: lb.c:29
static const char *const lb_dpo_gre4_ip4[]
Definition: lb.c:37
u32 flow_timeout
Flow timeout in seconds.
Definition: lb.h:527
A high priority source a plugin can use.
Definition: fib_entry.h:67
u16 port
Definition: lb.h:304
Definition: lb.h:470
fib_node_type_t fib_node_type
Node type for registering to fib changes.
Definition: lb.h:548
dpo_type_t dpo_gre4_type
DPO used to send packet from IP4/6 lookup to LB node.
Definition: lb.h:537
Aggregrate type for a prefix.
Definition: fib_types.h:203
u16 protocol
Definition: lb.h:420
static const char *const *const lb_dpo_nat4_port_nodes[DPO_PROTO_NUM]
Definition: lb.c:82
u8 protocol
Definition: lb.h:301
vlib_refcount_t as_refcount
Each AS has an associated reference counter.
Definition: lb.h:494
lb_vip_encap_args_t encap_args
Definition: lb.h:316
static const char *const lb_dpo_gre6_ip4_port[]
Definition: lb.c:61
static void lb_vip_garbage_collection(lb_vip_t *vip)
Definition: lb.c:285
u8 * format_lb_main(u8 *s, va_list *args)
Definition: lb.c:98
uword * vip_prefix_indexes
bitmap for vip prefix to support per-port vip
Definition: lb.h:479
unsigned int u32
Definition: types.h:88
u8 * format_lb_vip(u8 *s, va_list *args)
Definition: lb.c:153
enum dpo_proto_t_ dpo_proto_t
Data path protocol.
u16 fp_len
The mask length.
Definition: fib_types.h:207
vlib_node_registration_t lb6_nodeport_node
(constructor) VLIB_REGISTER_NODE (lb6_nodeport_node)
Definition: node.c:1220
lb_vip_t * vips
Pool of all Virtual IPs.
Definition: lb.h:474
dpo_type_t dpo_register_new_type(const dpo_vft_t *vft, const char *const *const *nodes)
Create and register a new DPO type.
Definition: dpo.c:342
u32 last_used
Rotating timestamp of when LB_AS_FLAGS_USED flag was last set.
Definition: lb.h:146
ip4_address_t ip4_src_address
Source address used for IPv4 encapsulated traffic.
Definition: lb.h:517
static const char *const lb_dpo_l3dsr_ip4_port[]
Definition: lb.c:75
Definition: fib_entry.h:281
static void clib_spinlock_init(clib_spinlock_t *p)
Definition: lock.h:61
char * name
The counter collection&#39;s name.
Definition: counter.h:64
vl_api_fib_path_type_t type
Definition: fib_types.api:123
u8 plen
The VIP prefix length.
Definition: lb.h:298
The identity of a DPO is a combination of its type and its instance number/index of objects of that t...
Definition: dpo.h:170
static const char *const lb_dpo_nat6_ip6_port[]
Definition: lb.c:87
static const char *const lb_dpo_nat4_ip4_port[]
Definition: lb.c:81
#define hash_create_mem(elts, key_bytes, value_bytes)
Definition: hash.h:661
Definition: fib_entry.h:285
#define lb_vip_is_gre4(vip)
Definition: lb.h:349
static const char *const lb_dpo_gre6_ip4[]
Definition: lb.c:45
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:514
#define lb_vip_is_gre4_port(vip)
Definition: lb.h:358
static const char *const *const lb_dpo_gre4_port_nodes[DPO_PROTO_NUM]
Definition: lb.c:55
#define lb_encap_is_ip4(vip)
Definition: lb.h:344
u32 value[LBHASH_ENTRY_PER_BUCKET]
Definition: lbhash.h:55
ip46_address_t fp_addr
The address type is not deriveable from the fp_addr member.
Definition: fib_types.h:226
u64 key
the key
Definition: bihash_8_8.h:35
int lb_vip_del(u32 vip_index)
Definition: lb.c:1197
long ctx[MAX_CONNS]
Definition: main.c:144
vl_api_ip_proto_t protocol
Definition: punt.api:39
u8 * format_lb_vip_type(u8 *s, va_list *args)
Definition: lb.c:131
struct _unformat_input_t unformat_input_t
unsigned short u16
Definition: types.h:57
u16 src_port
Network byte order for vip + port case, src_port = port; for node ip + node_port, src_port = node_por...
Definition: lb.h:456
static const char *const *const lb_dpo_l3dsr_port_nodes[DPO_PROTO_NUM]
Definition: lb.c:76
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:286
uword unformat_lb_vip_type(unformat_input_t *input, va_list *args)
Definition: lb.c:141
int lb_flush_vip_as(u32 vip_index, u32 as_index)
Definition: lb.c:759
#define LB_DEFAULT_FLOW_TIMEOUT
Definition: lb.h:47
static int lb_vip_port_find_index(ip46_address_t *prefix, u8 plen, u8 protocol, u16 port, lb_lkp_type_t lkp_type, u32 *vip_index)
Definition: lb.c:493
void ip46_prefix_normalize(ip46_address_t *prefix, u8 plen)
Definition: util.c:18
vlib_node_registration_t lb4_nodeport_node
(constructor) VLIB_REGISTER_NODE (lb4_nodeport_node)
Definition: node.c:1204
u16 port
Definition: punt.api:40
clib_bihash_8_8_t mapping_by_as4
Definition: lb.h:554
static const char *const *const lb_dpo_gre4_nodes[DPO_PROTO_NUM]
Definition: lb.c:39
An node in the FIB graph.
Definition: fib_node.h:295
Definition: lb.h:167
fib_node_t fib_node
Registration to FIB event.
Definition: lb.h:112
u16 port
Definition: lb.h:246
u8 src_ip_is_ipv6
Definition: lb.h:449
static_always_inline void vlib_refcount_add(vlib_refcount_t *r, u32 thread_index, u32 counter_index, i32 v)
Definition: refcount.h:68
#define lb_hash_foreach_entry(h, bucket, i)
Definition: lbhash.h:72
ip46_address_t src_ip
for vip + port case, src_ip = vip; for node ip + node_port, src_ip = node_ip
Definition: lb.h:447
static const char *const lb_dpo_gre6_ip6[]
Definition: lb.c:46
u32 new_length
Definition: lb.h:579
static const dpo_vft_t lb_vft
Definition: load_balance.c:896
#define ip46_prefix_is_ip4(ip46, len)
Definition: util.h:27
#define pool_free(p)
Free a pool.
Definition: pool.h:407
static bool lb_vip_is_nat4_port(const lb_vip_t *vip)
Definition: lb.h:378
fib_node_index_t fib_table_entry_special_add(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, fib_entry_flag_t flags)
Add a &#39;special&#39; entry to the FIB.
Definition: fib_table.c:388
u64 value
the value
Definition: bihash_8_8.h:36
dpo_type_t dpo_l3dsr_port_type
Definition: lb.h:542
dpo_type_t dpo_nat4_port_type
Definition: lb.h:543
static const char *const lb_dpo_gre6_ip6_port[]
Definition: lb.c:62
format_function_t format_ip6_address
Definition: format.h:93
vlib_main_t * vm
Definition: buffer.c:312
static int lb_vip_prefix_index_free(lb_main_t *lbm, u32 instance)
Definition: lb.c:875
dpo_type_t dpo_gre4_port_type
Definition: lb.h:539
u32 vrf_id
Definition: lb.h:458
#define lb_vip_is_ip6(type)
Definition: lb.h:340
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:341
static bool lb_vip_is_nat6_port(const lb_vip_t *vip)
Definition: lb.h:383
#define lb_foreach_vip_counter
Definition: lb.h:171
#define clib_warning(format, args...)
Definition: error.h:59
vlib_main_t * vlib_main
Definition: lb.h:568
fib_node_get_t fnv_get
Definition: fib_node.h:283
u8 ip6_address[16]
Definition: ip_types.api:18
u32 fib_node_index_t
A typedef of a node index.
Definition: fib_types.h:30
u32 as_index
Definition: lb.h:168
8 octet key, 8 octet key value pair
Definition: bihash_8_8.h:33
static fib_node_back_walk_rc_t lb_fib_node_back_walk_notify(fib_node_t *node, fib_node_back_walk_ctx_t *ctx)
Definition: lb.c:1318
static uword clib_bitmap_get(uword *ai, uword i)
Gets the ith bit value from a bitmap.
Definition: bitmap.h:197
void dpo_set(dpo_id_t *dpo, dpo_type_t type, dpo_proto_t proto, index_t index)
Set/create a DPO ID The DPO will be locked.
Definition: dpo.c:186
dpo_type_t dpo_gre6_type
Definition: lb.h:538
u32 last_garbage_collection
Last time garbage collection was run to free the ASs.
Definition: lb.h:281
static_always_inline void lb_hash_free(lb_hash_t *h)
Definition: lbhash.h:100
lb_as_t * ass
Pool of ASs.
Definition: lb.h:487
uword * vip_index_by_nodeport
Definition: lb.h:497
ip6_address_t addr
Definition: lb.h:433
lb_vip_type_t type
The type of traffic for this.
Definition: lb.h:313
Context passed between object during a back walk.
Definition: fib_node.h:208
fib_node_index_t fib_table_entry_special_dpo_add(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, fib_entry_flag_t flags, const dpo_id_t *dpo)
Add a &#39;special&#39; entry to the FIB that links to the DPO passed A special entry is an entry that the FI...
Definition: fib_table.c:307
void vlib_validate_simple_counter(vlib_simple_counter_main_t *cm, u32 index)
validate a simple counter
Definition: counter.c:79
u8 value
Definition: qos.api:53
#define ASSERT(truth)
static int lb_vip_port_find_diff_port(ip46_address_t *prefix, u8 plen, u8 protocol, u16 port, u32 *vip_index)
Definition: lb.c:544
int lb_vip_del_ass_withlock(u32 vip_index, ip46_address_t *addresses, u32 n, u8 flush)
Definition: lb.c:793
lb_vip_type_t
The load balancer supports IPv4 and IPv6 traffic and GRE4, GRE6, L3DSR and NAT4, NAT6 encap...
Definition: lb.h:208
u16 target_port
Definition: lb.h:457
ip46_type_t
Definition: ip6_packet.h:70
int lb_vip_find_index(ip46_address_t *prefix, u8 plen, u8 protocol, u16 port, u32 *vip_index)
Definition: lb.c:551
u8 * format_lb_as(u8 *s, va_list *args)
Definition: lb.c:184
ip46_address_t prefix
Definition: lb.h:574
u32 new_flow_table_mask
New flows table length - 1 (length MUST be a power of 2)
Definition: lb.h:276
dpo_type_t dpo_gre6_port_type
Definition: lb.h:540
static const char *const *const lb_dpo_nat6_port_nodes[DPO_PROTO_NUM]
Definition: lb.c:88
static void vlib_zero_simple_counter(vlib_simple_counter_main_t *cm, u32 index)
Clear a simple counter Clears the set of per-thread u16 counters, and the u64 counter.
Definition: counter.h:139
size_t count
Definition: vapi.c:47
lb_vip_encap_args_t encap_args
Definition: lb.h:580
u32 vip_prefix_index
Definition: lb.h:307
lb_per_cpu_t * per_cpu
Some global data is per-cpu.
Definition: lb.h:502
static void lb_dpo_unlock(dpo_id_t *dpo)
Definition: lb.c:1264
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
static uword is_pow2(uword x)
Definition: clib.h:235
u16 target_port
Definition: lb.h:233
u32 as_index
Definition: lb.c:271
vlib_simple_counter_main_t vip_counters[LB_N_VIP_COUNTERS]
Per VIP counter.
Definition: lb.h:532
int lb_nat6_interface_add_del(u32 sw_if_index, int is_del)
Definition: lb.c:1341
u64 as_u64
Definition: lb.h:250
int lb_vip_add(lb_vip_add_args_t args, u32 *vip_index)
Definition: lb.c:1043
static int lb_vip_port_find_index_with_lock(ip46_address_t *prefix, u8 plen, u8 protocol, u16 port, u32 *vip_index)
Definition: lb.c:527
u8 ip4_address[4]
Definition: ip_types.api:17
static const char *const lb_dpo_gre4_ip6[]
Definition: lb.c:38
#define CLIB_SPINLOCK_ASSERT_LOCKED(_p)
Definition: lock.h:47
#define DPO_PROTO_NUM
Definition: dpo.h:70
#define LB_VIP_PER_PORT_BUCKETS
Definition: lb.h:51
ip6_address_t ip6_src_address
Source address used in IPv6 encapsulated traffic.
Definition: lb.h:512
u8 * format_lb_vip_detailed(u8 *s, va_list *args)
Definition: lb.c:192
vl_api_address_t ip
Definition: l2.api:489
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
static fib_node_t * lb_fib_node_get_node(fib_node_index_t index)
Definition: lb.c:1267
u32 instance
Definition: gre.api:48
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
clib_spinlock_t writer_lock
Definition: lb.h:565
lb_snat_mapping_t * snat_mappings
Definition: lb.h:558
typedef key
Definition: ipsec.api:245
#define DPO_INVALID
An initialiser for DPOs declared on the stack.
Definition: dpo.h:197
void lb_garbage_collection()
Definition: lb.c:354
static bool lb_vip_is_l3dsr_port(const lb_vip_t *vip)
Definition: lb.h:373
u8 protocol
Definition: lb.h:247
u16 port
Definition: lb.h:434
u32 next_hop_child_index
The child index on the FIB entry.
Definition: lb.h:156
dpo_type_t dpo_l3dsr_type
Definition: lb.h:541
#define hash_get_mem(h, key)
Definition: hash.h:269
A FIB graph nodes virtual function table.
Definition: fib_node.h:282
u32 fib_index
Definition: lb.h:459
static vlib_thread_main_t * vlib_get_thread_main()
Definition: global_funcs.h:32
clib_bihash_8_8_t vip_index_per_port
Definition: lb.h:551
static int lb_vip_add_port_filter(lb_main_t *lbm, lb_vip_t *vip, u32 vip_prefix_index, u32 vip_idx)
Add the VIP filter entry.
Definition: lb.c:960
void dpo_reset(dpo_id_t *dpo)
reset a DPO ID The DPO will be unlocked.
Definition: dpo.c:232
#define vec_foreach(var, vec)
Vector iterator.
u16 protocol
Definition: lb.h:435
dpo_id_t dpo
The next DPO in the graph to follow.
Definition: lb.h:161
static const char *const lb_dpo_l3dsr_ip4[]
Definition: lb.c:69
static const char *const lb_dpo_gre4_ip4_port[]
Definition: lb.c:53
u8 flags
Some per-AS flags.
Definition: lb.h:133
u16 dpoi_next_node
The next VLIB node to follow.
Definition: dpo.h:182
void udp_register_dst_port(vlib_main_t *vm, udp_dst_port_t dst_port, u32 node_index, u8 is_ip4)
Definition: udp_local.c:471
ip4_address_t addr
Definition: lb.h:418
clib_bihash_24_8_t mapping_by_as6
Definition: lb.h:555
lb_new_flow_entry_t * new_flow_table
Vector mapping (flow-hash & new_connect_table_mask) to AS index.
Definition: lb.h:270
static const char *const *const lb_dpo_l3dsr_nodes[DPO_PROTO_NUM]
Definition: lb.c:70
dpo_type_t dpo_nat6_port_type
Definition: lb.h:544
static uword clib_bitmap_first_clear(uword *ai)
Return the lowest numbered clear bit in a bitmap.
Definition: bitmap.h:445
u8 flags
Flags related to this VIP.
Definition: lb.h:325
lb_vip_type_t type
Definition: lb.h:578
static const char *const *const lb_dpo_gre6_port_nodes[DPO_PROTO_NUM]
Definition: lb.c:63
static char * lb_vip_type_strings[]
Definition: lb.c:121
u8 * format_lb_dpo(u8 *s, va_list *va)
Definition: lb.c:1254
ip46_address_t as_ip
Definition: lb.h:448
Load balancing service is provided per VIP+protocol+port.
Definition: lb.h:262
u32 * as_indexes
Pool of AS indexes used for this VIP.
Definition: lb.h:332
u16 fib_index
Definition: lb.h:420
#define lb_hash_size(h)
Definition: lbhash.h:65
u8 rsv
Definition: lb.h:248
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
vl_api_fib_path_nh_proto_t proto
Definition: fib_types.api:125
int vnet_feature_enable_disable(const char *arc_name, const char *node_name, u32 sw_if_index, int enable_disable, void *feature_config, u32 n_feature_config_bytes)
Definition: feature.c:274
void dpo_stack(dpo_type_t child_type, dpo_proto_t child_proto, dpo_id_t *dpo, const dpo_id_t *parent)
Stack one DPO object on another, and thus establish a child-parent relationship.
Definition: dpo.c:516
#define lb_put_writer_lock()
Definition: lb.c:32
fib_node_index_t next_hop_fib_entry_index
The FIB entry index for the next-hop.
Definition: lb.h:151
static_always_inline u32 lb_hash_elts(lb_hash_t *h, u32 time_now)
Definition: lbhash.h:186
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:128