FD.io VPP  v19.01.2-3-gf61a1a8
Vector Packet Processing
gbp_endpoint.c
Go to the documentation of this file.
1 /*
2  * gbp.h : Group Based Policy
3  *
4  * Copyright (c) 2018 Cisco and/or its affiliates.
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
20 #include <plugins/gbp/gbp_itf.h>
25 #include <plugins/gbp/gbp_vxlan.h>
26 
27 #include <vnet/ethernet/arp.h>
28 #include <vnet/l2/l2_input.h>
29 #include <vnet/l2/l2_output.h>
30 #include <vnet/l2/feat_bitmap.h>
31 #include <vnet/l2/l2_fib.h>
32 #include <vnet/fib/fib_table.h>
33 #include <vnet/ip/ip_neighbor.h>
34 #include <vnet/fib/fib_walk.h>
35 
37 
38 /**
39  * EP DBs
40  */
42 
44 
46 
47 #define GBP_ENDPOINT_DBG(...) \
48  vlib_log_debug (gbp_ep_logger, __VA_ARGS__);
49 
50 #define GBP_ENDPOINT_INFO(...) \
51  vlib_log_notice (gbp_ep_logger, __VA_ARGS__);
52 
53 /**
54  * GBP Endpoint inactive timeout (in seconds)
55  * If a dynamically learned Endpoint has not been heard from in this
56  * amount of time it is considered inactive and discarded
57  */
59 
60 /**
61  * Pool of GBP endpoints
62  */
64 
65 /**
66  * A count of the number of dynamic entries
67  */
69 
70 #define FOR_EACH_GBP_ENDPOINT_ATTR(_item) \
71  for (_item = GBP_ENDPOINT_ATTR_FIRST; \
72  _item < GBP_ENDPOINT_ATTR_LAST; \
73  _item++)
74 
75 u8 *
76 format_gbp_endpoint_flags (u8 * s, va_list * args)
77 {
80 
82  {
83  if ((1 << attr) & flags)
84  {
85  s = format (s, "%s,", gbp_endpoint_attr_names[attr]);
86  }
87  }
88 
89  return (s);
90 }
91 
92 int
94 {
95  return (! !(ge->ge_fwd.gef_flags & GBP_ENDPOINT_FLAG_REMOTE));
96 }
97 
98 int
100 {
101  return (!(ge->ge_fwd.gef_flags & GBP_ENDPOINT_FLAG_REMOTE));
102 }
103 
104 int
106 {
107  return (! !(ge->ge_fwd.gef_flags & GBP_ENDPOINT_FLAG_EXTERNAL));
108 }
109 
110 static void
113 {
114  mac_address_from_u64 (key->key[0], mac);
115  *sw_if_index = key->key[1];
116 }
117 
118 static void
120  ip46_address_t * ip, u32 * sw_if_index)
121 {
122  ip->as_u64[0] = key->key[0];
123  ip->as_u64[1] = key->key[1];
124  *sw_if_index = key->key[2];
125 }
126 
128 gbp_endpoint_find_ip (const ip46_address_t * ip, u32 fib_index)
129 {
130  clib_bihash_kv_24_8_t key, value;
131  int rv;
132 
133  gbp_endpoint_mk_key_ip (ip, fib_index, &key);
134 
135  rv = clib_bihash_search_24_8 (&gbp_ep_db.ged_by_ip_rd, &key, &value);
136 
137  if (0 != rv)
138  return NULL;
139 
140  return (gbp_endpoint_get (value.value));
141 }
142 
143 static void
145 {
146  vec_validate_init_empty (gbp_ep_db.ged_by_sw_if_index, sw_if_index, ~0);
147 
148  gbp_ep_db.ged_by_sw_if_index[sw_if_index] = gei;
149 }
150 
151 static bool
153 {
155  int rv;
156 
157  gbp_endpoint_mk_key_mac (mac->bytes, bd_index, &key);
158  key.value = gei;
159 
160  rv = clib_bihash_add_del_16_8 (&gbp_ep_db.ged_by_mac_bd, &key, 1);
161 
162 
163  return (0 == rv);
164 }
165 
166 static bool
167 gbp_endpoint_add_ip (const ip46_address_t * ip, u32 fib_index, index_t gei)
168 {
170  int rv;
171 
172  gbp_endpoint_mk_key_ip (ip, fib_index, &key);
173  key.value = gei;
174 
175  rv = clib_bihash_add_del_24_8 (&gbp_ep_db.ged_by_ip_rd, &key, 1);
176 
177  return (0 == rv);
178 }
179 
180 static void
182 {
184 
185  gbp_endpoint_mk_key_mac (mac->bytes, bd_index, &key);
186 
187  clib_bihash_add_del_16_8 (&gbp_ep_db.ged_by_mac_bd, &key, 0);
188 }
189 
190 static void
191 gbp_endpoint_del_ip (const ip46_address_t * ip, u32 fib_index)
192 {
194 
195  gbp_endpoint_mk_key_ip (ip, fib_index, &key);
196 
197  clib_bihash_add_del_24_8 (&gbp_ep_db.ged_by_ip_rd, &key, 0);
198 }
199 
200 static index_t
202 {
203  return (ge - gbp_endpoint_pool);
204 }
205 
206 static ip46_type_t
207 ip46_address_get_type (const ip46_address_t * a)
208 {
210 }
211 
212 static int
213 gbp_endpoint_ip_is_equal (const fib_prefix_t * fp, const ip46_address_t * ip)
214 {
215  return (ip46_address_is_equal (ip, &fp->fp_addr));
216 }
217 
218 static void
220  const ip46_address_t * ips,
221  const gbp_route_domain_t * grd)
222 {
223  const ip46_address_t *ip;
224  index_t gei, grdi;
225 
226  gei = gbp_endpoint_index (ge);
227  grdi = gbp_route_domain_index (grd);
228 
229  ASSERT ((ge->ge_key.gek_grd == INDEX_INVALID) ||
230  (ge->ge_key.gek_grd == grdi));
231 
232  vec_foreach (ip, ips)
233  {
234  if (~0 == vec_search_with_function (ge->ge_key.gek_ips, ip,
236  {
237  fib_prefix_t *pfx;
238 
239  vec_add2 (ge->ge_key.gek_ips, pfx, 1);
240  fib_prefix_from_ip46_addr (ip, pfx);
241 
243  grd->grd_fib_index[pfx->fp_proto], gei);
244  }
245  ge->ge_key.gek_grd = grdi;
246  }
247 }
248 
249 static gbp_endpoint_t *
250 gbp_endpoint_alloc (const ip46_address_t * ips,
251  const gbp_route_domain_t * grd,
252  const mac_address_t * mac,
253  const gbp_bridge_domain_t * gbd)
254 {
255  gbp_endpoint_t *ge;
256  index_t gei;
257 
258  pool_get_zero (gbp_endpoint_pool, ge);
259 
261  gei = gbp_endpoint_index (ge);
262  ge->ge_key.gek_gbd =
266 
267  if (NULL != mac)
268  {
269  mac_address_copy (&ge->ge_key.gek_mac, mac);
270  gbp_endpoint_add_mac (mac, gbd->gb_bd_index, gei);
271  }
272  gbp_endpoint_ips_update (ge, ips, grd);
273 
274  return (ge);
275 }
276 
277 static int
279 {
280  return (a->gel_src == b->gel_src);
281 }
282 
283 static int
285 {
286  return (a->gel_src - b->gel_src);
287 }
288 
289 static gbp_endpoint_loc_t *
291 {
292  gbp_endpoint_loc_t gel = {
293  .gel_src = src,
294  };
295  u32 pos;
296 
297  pos = vec_search_with_function (ge->ge_locs, &gel,
299 
300  if (~0 != pos)
301  return (&ge->ge_locs[pos]);
302 
303  return NULL;
304 }
305 
306 static int
308 {
309  u32 pos;
310 
311  gel->gel_locks--;
312 
313  if (0 == gel->gel_locks)
314  {
315  pos = gel - ge->ge_locs;
316 
317  vec_del1 (ge->ge_locs, pos);
318  if (vec_len (ge->ge_locs) > 1)
320 
321  /* This could be the last lock, so don't access the EP from
322  * this point on */
323  fib_node_unlock (&ge->ge_node);
324 
325  return (1);
326  }
327  return (0);
328 }
329 
330 static void
332 {
334 
336  {
338  }
339 }
340 
341 static gbp_endpoint_loc_t *
343 {
344  gbp_endpoint_loc_t gel = {
345  .gel_src = src,
346  .gel_epg = INDEX_INVALID,
347  .gel_sw_if_index = INDEX_INVALID,
348  .gel_locks = 0,
349  };
350  u32 pos;
351 
352  pos = vec_search_with_function (ge->ge_locs, &gel,
354 
355  if (~0 == pos)
356  {
357  vec_add1 (ge->ge_locs, gel);
358 
359  if (vec_len (ge->ge_locs) > 1)
360  {
362 
363  pos = vec_search_with_function (ge->ge_locs, &gel,
365  }
366  else
367  pos = 0;
368 
369  /*
370  * it's the sources and children that lock the endpoints
371  */
372  fib_node_lock (&ge->ge_node);
373  }
374 
375  return (&ge->ge_locs[pos]);
376 }
377 
378 /**
379  * Find an EP inthe DBs and check that if we find it in the L2 DB
380  * it has the same IPs as this update
381  */
382 static int
383 gbp_endpoint_find_for_update (const ip46_address_t * ips,
384  const gbp_route_domain_t * grd,
385  const mac_address_t * mac,
386  const gbp_bridge_domain_t * gbd,
387  gbp_endpoint_t ** ge)
388 {
389  gbp_endpoint_t *l2_ge, *l3_ge, *tmp;
390 
391  l2_ge = l3_ge = NULL;
392 
393  if (NULL != mac && !mac_address_is_zero (mac))
394  {
395  ASSERT (gbd);
396  l2_ge = gbp_endpoint_find_mac (mac->bytes, gbd->gb_bd_index);
397  }
398  if (NULL != ips && !ip46_address_is_zero (ips))
399  {
400  const ip46_address_t *ip;
401  fib_protocol_t fproto;
402 
403  ASSERT (grd);
404  vec_foreach (ip, ips)
405  {
407 
408  tmp = gbp_endpoint_find_ip (ip, grd->grd_fib_index[fproto]);
409 
410  if (NULL == tmp)
411  /* not found */
412  continue;
413  else if (NULL == l3_ge)
414  /* first match against an IP address */
415  l3_ge = tmp;
416  else if (tmp == l3_ge)
417  /* another match against IP address that is the same endpoint */
418  continue;
419  else
420  {
421  /*
422  * a match agains a different endpoint.
423  * this means the KEY of the EP is changing which is not allowed
424  */
425  return (-1);
426  }
427  }
428  }
429 
430  if (NULL == l2_ge && NULL == l3_ge)
431  /* not found */
432  *ge = NULL;
433  else if (NULL == l2_ge)
434  /* found at L3 */
435  *ge = l3_ge;
436  else if (NULL == l3_ge)
437  /* found at L2 */
438  *ge = l2_ge;
439  else
440  {
441  /* found both L3 and L2 - they must be the same else the KEY
442  * is changing
443  */
444  if (l2_ge == l3_ge)
445  *ge = l2_ge;
446  else
447  return (-1);
448  }
449 
450  return (0);
451 }
452 
453 static gbp_endpoint_src_t
455 {
456  if (0 == vec_len (ge->ge_locs))
457  return (GBP_ENDPOINT_SRC_MAX);
458 
459  return (ge->ge_locs[0].gel_src);
460 }
461 
462 static void
464 {
466 
467  if (n > 0 && 1 == gbp_n_learnt_endpoints)
468  {
470  gbp_scanner_node.index,
472  }
473  if (n < 0 && 0 == gbp_n_learnt_endpoints)
474  {
476  gbp_scanner_node.index,
478  }
479 }
480 
481 static void
484  index_t ggi,
486  const ip46_address_t * tun_src,
487  const ip46_address_t * tun_dst)
488 {
489  int was_learnt, is_learnt;
490 
491  gel->gel_locks++;
492  was_learnt = ! !(gel->gel_flags & GBP_ENDPOINT_FLAG_REMOTE);
493  gel->gel_flags = flags;
494  is_learnt = ! !(gel->gel_flags & GBP_ENDPOINT_FLAG_REMOTE);
495 
496  gbp_endpoint_n_learned (is_learnt - was_learnt);
497 
498  if (INDEX_INVALID == gel->gel_epg)
499  {
500  gel->gel_epg = ggi;
501  if (INDEX_INVALID != gel->gel_epg)
502  {
504  }
505  }
506  else
507  {
508  ASSERT (gel->gel_epg == ggi);
509  }
510 
512  {
513  if (NULL != tun_src)
514  ip46_address_copy (&gel->tun.gel_src, tun_src);
515  if (NULL != tun_dst)
516  ip46_address_copy (&gel->tun.gel_dst, tun_dst);
517 
518  /*
519  * the input interface may be the parent GBP-vxlan interface,
520  * create a child vlxan-gbp tunnel and use that as the endpoint's
521  * interface.
522  */
523  if (~0 != gel->gel_sw_if_index)
525 
526  switch (gbp_vxlan_tunnel_get_type (sw_if_index))
527  {
530  gel->gel_sw_if_index =
531  gbp_vxlan_tunnel_clone_and_lock (sw_if_index,
532  &gel->tun.gel_src,
533  &gel->tun.gel_dst);
534  break;
535  case VXLAN_GBP_TUNNEL:
537  vxlan_gbp_tunnel_get_parent (sw_if_index);
540  break;
541  }
542  }
543  else
544  {
546  }
547 }
548 
549 static void
551 {
552  const gbp_route_domain_t *grd;
553  const gbp_bridge_domain_t *gbd;
554  gbp_endpoint_fwd_t *gef;
555  const fib_prefix_t *pfx;
556  index_t *ai;
557  index_t gei;
558 
559  gei = gbp_endpoint_index (ge);
561  gef = &ge->ge_fwd;
562 
563  vec_foreach (pfx, ge->ge_key.gek_ips)
564  {
565  u32 fib_index;
566 
567  grd = gbp_route_domain_get (ge->ge_key.gek_grd);
568  fib_index = grd->grd_fib_index[pfx->fp_proto];
569 
571  &pfx->fp_addr, &ge->ge_key.gek_mac, 0);
572 
573  /*
574  * remove a host route
575  */
576  if (gbp_endpoint_is_remote (ge))
577  {
579  }
580 
582  }
583  vec_foreach (ai, gef->gef_adjs)
584  {
585  adj_unlock (*ai);
586  }
587 
588  if (INDEX_INVALID != gef->gef_itf)
589  {
591  gbd->gb_bd_index, gef->gef_itf);
594 
595  gbp_itf_unlock (gef->gef_itf);
596  gef->gef_itf = INDEX_INVALID;
597  }
598 
599  vec_free (gef->gef_adjs);
600 }
601 
602 static void
604 {
605  const gbp_route_domain_t *grd;
606  const gbp_bridge_domain_t *gbd;
607  const gbp_endpoint_group_t *gg;
608  gbp_endpoint_loc_t *gel;
609  gbp_endpoint_fwd_t *gef;
610  const fib_prefix_t *pfx;
611  index_t gei;
612 
613  /*
614  * locations are sort in source priority order
615  */
616  gei = gbp_endpoint_index (ge);
617  gel = &ge->ge_locs[0];
618  gef = &ge->ge_fwd;
620 
621  gef->gef_flags = gel->gel_flags;
622 
623  if (INDEX_INVALID != gel->gel_epg)
624  {
625  gg = gbp_endpoint_group_get (gel->gel_epg);
626  gef->gef_epg_id = gg->gg_id;
627  }
628  else
629  {
630  gg = NULL;
631  }
632 
634  gbd->gb_bd_index);
635 
636  if (!mac_address_is_zero (&ge->ge_key.gek_mac))
637  {
638  gbp_itf_set_l2_input_feature (gef->gef_itf, gei, L2INPUT_FEAT_GBP_FWD);
639 
641  {
642  /*
643  * bridged packets to external endpoints should be classifed
644  * based on the EP's/BD's EPG
645  */
647  L2OUTPUT_FEAT_GBP_POLICY_MAC);
648  }
649  else
650  {
651  gbp_endpoint_add_itf (gef->gef_itf, gei);
653  L2OUTPUT_FEAT_GBP_POLICY_PORT);
654  }
656  gbd->gb_bd_index,
657  gef->gef_itf, L2FIB_ENTRY_RESULT_FLAG_STATIC);
658  }
659 
660  vec_foreach (pfx, ge->ge_key.gek_ips)
661  {
662  ethernet_header_t *eth;
663  u32 ip_sw_if_index;
664  u32 fib_index;
665  u8 *rewrite;
666  index_t ai;
667 
668  rewrite = NULL;
669  grd = gbp_route_domain_get (ge->ge_key.gek_grd);
670  fib_index = grd->grd_fib_index[pfx->fp_proto];
671 
673  &pfx->fp_addr, &ge->ge_key.gek_mac, 1);
674 
675  /*
676  * add a host route via the EPG's BVI we need this because the
677  * adj fib does not install, due to cover refinement check, since
678  * the BVI's prefix is /32
679  */
680  vec_validate (rewrite, sizeof (*eth) - 1);
681  eth = (ethernet_header_t *) rewrite;
682 
683  eth->type = clib_host_to_net_u16 ((pfx->fp_proto == FIB_PROTOCOL_IP4 ?
684  ETHERNET_TYPE_IP4 :
685  ETHERNET_TYPE_IP6));
686 
687  if (gbp_endpoint_is_remote (ge))
688  {
689  /*
690  * for dynamic EPs we must add the IP adjacency via the learned
691  * tunnel since the BD will not contain the EP's MAC since it was
692  * L3 learned. The dst MAC address used is the 'BD's MAC'.
693  */
694  ip_sw_if_index = gef->gef_itf;
695 
697  eth->src_address);
699  eth->dst_address);
700  }
701  else
702  {
703  /*
704  * for the static EPs we add the IP adjacency via the BVI
705  * knowing that the BD has the MAC address to route to and
706  * that policy will be applied on egress to the EP's port
707  */
708  ip_sw_if_index = gbd->gb_bvi_sw_if_index;
709 
710  clib_memcpy (eth->src_address,
712  ip_sw_if_index),
713  sizeof (eth->src_address));
715  }
716 
717  fib_table_entry_path_add (fib_index, pfx,
720  fib_proto_to_dpo (pfx->fp_proto),
721  &pfx->fp_addr, ip_sw_if_index,
723 
726  &pfx->fp_addr,
727  ip_sw_if_index, rewrite);
728  vec_add1 (gef->gef_adjs, ai);
729 
730  /*
731  * if the endpoint is external then routed packet to it must be
732  * classifed to the BD's EPG. but this will happen anyway with
733  * the GBP_MAC classification.
734  */
735 
736  if (NULL != gg)
737  {
738  if (gbp_endpoint_is_remote (ge))
739  {
740  dpo_id_t policy_dpo = DPO_INVALID;
741 
742  /*
743  * interpose a policy DPO from the endpoint so that policy
744  * is applied
745  */
747  gg->gg_id, ~0, &policy_dpo);
748 
749  fib_table_entry_special_dpo_add (fib_index, pfx,
752  &policy_dpo);
753  dpo_reset (&policy_dpo);
754  }
755 
756  /*
757  * send a gratuitous ARP on the EPG's uplink. this is done so
758  * that if this EP has moved from some other place in the
759  * 'fabric', upstream devices are informed
760  */
761  if (gbp_endpoint_is_local (ge) && ~0 != gg->gg_uplink_sw_if_index)
762  {
763  gbp_endpoint_add_itf (gef->gef_itf, gei);
764  if (FIB_PROTOCOL_IP4 == pfx->fp_proto)
766  &pfx->fp_addr.ip4,
768  else
770  &pfx->fp_addr.ip6,
772  }
773  }
774  }
775 
777  {
778  /*
779  * non-remote endpoints (i.e. those not arriving on iVXLAN
780  * tunnels) need to be classifed based on the the input interface.
781  * We enable the GBP-FWD feature only if the group has an uplink
782  * interface (on which the GBP-FWD feature would send UU traffic).
783  * External endpoints get classified based on an LPM match
784  */
785  l2input_feat_masks_t feats = L2INPUT_FEAT_GBP_SRC_CLASSIFY;
786 
787  if (NULL != gg && ~0 != gg->gg_uplink_sw_if_index)
788  feats |= L2INPUT_FEAT_GBP_FWD;
789  gbp_itf_set_l2_input_feature (gef->gef_itf, gei, feats);
790  }
791 
792  /*
793  * update children with the new forwarding info
794  */
795  fib_node_back_walk_ctx_t bw_ctx = {
797  .fnbw_flags = FIB_NODE_BW_FLAG_FORCE_SYNC,
798  };
799 
800  fib_walk_sync (gbp_endpoint_fib_type, gei, &bw_ctx);
801 }
802 
803 int
806  const ip46_address_t * ips,
807  const mac_address_t * mac,
808  index_t gbdi, index_t grdi, epg_id_t epg_id,
810  const ip46_address_t * tun_src,
811  const ip46_address_t * tun_dst, u32 * handle)
812 {
813  gbp_bridge_domain_t *gbd;
815  gbp_endpoint_src_t best;
816  gbp_route_domain_t *grd;
817  gbp_endpoint_loc_t *gel;
818  gbp_endpoint_t *ge;
819  index_t ggi, gei;
820  int rv;
821 
822  if (~0 == sw_if_index)
823  return (VNET_API_ERROR_INVALID_SW_IF_INDEX);
824 
825  ge = NULL;
826  gg = NULL;
827 
828  /*
829  * we need to determine the bridge-domain, either from the EPG or
830  * the BD passed
831  */
832  if (EPG_INVALID != epg_id)
833  {
834  ggi = gbp_endpoint_group_find (epg_id);
835 
836  if (INDEX_INVALID == ggi)
837  return (VNET_API_ERROR_NO_SUCH_ENTRY);
838 
839  gg = gbp_endpoint_group_get (ggi);
840  gbdi = gg->gg_gbd;
841  grdi = gg->gg_rd;
842  }
843  else
844  {
845  if (INDEX_INVALID == gbdi)
846  return (VNET_API_ERROR_NO_SUCH_ENTRY);
847  if (INDEX_INVALID == grdi)
848  return (VNET_API_ERROR_NO_SUCH_FIB);
849  ggi = INDEX_INVALID;
850  }
851 
852  gbd = gbp_bridge_domain_get (gbdi);
853  grd = gbp_route_domain_get (grdi);
854  rv = gbp_endpoint_find_for_update (ips, grd, mac, gbd, &ge);
855 
856  if (0 != rv)
857  return (rv);
858 
859  if (NULL == ge)
860  {
861  ge = gbp_endpoint_alloc (ips, grd, mac, gbd);
862  }
863  else
864  {
865  gbp_endpoint_ips_update (ge, ips, grd);
866  }
867 
868  best = gbp_endpoint_get_best_src (ge);
869  gei = gbp_endpoint_index (ge);
870  gel = gbp_endpoint_loc_find_or_add (ge, src);
871 
872  gbp_endpoint_loc_update (gel, sw_if_index, ggi, flags, tun_src, tun_dst);
873 
874  if (src <= best)
875  {
876  /*
877  * either the best source has been updated or we have a new best source
878  */
881  }
882  else
883  {
884  /*
885  * an update to a lower priority source, so we need do nothing
886  */
887  }
888 
889  if (handle)
890  *handle = gei;
891 
892  GBP_ENDPOINT_INFO ("update: %U", format_gbp_endpoint, gei);
893 
894  return (0);
895 }
896 
897 void
899 {
900  gbp_endpoint_loc_t *gel, gel_copy;
901  gbp_endpoint_src_t best;
902  gbp_endpoint_t *ge;
903  int removed;
904 
905  if (pool_is_free_index (gbp_endpoint_pool, gei))
906  return;
907 
908  GBP_ENDPOINT_INFO ("delete: %U", format_gbp_endpoint, gei);
909 
910  ge = gbp_endpoint_get (gei);
911 
912  gel = gbp_endpoint_loc_find (ge, src);
913 
914  if (NULL == gel)
915  return;
916 
917  /*
918  * lock the EP so we can control when it is deleted
919  */
920  fib_node_lock (&ge->ge_node);
921  best = gbp_endpoint_get_best_src (ge);
922 
923  /*
924  * copy the location info since we'll lose it when it's removed from
925  * the vector
926  */
927  clib_memcpy (&gel_copy, gel, sizeof (gel_copy));
928 
929  /*
930  * remove the source we no longer need
931  */
932  removed = gbp_endpoint_loc_unlock (ge, gel);
933 
934  if (src == best)
935  {
936  /*
937  * we have removed the old best source => recalculate fwding
938  */
939  if (0 == vec_len (ge->ge_locs))
940  {
941  /*
942  * if there are no more sources left, then we need only release
943  * the fwding resources held and then this EP is gawn.
944  */
946  }
947  else
948  {
949  /*
950  * else there are more sources. release the old and get new
951  * fwding objects
952  */
955  }
956  }
957  /*
958  * else
959  * we removed a lower priority source so we need to do nothing
960  */
961 
962  /*
963  * clear up any resources held by the source
964  */
965  if (removed)
966  gbp_endpoint_loc_destroy (&gel_copy);
967 
968  /*
969  * remove the lock taken above
970  */
971  fib_node_unlock (&ge->ge_node);
972  /*
973  * We may have removed the last source and so this EP is now TOAST
974  * DO NOTHING BELOW HERE
975  */
976 }
977 
978 u32
980  fib_node_type_t type, fib_node_index_t index)
981 {
982  return (fib_node_child_add (gbp_endpoint_fib_type, gei, type, index));
983 }
984 
985 void
987 {
988  return (fib_node_child_remove (gbp_endpoint_fib_type, gei, sibling));
989 }
990 
992 {
997 
998 static walk_rc_t
1000 {
1001  gbp_endpoint_flush_ctx_t *ctx = args;
1002  gbp_endpoint_loc_t *gel;
1003  gbp_endpoint_t *ge;
1004 
1005  ge = gbp_endpoint_get (gei);
1006  gel = gbp_endpoint_loc_find (ge, ctx->src);
1007 
1008  if ((NULL != gel) && ctx->sw_if_index == gel->tun.gel_parent_sw_if_index)
1009  {
1010  vec_add1 (ctx->geis, gei);
1011  }
1012 
1013  return (WALK_CONTINUE);
1014 }
1015 
1016 /**
1017  * remove all learnt endpoints using the interface
1018  */
1019 void
1021 {
1023  .sw_if_index = sw_if_index,
1024  .src = src,
1025  };
1026  index_t *gei;
1027 
1028  GBP_ENDPOINT_INFO ("flush: %U %U",
1031  sw_if_index);
1033 
1034  vec_foreach (gei, ctx.geis)
1035  {
1036  gbp_endpoint_unlock (src, *gei);
1037  }
1038 
1039  vec_free (ctx.geis);
1040 }
1041 
1042 void
1044 {
1045  u32 index;
1046 
1047  /* *INDENT-OFF* */
1048  pool_foreach_index(index, gbp_endpoint_pool,
1049  {
1050  if (!cb(index, ctx))
1051  break;
1052  });
1053  /* *INDENT-ON* */
1054 }
1055 
1056 static clib_error_t *
1058  unformat_input_t * input, vlib_cli_command_t * cmd)
1059 {
1060  ip46_address_t ip = ip46_address_initializer, *ips = NULL;
1062  vnet_main_t *vnm = vnet_get_main ();
1064  u32 handle = INDEX_INVALID;
1065  u32 sw_if_index = ~0;
1066  u8 add = 1;
1067  int rv;
1068 
1069  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1070  {
1071  ip46_address_reset (&ip);
1072 
1073  if (unformat (input, "%U", unformat_vnet_sw_interface,
1074  vnm, &sw_if_index))
1075  ;
1076  else if (unformat (input, "add"))
1077  add = 1;
1078  else if (unformat (input, "del"))
1079  add = 0;
1080  else if (unformat (input, "epg %d", &epg_id))
1081  ;
1082  else if (unformat (input, "handle %d", &handle))
1083  ;
1084  else if (unformat (input, "ip %U", unformat_ip4_address, &ip.ip4))
1085  vec_add1 (ips, ip);
1086  else if (unformat (input, "ip %U", unformat_ip6_address, &ip.ip6))
1087  vec_add1 (ips, ip);
1088  else if (unformat (input, "mac %U", unformat_mac_address, &mac))
1089  ;
1090  else
1091  break;
1092  }
1093 
1094  if (add)
1095  {
1096  if (~0 == sw_if_index)
1097  return clib_error_return (0, "interface must be specified");
1098  if (EPG_INVALID == epg_id)
1099  return clib_error_return (0, "EPG-ID must be specified");
1100 
1101  rv =
1102  gbp_endpoint_update_and_lock (GBP_ENDPOINT_SRC_CP,
1103  sw_if_index, ips, &mac,
1105  epg_id,
1107  NULL, NULL, &handle);
1108 
1109  if (rv)
1110  return clib_error_return (0, "GBP Endpoint update returned %d", rv);
1111  else
1112  vlib_cli_output (vm, "handle %d\n", handle);
1113  }
1114  else
1115  {
1116  if (INDEX_INVALID == handle)
1117  return clib_error_return (0, "handle must be specified");
1118 
1119  gbp_endpoint_unlock (GBP_ENDPOINT_SRC_CP, handle);
1120  }
1121 
1122  vec_free (ips);
1123 
1124  return (NULL);
1125 }
1126 
1127 /*?
1128  * Configure a GBP Endpoint
1129  *
1130  * @cliexpar
1131  * @cliexstart{set gbp endpoint [del] <interface> epg <ID> ip <IP>}
1132  * @cliexend
1133  ?*/
1134 /* *INDENT-OFF* */
1135 VLIB_CLI_COMMAND (gbp_endpoint_cli_node, static) = {
1136  .path = "gbp endpoint",
1137  .short_help = "gbp endpoint [del] <interface> epg <ID> ip <IP> mac <MAC>",
1138  .function = gbp_endpoint_cli,
1139 };
1140 /* *INDENT-ON* */
1141 
1142 u8 *
1143 format_gbp_endpoint_src (u8 * s, va_list * args)
1144 {
1145  gbp_endpoint_src_t action = va_arg (*args, gbp_endpoint_src_t);
1146 
1147  switch (action)
1148  {
1149 #define _(v,a) case GBP_ENDPOINT_SRC_##v: return (format (s, "%s", a));
1151 #undef _
1152  }
1153 
1154  return (format (s, "unknown"));
1155 }
1156 
1157 static u8 *
1158 format_gbp_endpoint_fwd (u8 * s, va_list * args)
1159 {
1160  gbp_endpoint_fwd_t *gef = va_arg (*args, gbp_endpoint_fwd_t *);
1161 
1162  s = format (s, "fwd:");
1163  s = format (s, "\n itf:[%U]", format_gbp_itf, gef->gef_itf);
1164  if (GBP_ENDPOINT_FLAG_NONE != gef->gef_flags)
1165  {
1166  s = format (s, " flags:%U", format_gbp_endpoint_flags, gef->gef_flags);
1167  }
1168 
1169  return (s);
1170 }
1171 
1172 static u8 *
1173 format_gbp_endpoint_key (u8 * s, va_list * args)
1174 {
1175  gbp_endpoint_key_t *gek = va_arg (*args, gbp_endpoint_key_t *);
1176  const fib_prefix_t *pfx;
1177 
1178  s = format (s, "ips:[");
1179 
1180  vec_foreach (pfx, gek->gek_ips)
1181  {
1182  s = format (s, "%U, ", format_fib_prefix, pfx);
1183  }
1184  s = format (s, "]");
1185 
1186  s = format (s, " mac:%U", format_mac_address_t, &gek->gek_mac);
1187 
1188  return (s);
1189 }
1190 
1191 static u8 *
1192 format_gbp_endpoint_loc (u8 * s, va_list * args)
1193 {
1194  gbp_endpoint_loc_t *gel = va_arg (*args, gbp_endpoint_loc_t *);
1195 
1196  s = format (s, "%U", format_gbp_endpoint_src, gel->gel_src);
1197  s =
1199  gel->gel_sw_if_index);
1200  s = format (s, " EPG:%d", gel->gel_epg);
1201 
1202  if (GBP_ENDPOINT_FLAG_NONE != gel->gel_flags)
1203  {
1204  s = format (s, " flags:%U", format_gbp_endpoint_flags, gel->gel_flags);
1205  }
1207  {
1208  s = format (s, " tun:[");
1209  s = format (s, "parent:%U", format_vnet_sw_if_index_name,
1211  s = format (s, " {%U,%U}]",
1214  }
1215 
1216  return (s);
1217 }
1218 
1219 u8 *
1220 format_gbp_endpoint (u8 * s, va_list * args)
1221 {
1222  index_t gei = va_arg (*args, index_t);
1223  gbp_endpoint_loc_t *gel;
1224  gbp_endpoint_t *ge;
1225 
1226  ge = gbp_endpoint_get (gei);
1227 
1228  s = format (s, "[@%d] %U", gei, format_gbp_endpoint_key, &ge->ge_key);
1229  s = format (s, " last-time:[%f]", ge->ge_last_time);
1230 
1231  vec_foreach (gel, ge->ge_locs)
1232  {
1233  s = format (s, "\n %U", format_gbp_endpoint_loc, gel);
1234  }
1235  s = format (s, "\n %U", format_gbp_endpoint_fwd, &ge->ge_fwd);
1236 
1237  return s;
1238 }
1239 
1240 static walk_rc_t
1242 {
1243  vlib_main_t *vm;
1244 
1245  vm = ctx;
1246  vlib_cli_output (vm, " %U", format_gbp_endpoint, gei);
1247 
1248  return (WALK_CONTINUE);
1249 }
1250 
1251 static void
1253 {
1254  ip46_address_t ip;
1255  vlib_main_t *vm;
1256  u32 sw_if_index;
1257 
1258  vm = arg;
1259 
1260  gbp_endpoint_extract_key_ip_itf (kvp, &ip, &sw_if_index);
1261 
1262  vlib_cli_output (vm, " {%U, %U} -> %d",
1265  sw_if_index, kvp->value);
1266 }
1267 
1268 static void
1270 {
1272  vlib_main_t *vm;
1273  u32 sw_if_index;
1274 
1275  vm = arg;
1276 
1277  gbp_endpoint_extract_key_mac_itf (kvp, &mac, &sw_if_index);
1278 
1279  vlib_cli_output (vm, " {%U, %U} -> %d",
1280  format_mac_address_t, &mac,
1282  sw_if_index, kvp->value);
1283 }
1284 
1285 static clib_error_t *
1287  unformat_input_t * input, vlib_cli_command_t * cmd)
1288 {
1289  u32 show_dbs, handle;
1290 
1291  handle = INDEX_INVALID;
1292  show_dbs = 0;
1293 
1294  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1295  {
1296  if (unformat (input, "%d", &handle))
1297  ;
1298  else if (unformat (input, "db"))
1299  show_dbs = 1;
1300  else
1301  break;
1302  }
1303 
1304  if (INDEX_INVALID != handle)
1305  {
1306  vlib_cli_output (vm, "%U", format_gbp_endpoint, handle);
1307  }
1308  else if (show_dbs)
1309  {
1310  vlib_cli_output (vm, "\nDatabases:");
1311  clib_bihash_foreach_key_value_pair_24_8 (&gbp_ep_db.ged_by_ip_rd,
1313  clib_bihash_foreach_key_value_pair_16_8
1314  (&gbp_ep_db.ged_by_mac_bd, gbp_endpoint_walk_mac_itf, vm);
1315  }
1316  else
1317  {
1318  vlib_cli_output (vm, "Endpoints:");
1320  }
1321 
1322  return (NULL);
1323 }
1324 
1325 /*?
1326  * Show Group Based Policy Endpoints and derived information
1327  *
1328  * @cliexpar
1329  * @cliexstart{show gbp endpoint}
1330  * @cliexend
1331  ?*/
1332 /* *INDENT-OFF* */
1333 VLIB_CLI_COMMAND (gbp_endpoint_show_node, static) = {
1334  .path = "show gbp endpoint",
1335  .short_help = "show gbp endpoint\n",
1336  .function = gbp_endpoint_show,
1337 };
1338 /* *INDENT-ON* */
1339 
1340 static void
1341 gbp_endpoint_check (index_t gei, f64 start_time)
1342 {
1343  gbp_endpoint_loc_t *gel;
1344  gbp_endpoint_t *ge;
1345 
1346  ge = gbp_endpoint_get (gei);
1347  gel = gbp_endpoint_loc_find (ge, GBP_ENDPOINT_SRC_DP);
1348 
1349  if ((NULL != gel) &&
1350  ((start_time - ge->ge_last_time) > GBP_ENDPOINT_INACTIVE_TIME))
1351  {
1352  gbp_endpoint_unlock (GBP_ENDPOINT_SRC_DP, gei);
1353  }
1354 }
1355 
1356 static void
1358 {
1359  clib_bihash_16_8_t *gte_table = &gbp_ep_db.ged_by_mac_bd;
1360  f64 last_start, start_time, delta_t;
1361  int i, j, k;
1362 
1363  delta_t = 0;
1364  last_start = start_time = vlib_time_now (vm);
1365 
1366  for (i = 0; i < gte_table->nbuckets; i++)
1367  {
1368  clib_bihash_bucket_16_8_t *b;
1369  clib_bihash_value_16_8_t *v;
1370 
1371  /* allow no more than 20us without a pause */
1372  delta_t = vlib_time_now (vm) - last_start;
1373  if (delta_t > 20e-6)
1374  {
1375  /* suspend for 100 us */
1376  vlib_process_suspend (vm, 100e-6);
1377  last_start = vlib_time_now (vm);
1378  }
1379 
1380  b = &gte_table->buckets[i];
1381  if (b->offset == 0)
1382  continue;
1383  v = clib_bihash_get_value_16_8 (gte_table, b->offset);
1384 
1385  for (j = 0; j < (1 << b->log2_pages); j++)
1386  {
1387  for (k = 0; k < BIHASH_KVP_PER_PAGE; k++)
1388  {
1389  if (clib_bihash_is_free_16_8 (&v->kvp[k]))
1390  continue;
1391 
1392  gbp_endpoint_check (v->kvp[k].value, start_time);
1393 
1394  /*
1395  * Note: we may have just freed the bucket's backing
1396  * storage, so check right here...
1397  */
1398  if (b->offset == 0)
1399  goto doublebreak;
1400  }
1401  v++;
1402  }
1403  doublebreak:
1404  ;
1405  }
1406 }
1407 
1408 static void
1410 {
1411  clib_bihash_24_8_t *gte_table = &gbp_ep_db.ged_by_ip_rd;
1412  f64 last_start, start_time, delta_t;
1413  int i, j, k;
1414 
1415  delta_t = 0;
1416  last_start = start_time = vlib_time_now (vm);
1417 
1418  for (i = 0; i < gte_table->nbuckets; i++)
1419  {
1420  clib_bihash_bucket_24_8_t *b;
1421  clib_bihash_value_24_8_t *v;
1422 
1423  /* allow no more than 20us without a pause */
1424  delta_t = vlib_time_now (vm) - last_start;
1425  if (delta_t > 20e-6)
1426  {
1427  /* suspend for 100 us */
1428  vlib_process_suspend (vm, 100e-6);
1429  last_start = vlib_time_now (vm);
1430  }
1431 
1432  b = &gte_table->buckets[i];
1433  if (b->offset == 0)
1434  continue;
1435  v = clib_bihash_get_value_24_8 (gte_table, b->offset);
1436 
1437  for (j = 0; j < (1 << b->log2_pages); j++)
1438  {
1439  for (k = 0; k < BIHASH_KVP_PER_PAGE; k++)
1440  {
1441  if (clib_bihash_is_free_24_8 (&v->kvp[k]))
1442  continue;
1443 
1444  gbp_endpoint_check (v->kvp[k].value, start_time);
1445 
1446  /*
1447  * Note: we may have just freed the bucket's backing
1448  * storage, so check right here...
1449  */
1450  if (b->offset == 0)
1451  goto doublebreak;
1452  }
1453  v++;
1454  }
1455  doublebreak:
1456  ;
1457  }
1458 }
1459 
1460 void
1462 {
1463  gbp_endpoint_scan_l2 (vm);
1464  gbp_endpoint_scan_l3 (vm);
1465 }
1466 
1467 void
1469 {
1470  GBP_ENDPOINT_INACTIVE_TIME = threshold;
1471 
1473  gbp_scanner_node.index,
1475 }
1476 
1477 f64
1479 {
1480  return (GBP_ENDPOINT_INACTIVE_TIME);
1481 }
1482 
1483 static fib_node_t *
1485 {
1486  gbp_endpoint_t *ge;
1487 
1488  ge = gbp_endpoint_get (index);
1489 
1490  return (&ge->ge_node);
1491 }
1492 
1493 static gbp_endpoint_t *
1495 {
1497  return ((gbp_endpoint_t *) node);
1498 }
1499 
1500 static void
1502 {
1503  const gbp_bridge_domain_t *gbd;
1504  const gbp_route_domain_t *grd;
1505  const fib_prefix_t *pfx;
1506  gbp_endpoint_t *ge;
1507 
1508  ge = gbp_endpoint_from_fib_node (node);
1509 
1510  ASSERT (0 == vec_len (ge->ge_locs));
1511 
1512  gbd = gbp_bridge_domain_get (ge->ge_key.gek_gbd);
1513 
1514  /*
1515  * we have removed the last source. this EP is toast
1516  */
1517  if (INDEX_INVALID != ge->ge_key.gek_gbd)
1518  {
1520  }
1521  vec_foreach (pfx, ge->ge_key.gek_ips)
1522  {
1523  grd = gbp_route_domain_get (ge->ge_key.gek_grd);
1524  gbp_endpoint_del_ip (&pfx->fp_addr, grd->grd_fib_index[pfx->fp_proto]);
1525  }
1526  pool_put (gbp_endpoint_pool, ge);
1527 }
1528 
1532 {
1533  ASSERT (0);
1534 
1535  return (FIB_NODE_BACK_WALK_CONTINUE);
1536 }
1537 
1538 /*
1539  * The FIB path's graph node virtual function table
1540  */
1541 static const fib_node_vft_t gbp_endpoint_vft = {
1543  .fnv_last_lock = gbp_endpoint_last_lock_gone,
1544  .fnv_back_walk = gbp_endpoint_back_walk_notify,
1545  // .fnv_mem_show = fib_path_memory_show,
1546 };
1547 
1548 static clib_error_t *
1550 {
1551 #define GBP_EP_HASH_NUM_BUCKETS (2 * 1024)
1552 #define GBP_EP_HASH_MEMORY_SIZE (1 << 20)
1553 
1554  clib_bihash_init_24_8 (&gbp_ep_db.ged_by_ip_rd,
1555  "GBP Endpoints - IP/RD",
1557 
1558  clib_bihash_init_16_8 (&gbp_ep_db.ged_by_mac_bd,
1559  "GBP Endpoints - MAC/BD",
1561 
1562  gbp_ep_logger = vlib_log_register_class ("gbp", "ep");
1563  gbp_endpoint_fib_type = fib_node_register_new_type (&gbp_endpoint_vft);
1564 
1565  return (NULL);
1566 }
1567 
1569 
1570 /*
1571  * fd.io coding-style-patch-verification: ON
1572  *
1573  * Local Variables:
1574  * eval: (c-set-style "gnu")
1575  * End:
1576  */
vlib_log_class_t vlib_log_register_class(char *class, char *subclass)
Definition: log.c:227
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:439
A real VXLAN-GBP tunnel (from vnet/vxlan-gbp/...)
Definition: gbp_vxlan.h:102
static void gbp_endpoint_scan_l3(vlib_main_t *vm)
index_t gek_grd
Index of the Route-Domain.
Definition: gbp_endpoint.h:106
fib_protocol_t fp_proto
protocol type
Definition: fib_types.h:212
fib_node_index_t fib_table_entry_path_add(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, fib_entry_flag_t flags, dpo_proto_t next_hop_proto, const ip46_address_t *next_hop, u32 next_hop_sw_if_index, u32 next_hop_fib_index, u32 next_hop_weight, fib_mpls_label_t *next_hop_labels, fib_route_path_flags_t path_flags)
Add one path to an entry (aka route) in the FIB.
Definition: fib_table.c:522
int gbp_endpoint_is_external(const gbp_endpoint_t *ge)
Definition: gbp_endpoint.c:105
void gbp_itf_set_l2_input_feature(index_t gii, index_t useri, l2input_feat_masks_t feats)
Definition: gbp_itf.c:102
u32 gbp_vxlan_tunnel_clone_and_lock(u32 sw_if_index, const ip46_address_t *src, const ip46_address_t *dst)
Definition: gbp_vxlan.c:224
static gbp_endpoint_loc_t * gbp_endpoint_loc_find_or_add(gbp_endpoint_t *ge, gbp_endpoint_src_t src)
Definition: gbp_endpoint.c:342
u32 vlib_log_class_t
Definition: log.h:21
static gbp_endpoint_src_t gbp_endpoint_get_best_src(const gbp_endpoint_t *ge)
Definition: gbp_endpoint.c:454
u32 flags
Definition: vhost_user.h:115
u16 epg_id_t
Definition: gbp_types.h:21
vl_api_address_t src
Definition: vxlan_gbp.api:32
int gbp_endpoint_is_remote(const gbp_endpoint_t *ge)
Definition: gbp_endpoint.c:93
static gbp_endpoint_t * gbp_endpoint_get(index_t gbpei)
Get the endpoint from a port/interface.
Definition: gbp_endpoint.h:258
f64 ge_last_time
The last time a packet from seen from this end point.
Definition: gbp_endpoint.h:205
index_t * ged_by_sw_if_index
Definition: gbp_endpoint.h:215
A Group Based Policy Endpoint.
Definition: gbp_endpoint.h:182
fib_prefix_t * gek_ips
A vector of ip addresses that belong to the endpoint.
Definition: gbp_endpoint.h:90
const mac_address_t * gbp_route_domain_get_local_mac(void)
#define BIHASH_KVP_PER_PAGE
Definition: bihash_16_8.h:19
a
Definition: bitmap.h:538
void gbp_endpoint_unlock(gbp_endpoint_src_t src, index_t gei)
Definition: gbp_endpoint.c:898
Information about the location of the endpoint provided by a source of endpoints. ...
Definition: gbp_endpoint.h:113
gbp_endpoint_fwd_t ge_fwd
Definition: gbp_endpoint.h:200
#define GBP_EP_HASH_NUM_BUCKETS
gbp_endpoint_key_t ge_key
The key/ID of this EP.
Definition: gbp_endpoint.h:192
u32 bd_add_del_ip_mac(u32 bd_index, ip46_type_t type, const ip46_address_t *ip, const mac_address_t *mac, u8 is_add)
Add/delete IP address to MAC address mapping.
Definition: l2_bd.c:742
vnet_main_t * vnet_get_main(void)
Definition: misc.c:47
static void gbp_endpoint_walk_mac_itf(const clib_bihash_kv_16_8_t *kvp, void *arg)
#define pool_get_zero(P, E)
Allocate an object E from a pool P and zero it.
Definition: pool.h:239
index_t * gef_adjs
The L3 adj, if created.
Definition: gbp_endpoint.h:164
void fib_node_init(fib_node_t *node, fib_node_type_t type)
Definition: fib_node.c:185
ip46_type_t fib_proto_to_ip46(fib_protocol_t fproto)
Convert from fib_protocol to ip46_type.
Definition: fib_types.c:287
static void gbp_endpoint_walk_ip_itf(const clib_bihash_kv_24_8_t *kvp, void *arg)
struct gbp_endpoint_flush_ctx_t_ gbp_endpoint_flush_ctx_t
Definition: fib_entry.h:286
static void gbp_endpoint_del_ip(const ip46_address_t *ip, u32 fib_index)
Definition: gbp_endpoint.c:191
#define NULL
Definition: clib.h:58
int gbp_endpoint_is_local(const gbp_endpoint_t *ge)
Definition: gbp_endpoint.c:99
static walk_rc_t gbp_endpoint_show_one(index_t gei, void *ctx)
gbp_endpoint_flags_t gef_flags
Definition: gbp_endpoint.h:171
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:232
index_t gef_itf
The interface on which the EP is connected.
Definition: gbp_endpoint.h:159
static gbp_endpoint_loc_t * gbp_endpoint_loc_find(gbp_endpoint_t *ge, gbp_endpoint_src_t src)
Definition: gbp_endpoint.c:290
enum fib_node_back_walk_rc_t_ fib_node_back_walk_rc_t
Return code from a back walk function.
u8 src_address[6]
Definition: packet.h:56
enum gbp_endpoint_src_t_ gbp_endpoint_src_t
A bridge Domain Representation.
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:525
static u32 GBP_ENDPOINT_INACTIVE_TIME
GBP Endpoint inactive timeout (in seconds) If a dynamically learned Endpoint has not been heard from ...
Definition: gbp_endpoint.c:58
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:564
int i
static void gbp_endpoint_scan_l2(vlib_main_t *vm)
static_always_inline void mac_address_copy(mac_address_t *dst, const mac_address_t *src)
Definition: mac_address.h:76
format_function_t format_ip46_address
Definition: format.h:61
static_always_inline int mac_address_is_zero(const mac_address_t *mac)
Definition: mac_address.h:54
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
static u32 gbp_n_learnt_endpoints
A count of the number of dynamic entries.
Definition: gbp_endpoint.c:68
unformat_function_t unformat_vnet_sw_interface
static void gbp_endpoint_loc_update(gbp_endpoint_loc_t *gel, u32 sw_if_index, index_t ggi, gbp_endpoint_flags_t flags, const ip46_address_t *tun_src, const ip46_address_t *tun_dst)
Definition: gbp_endpoint.c:482
index_t gg_rd
route-domain/IP-table ID the EPG is in
index_t gbp_route_domain_index(const gbp_route_domain_t *grd)
static gbp_bridge_domain_t * gbp_bridge_domain_get(index_t i)
gbp_endpoint_src_t gel_src
The source providing this location information.
Definition: gbp_endpoint.h:118
adj_index_t adj_nbr_add_or_lock_w_rewrite(fib_protocol_t nh_proto, vnet_link_t link_type, const ip46_address_t *nh_addr, u32 sw_if_index, u8 *rewrite)
Add (and lock) a new or lock an existing neighbour adjacency.
Definition: adj_nbr.c:263
static int clib_bihash_is_free_16_8(clib_bihash_kv_16_8_t *v)
Definition: bihash_16_8.h:37
static void gbb_endpoint_fwd_reset(gbp_endpoint_t *ge)
Definition: gbp_endpoint.c:550
format_function_t format_vnet_sw_if_index_name
#define GBP_ENDPOINT_SRC_MAX
Definition: gbp_endpoint.h:75
unsigned char u8
Definition: types.h:56
static gbp_endpoint_t * gbp_endpoint_from_fib_node(fib_node_t *node)
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 gbp_endpoint_ip_is_equal(const fib_prefix_t *fp, const ip46_address_t *ip)
Definition: gbp_endpoint.c:213
enum fib_protocol_t_ fib_protocol_t
Protocol Type.
f64 gbp_endpoint_scan_threshold(void)
void gbp_itf_unlock(index_t gii)
Definition: gbp_itf.c:81
epg_id_t gef_epg_id
Endpoint Group&#39;s ID.
Definition: gbp_endpoint.h:169
u32 fib_node_child_add(fib_node_type_t parent_type, fib_node_index_t parent_index, fib_node_type_t type, fib_node_index_t index)
Definition: fib_node.c:98
double f64
Definition: types.h:142
static void gbp_endpoint_loc_destroy(gbp_endpoint_loc_t *gel)
Definition: gbp_endpoint.c:331
#define clib_memcpy(d, s, n)
Definition: string.h:180
struct gbp_endpoint_loc_t_::@427 tun
Tunnel info for remote endpoints.
index_t gbp_bridge_domain_index(const gbp_bridge_domain_t *gbd)
static uword vlib_process_suspend(vlib_main_t *vm, f64 dt)
Suspend a vlib cooperative multi-tasking thread for a period of time.
Definition: node_funcs.h:452
enum walk_rc_t_ walk_rc_t
Walk return code.
gbp_endpoint_t * gbp_endpoint_pool
Pool of GBP endpoints.
Definition: gbp_endpoint.c:63
void gbp_learn_set_inactive_threshold(u32 threshold)
void vxlan_gbp_tunnel_unlock(u32 sw_if_index)
Definition: gbp_vxlan.c:281
unformat_function_t unformat_ip4_address
Definition: format.h:70
gbp_endpoint_flags_t gel_flags
Endpoint flags.
Definition: gbp_endpoint.h:128
static int gbp_endpoint_loc_unlock(gbp_endpoint_t *ge, gbp_endpoint_loc_t *gel)
Definition: gbp_endpoint.c:307
static_always_inline void mac_address_to_bytes(const mac_address_t *mac, u8 *bytes)
Definition: mac_address.h:47
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:163
index_t gbp_endpoint_group_find(epg_id_t epg_id)
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
u32 sw_if_index
Definition: vxlan_gbp.api:37
void fib_walk_sync(fib_node_type_t parent_type, fib_node_index_t parent_index, fib_node_back_walk_ctx_t *ctx)
Back walk all the children of a FIB node.
Definition: fib_walk.c:745
u8 dst_address[6]
Definition: packet.h:55
gbp_endpoint_group_t * gbp_endpoint_group_get(index_t i)
u8 * format_fib_prefix(u8 *s, va_list *args)
Definition: fib_types.c:177
A high priority source a plugin can use.
Definition: fib_entry.h:62
clib_bihash_24_8_t ged_by_ip_rd
Definition: gbp_endpoint.h:216
u32 gel_sw_if_index
The interface on which the EP is connected.
Definition: gbp_endpoint.h:123
static int clib_bihash_is_free_24_8(const clib_bihash_kv_24_8_t *v)
Definition: bihash_24_8.h:37
static_always_inline gbp_endpoint_t * gbp_endpoint_find_mac(const u8 *mac, u32 bd_index)
Definition: gbp_endpoint.h:272
Aggregrate type for a prefix.
Definition: fib_types.h:203
u8 * format_gbp_endpoint_flags(u8 *s, va_list *args)
Definition: gbp_endpoint.c:76
#define clib_error_return(e, args...)
Definition: error.h:99
void l2fib_add_entry(const u8 *mac, u32 bd_index, u32 sw_if_index, l2fib_entry_result_flags_t flags)
Add an entry to the l2fib.
Definition: l2_fib.c:400
u8 * format_gbp_itf(u8 *s, va_list *args)
Definition: gbp_itf.c:190
void adj_unlock(adj_index_t adj_index)
Release a reference counting lock on the adjacency.
Definition: adj.c:318
unsigned int u32
Definition: types.h:88
index_t gek_gbd
Index of the Bridge-Domain.
Definition: gbp_endpoint.h:101
static void gbp_endpoint_extract_key_ip_itf(const clib_bihash_kv_24_8_t *key, ip46_address_t *ip, u32 *sw_if_index)
Definition: gbp_endpoint.c:119
static fib_node_back_walk_rc_t gbp_endpoint_back_walk_notify(fib_node_t *node, fib_node_back_walk_ctx_t *ctx)
static void gbp_endpoint_check(index_t gei, f64 start_time)
static const u8 * vnet_sw_interface_get_hw_address(vnet_main_t *vnm, u32 sw_if_index)
Definition: fib_entry.h:275
fib_protocol_t fib_proto_from_ip46(ip46_type_t iproto)
Convert from ip46_type to fib_protocol.
Definition: fib_types.c:303
The identity of a DPO is a combination of its type and its instance number/index of objects of that t...
Definition: dpo.h:168
fib_node_bw_reason_flag_t fnbw_reason
The reason/trigger for the backwalk.
Definition: fib_node.h:208
#define GBP_ENDPOINT_ATTR_NAMES
Definition: gbp_endpoint.h:50
int gbp_endpoint_update_and_lock(gbp_endpoint_src_t src, u32 sw_if_index, const ip46_address_t *ips, const mac_address_t *mac, index_t gbdi, index_t grdi, epg_id_t epg_id, gbp_endpoint_flags_t flags, const ip46_address_t *tun_src, const ip46_address_t *tun_dst, u32 *handle)
Definition: gbp_endpoint.c:804
static void vlib_process_signal_event(vlib_main_t *vm, uword node_index, uword type_opaque, uword data)
Definition: node_funcs.h:964
ip46_address_t fp_addr
The address type is not deriveable from the fp_addr member.
Definition: fib_types.h:226
GBP Endpoint Databases.
Definition: gbp_endpoint.h:213
void fib_node_lock(fib_node_t *node)
Definition: fib_node.c:203
long ctx[MAX_CONNS]
Definition: main.c:144
static u8 * format_gbp_endpoint_key(u8 *s, va_list *args)
struct _unformat_input_t unformat_input_t
u16 epg_id
Definition: gbp.api:116
void gbp_endpoint_scan(vlib_main_t *vm)
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:286
This is the object type deifend above.
Definition: gbp_vxlan.h:97
static fib_node_t * gbp_endpoint_get_node(fib_node_index_t index)
clib_bihash_16_8_t ged_by_mac_bd
Definition: gbp_endpoint.h:217
#define vec_del1(v, i)
Delete the element at index I.
Definition: vec.h:808
void gbp_itf_set_l2_output_feature(index_t gii, index_t useri, l2output_feat_masks_t feats)
Definition: gbp_itf.c:146
fib_node_type_t fn_type
The node&#39;s type.
Definition: fib_node.h:295
An node in the FIB graph.
Definition: fib_node.h:291
l2input_feat_masks_t
Definition: l2_input.h:138
void fib_node_unlock(fib_node_t *node)
Definition: fib_node.c:209
static ip46_type_t ip46_address_get_type(const ip46_address_t *a)
Definition: gbp_endpoint.c:207
mac_address_t gek_mac
MAC address of the endpoint.
Definition: gbp_endpoint.h:96
u32 gbp_endpoint_child_add(index_t gei, fib_node_type_t type, fib_node_index_t index)
Definition: gbp_endpoint.c:979
An Endpoint Group representation.
#define ip46_address_initializer
Definition: ip6_packet.h:96
vlib_node_registration_t gbp_scanner_node
(constructor) VLIB_REGISTER_NODE (gbp_scanner_node)
Definition: gbp_scanner.c:91
static void gbp_endpoint_ips_update(gbp_endpoint_t *ge, const ip46_address_t *ips, const gbp_route_domain_t *grd)
Definition: gbp_endpoint.c:219
#define ip46_address_is_ip4(ip46)
Definition: ip6_packet.h:88
unformat_function_t unformat_ip6_address
Definition: format.h:91
static u8 * format_gbp_endpoint_loc(u8 *s, va_list *args)
#define UNFORMAT_END_OF_INPUT
Definition: format.h:144
u32 l2fib_del_entry(const u8 *mac, u32 bd_index, u32 sw_if_index)
Delete an entry from the l2fib.
Definition: l2_fib.c:684
static void gbp_endpoint_add_itf(u32 sw_if_index, index_t gei)
Definition: gbp_endpoint.c:144
enum gbp_endpoint_attr_t_ gbp_endpoint_attr_t
Flags for each endpoint.
vlib_main_t * vm
Definition: buffer.c:301
void gbp_policy_dpo_add_or_lock(dpo_proto_t dproto, epg_id_t epg, u32 sw_if_index, dpo_id_t *dpo)
static bool gbp_endpoint_add_ip(const ip46_address_t *ip, u32 fib_index, index_t gei)
Definition: gbp_endpoint.c:167
void gbp_endpoint_walk(gbp_endpoint_cb_t cb, void *ctx)
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:341
static_always_inline void mac_address_from_u64(u64 u, mac_address_t *mac)
Definition: mac_address.h:70
void fib_table_entry_delete(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source)
Delete a FIB entry.
Definition: fib_table.c:853
Force the walk to be synchronous.
Definition: fib_node.h:170
#define FOR_EACH_GBP_ENDPOINT_ATTR(_item)
Definition: gbp_endpoint.c:70
u32 grd_fib_index[FIB_PROTOCOL_IP_MAX]
fib_node_get_t fnv_get
Definition: fib_node.h:279
void send_ip6_na_w_addr(vlib_main_t *vm, const ip6_address_t *addr, u32 sw_if_index)
#define vec_search_with_function(v, E, fn)
Search a vector for the index of the entry that matches.
Definition: vec.h:965
static_always_inline void ip46_address_copy(ip46_address_t *dst, const ip46_address_t *src)
Definition: ip6_packet.h:99
static void gbb_endpoint_fwd_recalc(gbp_endpoint_t *ge)
Definition: gbp_endpoint.c:603
u32 fib_node_index_t
A typedef of a node index.
Definition: fib_types.h:30
void gbp_endpoint_group_lock(index_t i)
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:283
uword unformat_mac_address(unformat_input_t *input, va_list *args)
Definition: format.c:241
void fib_prefix_from_ip46_addr(const ip46_address_t *addr, fib_prefix_t *pfx)
Host prefix from ip.
Definition: fib_types.c:80
static clib_error_t * gbp_endpoint_init(vlib_main_t *vm)
gbp_endpoint_t * gbp_endpoint_find_ip(const ip46_address_t *ip, u32 fib_index)
Definition: gbp_endpoint.c:128
void send_ip4_garp_w_addr(vlib_main_t *vm, const ip4_address_t *ip4_addr, u32 sw_if_index)
Definition: arp.c:2563
void gbp_endpoint_flush(gbp_endpoint_src_t src, u32 sw_if_index)
remove all learnt endpoints using the interface
Context passed between object during a back walk.
Definition: fib_node.h:204
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:155
This is the identity of an endpoint, as such it is information about an endpoint that is idempotent...
Definition: gbp_endpoint.h:84
static walk_rc_t gbp_endpoint_flush_cb(index_t gei, void *args)
Definition: gbp_endpoint.c:999
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
gbp_endpoint_src_t src
Definition: gbp_endpoint.c:994
enum gbp_endpoint_flags_t_ gbp_endpoint_flags_t
static bool gbp_endpoint_add_mac(const mac_address_t *mac, u32 bd_index, index_t gei)
Definition: gbp_endpoint.c:152
#define ASSERT(truth)
gbp_route_domain_t * gbp_route_domain_get(index_t i)
static u8 * format_gbp_endpoint_fwd(u8 *s, va_list *args)
u8 * format_gbp_endpoint(u8 *s, va_list *args)
const mac_address_t ZERO_MAC_ADDRESS
Definition: mac_address.c:19
u32 gb_bvi_sw_if_index
The BD&#39;s BVI interface (obligatory)
vlib_log_class_t gbp_ep_logger
Definition: gbp_endpoint.c:45
ip46_type_t
Definition: ip6_packet.h:70
void gbp_endpoint_group_unlock(index_t ggi)
#define EPG_INVALID
Definition: gbp_types.h:22
const mac_address_t * gbp_route_domain_get_remote_mac(void)
#define GBP_ENDPOINT_INFO(...)
Definition: gbp_endpoint.c:50
static clib_error_t * gbp_endpoint_show(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
void fib_node_child_remove(fib_node_type_t parent_type, fib_node_index_t parent_index, fib_node_index_t sibling_index)
Definition: fib_node.c:123
dpo_proto_t fib_proto_to_dpo(fib_protocol_t fib_proto)
Definition: fib_types.c:237
static gbp_endpoint_t * gbp_endpoint_alloc(const ip46_address_t *ips, const gbp_route_domain_t *grd, const mac_address_t *mac, const gbp_bridge_domain_t *gbd)
Definition: gbp_endpoint.c:250
static void gbp_endpoint_del_mac(const mac_address_t *mac, u32 bd_index)
Definition: gbp_endpoint.c:181
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
static_always_inline void gbp_endpoint_mk_key_mac(const u8 *mac, u32 bd_index, clib_bihash_kv_16_8_t *key)
Definition: gbp_endpoint.h:264
#define ip46_address_reset(ip46)
Definition: ip6_packet.h:91
static_always_inline void gbp_endpoint_mk_key_ip(const ip46_address_t *ip, u32 fib_index, clib_bihash_kv_24_8_t *key)
Definition: gbp_endpoint.h:288
static int gbp_endpoint_find_for_update(const ip46_address_t *ips, const gbp_route_domain_t *grd, const mac_address_t *mac, const gbp_bridge_domain_t *gbd, gbp_endpoint_t **ge)
Find an EP inthe DBs and check that if we find it in the L2 DB it has the same IPs as this update...
Definition: gbp_endpoint.c:383
static int gbp_endpoint_loc_cmp_for_sort(gbp_endpoint_loc_t *a, gbp_endpoint_loc_t *b)
Definition: gbp_endpoint.c:284
fib_node_t ge_node
A FIB node that allows the tracking of children.
Definition: gbp_endpoint.h:187
u32 gel_locks
number of times this source has locked this
Definition: gbp_endpoint.h:138
And endpoints current forwarding state.
Definition: gbp_endpoint.h:154
u32 vxlan_gbp_tunnel_get_parent(u32 sw_if_index)
Definition: gbp_vxlan.c:191
#define ip46_address_is_equal(a1, a2)
Definition: ip6_packet.h:94
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
A route Domain Representation.
u32 gg_uplink_sw_if_index
the uplink interface dedicated to the EPG
static void gbp_endpoint_n_learned(int n)
Definition: gbp_endpoint.c:463
#define INDEX_INVALID
Invalid index - used when no index is known blazoned capitals INVALID speak volumes where ~0 does not...
Definition: dpo.h:47
#define vec_sort_with_function(vec, f)
Sort a vector using the supplied element comparison function.
Definition: vec.h:984
static int gbp_endpoint_loc_is_equal(gbp_endpoint_loc_t *a, gbp_endpoint_loc_t *b)
Definition: gbp_endpoint.c:278
#define DPO_INVALID
An initialiser for DPOs declared on the stack.
Definition: dpo.h:195
static void gbp_endpoint_last_lock_gone(fib_node_t *node)
gbp_vxlan_tunnel_type_t gbp_vxlan_tunnel_get_type(u32 sw_if_index)
Definition: gbp_vxlan.c:206
gbp_ep_db_t gbp_ep_db
EP DBs.
Definition: gbp_endpoint.c:41
A FIB graph nodes virtual function table.
Definition: fib_node.h:278
enum fib_node_type_t_ fib_node_type_t
The types of nodes in a FIB graph.
u8 * format_mac_address_t(u8 *s, va_list *args)
Definition: mac_address.c:27
vl_api_address_t ips[n_ips]
Definition: gbp.api:121
void dpo_reset(dpo_id_t *dpo)
reset a DPO ID The DPO will be unlocked.
Definition: dpo.c:231
#define vec_foreach(var, vec)
Vector iterator.
vnet_link_t fib_proto_to_link(fib_protocol_t proto)
Convert from a protocol to a link type.
Definition: fib_types.c:271
static void gbp_endpoint_extract_key_mac_itf(const clib_bihash_kv_16_8_t *key, mac_address_t *mac, u32 *sw_if_index)
Definition: gbp_endpoint.c:111
index_t gel_epg
Endpoint Group.
Definition: gbp_endpoint.h:133
#define pool_foreach_index(i, v, body)
Iterate pool by index.
Definition: pool.h:535
static const char * gbp_endpoint_attr_names[]
Definition: gbp_endpoint.c:36
#define vec_validate_init_empty(V, I, INIT)
Make sure vector is long enough for given index and initialize empty space (no header, unspecified alignment)
Definition: vec.h:488
fib_node_type_t gbp_endpoint_fib_type
Definition: gbp_endpoint.c:43
index_t gbp_itf_add_and_lock(u32 sw_if_index, u32 bd_index)
Definition: gbp_itf.c:57
gbp_endpoint_loc_t * ge_locs
Location information provided by the various sources.
Definition: gbp_endpoint.h:198
#define ip46_address_is_zero(ip46)
Definition: ip6_packet.h:93
ip46_address_t gel_dst
Definition: gbp_endpoint.h:147
vl_api_mac_address_t mac
Definition: gbp.api:118
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:725
A low (below routing) priority source a plugin can use.
Definition: fib_entry.h:82
#define GBP_EP_HASH_MEMORY_SIZE
void gbp_endpoint_child_remove(index_t gei, u32 sibling)
Definition: gbp_endpoint.c:986
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:972
static index_t gbp_endpoint_index(const gbp_endpoint_t *ge)
Definition: gbp_endpoint.c:201
void vxlan_gbp_tunnel_lock(u32 sw_if_index)
Definition: gbp_vxlan.c:300
static clib_error_t * gbp_endpoint_cli(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:170
walk_rc_t(* gbp_endpoint_cb_t)(index_t gbpei, void *ctx)
Definition: gbp_endpoint.h:236
index_t gg_gbd
Bridge-domain ID the EPG is in.
u8 * format_gbp_endpoint_src(u8 *s, va_list *args)