OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
gmp_proto.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 #include "cmn/agent_cmn.h"
6 #include <init/agent_param.h>
7 #include "oper/route_common.h"
8 #include "oper/multicast.h"
10 #include "oper/nexthop.h"
11 
12 #ifdef __cplusplus
13 extern "C" {
14 #endif
15 #include "mcast_common.h"
16 #include "gmpx_basic_types.h"
17 #include "gmp.h"
18 #include "gmpx_environment.h"
19 #include "gmp_intf.h"
20 #include "gmp_map.h"
21 #ifdef __cplusplus
22 }
23 #endif
24 
25 #include "task_map.h"
26 #include "gmp_proto.h"
27 
29 
30 GmpIntf::GmpIntf(const GmpProto *gmp_proto) : gmp_proto_(gmp_proto),
31  vrf_name_(), ip_addr_() {
32 
33  gif_ = NULL;
34  querying_ = false;
35 }
36 
37 // GmpIntf is local to Agent IGMP implementation and is not known
38 // by core IGMP module.
39 // IP address change to be reflected in GMP interface also.
41 
42  if (ip_addr_ != addr) {
43  ip_addr_ = addr;
44 
45  uint32_t intf_addr = htonl(ip_addr_.to_v4().to_ulong());
46  gmp_addr_string gmp_addr;
47  memcpy(&gmp_addr, &intf_addr, IPV4_ADDR_LEN);
49  addr != IpAddress() ?
50  (const gmp_addr_string *)&intf_addr : NULL);
51  return true;
52  }
53 
54  return false;
55 }
56 
57 // Update the new VRF name for GmpIntf.
58 bool GmpIntf::set_vrf_name(const string &vrf_name) {
59  vrf_name_ = vrf_name;
60  return true;
61 }
62 
63 // Change of querying mode per-GmpIntf.
64 bool GmpIntf::set_gmp_querying(bool querying) {
65 
66  if (querying_ != querying) {
67  querying_ = querying;
69  querying ? TRUE : FALSE);
70  return ret ? true : false;
71  }
72 
73  return true;
74 }
75 
77  const std::string &task_name, int instance,
78  boost::asio::io_context &io) :
79  type_(type), agent_(agent), name_(task_name), instance_(instance), io_(io) {
80 
81  task_map_ = NULL;
82  gmp_trigger_timer_ = NULL;
83  gmp_notif_trigger_ = NULL;
84  gd_ = NULL;
85  cb_ = NULL;
86 
89 
92 }
93 
95 }
96 
97 // Start the GmpProto that represents the agent's IGMP functionality.
99 
100  if (type_ != GmpType::IGMP) {
101  return false;
102  }
103 
105  if (!task_map_) {
106  return false;
107  }
108 
109  // TaskTrigger instance for handling GMP notifications like join, leave
110  // per-<S,G> and per-host as required.
112  boost::bind(&GmpProto::GmpNotificationHandler,this),
113  TaskScheduler::GetInstance()->GetTaskId(name_),
114  instance_);
115 
117  if (!gd_) {
119  task_map_ = NULL;
120 
121  if (gmp_notif_trigger_) {
123  delete gmp_notif_trigger_;
124  }
125  gmp_notif_trigger_ = NULL;
126 
127  return false;
128  }
129 
131  boost::bind(&GmpProto::GmpVnNotify, this, _1, _2));
133  boost::bind(&GmpProto::GmpItfNotify, this, _1, _2));
134 
135  return true;
136 }
137 
138 // Stop the GmpProto that represents the agent's IGMP functionality.
140 
141  if (!gd_) {
142  return true;
143  }
144 
147 
149  gd_ = NULL;
150 
151  if (gmp_trigger_timer_) {
154  gmp_trigger_timer_ = NULL;
155  }
156 
158  delete gmp_notif_trigger_;
159  gmp_notif_trigger_ = NULL;
160 
162  task_map_ = NULL;
163 
164  return true;
165 }
166 
167 // Cleans up <S,G> per-GmpIntf. Also cleans up VMIs per-<S,G> from NH.
169  VnGmpDBState::VnGmpIntfState *gmp_intf_state) {
170 
171  MulticastHandler *m_handler = agent_->oper_db()->multicast();
172 
173  GmpSourceGroup *gmp_sg = NULL;
174  std::set<GmpSourceGroup *> sg_to_delete;
176  gmp_intf_state->gmp_intf_sg_list_.begin();
177  for (; gif_sg_it != gmp_intf_state->gmp_intf_sg_list_.end(); ++gif_sg_it) {
178 
179  gmp_sg = *gif_sg_it;
180 
181  MCTRACE(LogSG, "Delete Mcast VRF SG for VN ",
182  gmp_intf_state->gmp_intf_->get_vrf_name(),
183  gmp_sg->source_.to_v4().to_string(),
184  gmp_sg->group_.to_v4().to_string(), 0);
185 
186  gmp_sg->refcount_--;
187  sg_to_delete.insert(gmp_sg);
188  if (gmp_sg->refcount_ == 0) {
189  state->gmp_sg_list_.erase(gmp_sg);
190  // Delete VMIs from multicast list for the <S,G>
192  gmp_intf_state->gmp_intf_->get_vrf_name(),
193  gmp_sg->source_.to_v4(), gmp_sg->group_.to_v4());
194  }
195  }
196 
197  for(std::set<GmpSourceGroup *>::iterator sg_it = sg_to_delete.begin();
198  sg_it != sg_to_delete.end(); sg_it++) {
199  gmp_sg = *sg_it;
200  gmp_intf_state->gmp_intf_sg_list_.erase(gmp_sg);
201  if (gmp_sg->refcount_ == 0) {
202  delete gmp_sg;
203  }
204  }
205 
206  return;
207 }
208 
209 // Handle VN change notification, specifically IPAM changes
211 
212  // Registering/Unregistering every IPAM gateway (or) dns_server
213  // present in the VN with the IGMP module.
214  // Changes to VN, or VN IPAM info, or gateway or dns server is
215  // handled below.
216 
217  VnEntry *vn = static_cast<VnEntry *>(entry);
218 
219  VnGmpDBState *state = static_cast<VnGmpDBState *>
220  (entry->GetState(part->parent(), vn_listener_id_));
221  VnGmpDBState::VnGmpIntfState *gmp_intf_state;
222 
223  if (vn->IsDeleted() || !vn->GetVrf()) {
224  if (!state) {
225  return;
226  }
227  VnGmpDBState::VnGmpIntfMap::iterator it = state->gmp_intf_map_.begin();
228  for (;it != state->gmp_intf_map_.end(); ++it) {
229  gmp_intf_state = it->second;
230  GmpIntfSGClear(state, gmp_intf_state);
231  // Cleanup the GMP database and timers
232  gmp_intf_state->gmp_intf_->set_vrf_name(string());
233  gmp_intf_state->gmp_intf_->set_ip_address(IpAddress(Ip4Address()));
234  DeleteIntf(gmp_intf_state->gmp_intf_);
235  delete gmp_intf_state;
237  }
238  state->gmp_intf_map_.clear();
239 
240  if (vn->IsDeleted()) {
241  entry->ClearState(part->parent(), vn_listener_id_);
242  delete state;
243  }
244  return;
245  }
246 
247  if (!vn->GetVrf()) {
248  return;
249  }
250 
251  if ((vn->GetVrf()->GetName() == agent_->fabric_policy_vrf_name()) ||
252  (vn->GetVrf()->GetName() == agent_->fabric_vrf_name())) {
253  return;
254  }
255 
256  if (state == NULL) {
257  state = new VnGmpDBState();
258 
259  entry->SetState(part->parent(), vn_listener_id_, state);
260  }
261 
262  VnGmpDBState::VnGmpIntfMap::iterator it = state->gmp_intf_map_.begin();
263  while (it != state->gmp_intf_map_.end()) {
264  const VnIpam *ipam = vn->GetIpam(it->first);
265  if ((ipam != NULL) && ((ipam->default_gw == it->first) ||
266  (ipam->dns_server == it->first))) {
267  it++;
268  continue;
269  }
270  gmp_intf_state = it->second;
271  GmpIntfSGClear(state, gmp_intf_state);
272  // Cleanup the GMP database and timers
273  gmp_intf_state->gmp_intf_->set_vrf_name(string());
274  gmp_intf_state->gmp_intf_->set_ip_address(IpAddress(Ip4Address()));
275  DeleteIntf(gmp_intf_state->gmp_intf_);
276  delete gmp_intf_state;
278  state->gmp_intf_map_.erase(it++);
279  }
280 
281  const std::vector<VnIpam> &ipam = vn->GetVnIpam();
282  for (unsigned int i = 0; i < ipam.size(); ++i) {
283  if (!ipam[i].IsV4()) {
284  continue;
285  }
286  if ((ipam[i].default_gw == IpAddress(Ip4Address())) &&
287  (ipam[i].dns_server == IpAddress(Ip4Address()))) {
288  continue;
289  }
290 
291  IpAddress gmp_address = IpAddress(Ip4Address());
292  VnGmpDBState::VnGmpIntfMap::const_iterator it;
293 
294  if (ipam[i].dns_server != IpAddress(Ip4Address())) {
295  it = state->gmp_intf_map_.find(ipam[i].dns_server);
296  gmp_address = ipam[i].dns_server;
297  }
298  if (ipam[i].default_gw != IpAddress(Ip4Address())) {
299  if ((it != state->gmp_intf_map_.end()) &&
300  (ipam[i].default_gw != ipam[i].dns_server)) {
301  gmp_intf_state = it->second;
302  GmpIntfSGClear(state, gmp_intf_state);
303  // Cleanup the GMP database and timers
304  gmp_intf_state->gmp_intf_->set_vrf_name(string());
305  gmp_intf_state->gmp_intf_->set_ip_address(IpAddress(Ip4Address()));
306  DeleteIntf(gmp_intf_state->gmp_intf_);
308  delete gmp_intf_state;
309  state->gmp_intf_map_.erase(it->first);
310  }
311 
312  gmp_address = ipam[i].default_gw;
313  }
314 
315  it = state->gmp_intf_map_.find(gmp_address);
316  if (it == state->gmp_intf_map_.end()) {
317  gmp_intf_state = new VnGmpDBState::VnGmpIntfState();
318  gmp_intf_state->gmp_intf_ = CreateIntf();
320  state->gmp_intf_map_.insert(
321  std::pair<IpAddress,VnGmpDBState::VnGmpIntfState*>
322  (gmp_address, gmp_intf_state));
323  } else {
324  gmp_intf_state = it->second;
325  }
326  if (gmp_intf_state) {
327  gmp_intf_state->gmp_intf_->set_ip_address(gmp_address);
328  if (vn->GetVrf()) {
329  gmp_intf_state->gmp_intf_->set_vrf_name(vn->GetVrf()->GetName());
330  }
331  }
332  }
333 }
334 
335 // Handle Interface notification, specifically VMI delete notification
336 // Clean up VMI from NH for the <S,G>s on VMI delete
338 
339  Interface *itf = static_cast<Interface *>(entry);
340  if (itf->type() != Interface::VM_INTERFACE) {
341  return;
342  }
343 
344  VmInterface *vm_itf = static_cast<VmInterface *>(itf);
345  if (vm_itf->vmi_type() == VmInterface::VHOST) {
346  return;
347  }
348 
349  VmiGmpDBState *vmi_state = static_cast<VmiGmpDBState *>
350  (entry->GetState(part->parent(), itf_listener_id_));
351 
352  if (itf->IsDeleted() || !vm_itf->igmp_enabled()) {
353  if (!vmi_state) {
354  MCTRACE(IgmpIntf, "Itf Notify, no VMI state ",
355  "no-vrf", vm_itf->primary_ip_addr().to_string(),
356  vm_itf->igmp_enabled());
357  return;
358  }
359 
360  MCTRACE(IgmpIntf, "Itf Notify, VMI delete or IGMP disable ",
361  vmi_state->vrf_name_,
362  vm_itf->primary_ip_addr().to_string(),
363  vm_itf->igmp_enabled());
364  if (agent_->oper_db()->multicast()) {
366  vmi_state->vrf_name_, vm_itf);
367  }
368  if (itf->IsDeleted()) {
369  vm_ip_to_vmi_.erase(vmi_state->vmi_v4_addr_);
370  entry->ClearState(part->parent(), itf_listener_id_);
371  delete vmi_state;
372  }
373  return;
374  }
375 
376  MCTRACE(IgmpIntf, "Itf Notify, VMI create or IGMP enable",
377  vm_itf->vrf() ? vm_itf->vrf()->GetName() : "",
378  vm_itf->primary_ip_addr().to_string(),
379  vm_itf->igmp_enabled());
380  if (vmi_state == NULL) {
381  vmi_state = new VmiGmpDBState();
382  entry->SetState(part->parent(), itf_listener_id_, vmi_state);
383  }
384 
385  if (vm_itf->vrf()) {
386  if (vmi_state->vrf_name_ != vm_itf->vrf()->GetName()) {
387  if (agent_->oper_db()->multicast()) {
388  agent_->oper_db()->multicast()->
389  DeleteVmInterfaceFromVrfSourceGroup(
390  vmi_state->vrf_name_, vm_itf);
391  }
392 
393  vmi_state->vrf_name_ = vm_itf->vrf()->GetName();
394  }
395  }
396 
397  if (vmi_state->vmi_v4_addr_ != vm_itf->primary_ip_addr()) {
398 
399  if (vm_ip_to_vmi_.find(vmi_state->vmi_v4_addr_) !=
400  vm_ip_to_vmi_.end()) {
401  if (agent_->oper_db()->multicast()) {
402  agent_->oper_db()->multicast()->
403  DeleteVmInterfaceFromVrfSourceGroup(
404  vmi_state->vrf_name_, vm_itf);
405  }
406 
407  vm_ip_to_vmi_.erase(vmi_state->vmi_v4_addr_);
408  }
409 
410  vmi_state->vmi_v4_addr_ = vm_itf->primary_ip_addr();
411  vm_ip_to_vmi_.insert(std::pair<IpAddress,boost::uuids::uuid>
412  (vmi_state->vmi_v4_addr_,
413  vm_itf->GetUuid()));
414  }
415 
416  return;
417 }
418 
419 // Create a GmpIntf. Represents per-IPAM entry.
421 
422  GmpIntf *gmp_intf = new GmpIntf(this);
423 
424  gmp_intf->SetGif(gmp_attach_intf(gd_, gmp_intf));
425  if (!gmp_intf->GetGif()) {
426  delete gmp_intf;
427  return NULL;
428  }
429 
430  return gmp_intf;
431 }
432 
433 // Delete a GmpIntf.
435 
436  gmp_detach_intf(gd_, gif->GetGif());
437  delete gif;
438 
439  return true;
440 }
441 
442 // Pass the IP header processed IGMP packet to the GMP
444  void *rcv_pkt, uint32_t packet_len,
445  IpAddress ip_saddr, IpAddress ip_daddr) {
446 
447  uint32_t addr;
448  gmp_addr_string src_addr, dst_addr;
449 
450  const VnEntry *vn = vm_itf->vn();
451  VnGmpDBState *state = NULL;
452  state = static_cast<VnGmpDBState *>(vn->GetState(
453  vn->get_table_partition()->parent(),
454  vn_listener_id_));
455  if (!state) {
456  return false;
457  }
458 
459  const VnIpam *ipam = vn->GetIpam(ip_saddr);
460  VnGmpDBState::VnGmpIntfMap::const_iterator it =
461  state->gmp_intf_map_.find(ipam->default_gw);
462  if (it == state->gmp_intf_map_.end()) {
463  it = state->gmp_intf_map_.find(ipam->dns_server);
464  }
465  if (it == state->gmp_intf_map_.end()) {
466  return false;
467  }
468 
469  VnGmpDBState::VnGmpIntfState *gmp_intf_state = it->second;
470  GmpIntf *gmp_intf = gmp_intf_state->gmp_intf_;
471 
472  addr = htonl(ip_saddr.to_v4().to_ulong());
473  memcpy(&src_addr, &addr, IPV4_ADDR_LEN);
474  addr = htonl(ip_daddr.to_v4().to_ulong());
475  memcpy(&dst_addr, &addr, IPV4_ADDR_LEN);
476 
477  boolean ret = gmp_process_pkt(gd_, gmp_intf->GetGif(), rcv_pkt,
478  packet_len, &src_addr, &dst_addr);
479 
480  return ret ? true : false;
481 }
482 
484  return new uint8_t[GMP_TX_BUFF_LEN];
485 }
486 
487 void GmpProto::GmpBufferFree(uint8_t *pkt) {
488  delete [] pkt;
489 }
490 
491 // TaskTrigger handler for IGMP notifications like join, leave.
493 
494  boolean pending = FALSE;
495 
496  pending = gmp_notification_handler(gd_);
497 
498  if ((pending == TRUE) && gmp_notif_trigger_) {
499  gmp_trigger_timer_ = TimerManager::CreateTimer(io_, "GMP Trigger Timer",
500  TaskScheduler::GetInstance()->GetTaskId(name_),
501  instance_, true);
502 
504  boost::bind(&GmpProto::GmpNotificationTimer, this));
505  }
506 
507  return true;
508 }
509 
510 // Timer instance to handle pending notifications not handled in previous run
512 
515  }
516 
517  gmp_trigger_timer_ = NULL;
518 
519  return false;
520 }
521 
522 // Handler registered with GMP to take care of per-<S,G> and also
523 // per-host, per-<S,G> notifications. TaskTriggers instance created
524 // above is triggered to further handle the notifications
526 
528  return;
529  }
530 
532 
533  return;
534 }
535 
536 // <S,G>, including <*,G> notification handling
538  int group_action) {
539 
540  if (agent_->params()->mvpn_ipv4_enable()) {
541  return;
542  }
543 
544  // Support for EVPN <*,G> only.
545  if (!gif) {
546  return;
547  }
548 
550  VnEntry *vn;
551  if (vrf) {
552  vn = vrf->vn();
553  }
554  if (!vrf || !vn) {
555  return;
556  }
557 
558  VnGmpDBState *state = NULL;
559  state = static_cast<VnGmpDBState *>(vn->GetState(
560  vn->get_table_partition()->parent(),
561  vn_listener_id_));
562  if (!state) {
563  return;
564  }
565 
566  VnGmpDBState::VnGmpIntfMap::iterator gif_it = state->gmp_intf_map_.begin();
567  VnGmpDBState::VnGmpIntfState *gmp_intf_state = NULL;
568  while (gif_it != state->gmp_intf_map_.end()) {
569  gmp_intf_state = gif_it->second;
570  if (gmp_intf_state->gmp_intf_ == gif) {
571  break;
572  }
573  gif_it++;
574  }
575 
576  if (gif_it == state->gmp_intf_map_.end()) {
577  return;
578  }
579 
580  GmpSourceGroup *gmp_sg = NULL;
581  VnGmpDBState::VnGmpSGListIter sg_it = state->gmp_sg_list_.begin();
582  for (;sg_it != state->gmp_sg_list_.end(); ++sg_it) {
583  gmp_sg = *sg_it;
584  if ((gmp_sg->source_ == source) || (gmp_sg->group_ == group)) {
585  break;
586  }
587  }
588 
589  if (sg_it == state->gmp_sg_list_.end()) {
590  if (group_action == MGM_GROUP_REMOVED ||
591  group_action == MGM_GROUP_SRC_REMOVED) {
592 
593  return;
594  }
595  }
596 
597  bool created = false;
598  if (!gmp_sg) {
599  gmp_sg = new GmpSourceGroup();
600  gmp_sg->source_ = source;
601  gmp_sg->group_ = group;
604  created = true;
605  state->gmp_sg_list_.insert(gmp_sg);
606  }
607 
609  gmp_intf_state->gmp_intf_sg_list_.begin();
610 
611  MulticastHandler *m_handler = agent_->oper_db()->multicast();
612  if (group_action == MGM_GROUP_ADDED) {
613  gif_sg_it = gmp_intf_state->gmp_intf_sg_list_.find(gmp_sg);
614  if (gif_sg_it == gmp_intf_state->gmp_intf_sg_list_.end()) {
615  gmp_intf_state->gmp_intf_sg_list_.insert(gmp_sg);
616  gmp_sg->refcount_++;
617  }
618  if (created) {
619  MCTRACE(LogSG, "Create Mcast VRF SG ", vrf->GetName(),
620  source.to_string(), group.to_string(), 0);
621  m_handler->CreateMulticastVrfSourceGroup(vrf->GetName(),
622  vn->GetName(), source.to_v4(), group.to_v4());
623  m_handler->SetEvpnMulticastSGFlags(vrf->GetName(),
624  source.to_v4(), group.to_v4(), gmp_sg->flags_);
625  }
626  }
627 
628  if (group_action == MGM_GROUP_REMOVED ||
629  group_action == MGM_GROUP_SRC_REMOVED) {
630 
631  gif_sg_it = gmp_intf_state->gmp_intf_sg_list_.find(gmp_sg);
632  if (gif_sg_it != gmp_intf_state->gmp_intf_sg_list_.end()) {
633  gmp_sg->refcount_--;
634  gmp_intf_state->gmp_intf_sg_list_.erase(gmp_sg);
635  if (gmp_sg->refcount_ == 0) {
636  state->gmp_sg_list_.erase(gmp_sg);
637  MCTRACE(LogSG, "Delete Mcast VRF SG ", vrf->GetName(),
638  source.to_string(), group.to_string(), 0);
639  m_handler->DeleteMulticastVrfSourceGroup(vrf->GetName(),
640  source.to_v4(), group.to_v4());
641  delete gmp_sg;
642  }
643  }
644  }
645 
646  return;
647 }
648 
650 
651  return;
652 }
653 
654 // Per-host, per-<S,G> handling. For now, only per-host, per-<*,G> handling
656  IpAddress source, IpAddress group) {
657 
658  if (!agent_->oper_db()->multicast()) {
659  return;
660  }
661 
662  if (!host.is_v4()) {
663  return;
664  }
665 
666  if (source.to_v4() == Ip4Address()) {
668  } else {
670  }
671 
672  if (vm_ip_to_vmi_.find(host) == vm_ip_to_vmi_.end()) {
673  MCTRACE(Info, "igmp_trace: No host found", host.to_string());
674  return;
675  }
676 
677  boost::uuids::uuid vmi_uuid = vm_ip_to_vmi_[host];
678  InterfaceConstRef intf_ref = agent_->interface_table()->FindVmi(vmi_uuid);
679  const VmInterface *vm_intf = static_cast<const VmInterface *>(intf_ref.get());
680  if (!vm_intf) {
681  MCTRACE(Info, "igmp_trace: No VM Interface for host", host.to_string());
682  return;
683  }
684 
685  if (agent_->params()->mvpn_ipv4_enable()) {
686  // Support for MVPN <S,G> only.
687  TriggerMvpnNotification(vm_intf, join, source, group);
688  } else {
689  // Support for EVPN <*,G> only.
690  TriggerEvpnNotification(vm_intf, join, source, group);
691  }
692 
693  return;
694 }
695 
696 // Handling per-host, per-<S,G> notification for MVPN case
697 void GmpProto::TriggerMvpnNotification(const VmInterface *vm_intf, bool join,
698  IpAddress source, IpAddress group) {
699 
700  uint32_t src_addr;
701  src_addr = htonl(source.to_v4().to_ulong());
702 
703  if (src_addr) {
704  if (join) {
707  agent_->fabric_vn_name(), vm_intf,
708  source.to_v4(), group.to_v4());
709  } else {
711  agent_->fabric_policy_vrf_name(), vm_intf,
712  source.to_v4(), group.to_v4());
713  }
714  } else {
715  if (!join) {
717  agent_->fabric_policy_vrf_name(), vm_intf,
718  group.to_v4());
719  }
720  }
721 
722  return;
723 }
724 
725 // Handling per-host, per-<S,G> notification for EVPN(SMET) case
726 void GmpProto::TriggerEvpnNotification(const VmInterface *vm_intf, bool join,
727  IpAddress source, IpAddress group) {
728 
729  if (join) {
730  MCTRACE(LogSG, "Add VM Mcast VRF SG ",
731  vm_intf->primary_ip_addr().to_string(),
732  source.to_string(), group.to_string(), 0);
734  vm_intf->vrf()->GetName(),
735  agent_->fabric_vn_name(), vm_intf,
736  source.to_v4(), group.to_v4());
737  } else {
738  MCTRACE(LogSG, "Delete VM Mcast VRF SG ",
739  vm_intf->primary_ip_addr().to_string(),
740  source.to_string(), group.to_string(), 0);
742  vm_intf->vrf()->GetName(), vm_intf,
743  source.to_v4(), group.to_v4());
744  }
745 
746  return;
747 }
748 
749 // Accept/reject <S,G> based on the multicast policy configured
750 // by the user/application.
752  IpAddress group) {
753 
754  if (!gif) {
755  return false;
756  }
757 
759  VnEntry *vn = vrf ? vrf->vn() : NULL;
760  if (!vn) {
761  return false;
762  }
763 
764  const UuidList &mp_list = vn->mp_list();
765  if (!mp_list.size()) {
766  return true;
767  }
768 
769  UuidList::const_iterator it = mp_list.begin();
771  while (it != mp_list.end()) {
772  MulticastPolicyKey key(*it);
773  MulticastPolicyEntry *entry = static_cast<MulticastPolicyEntry *>
774  (table->FindActiveEntry(&key));
775  SourceGroupInfo::Action action = entry->GetAction(source, group);
776  if (action == SourceGroupInfo::ACTION_PASS) {
777  return true;
778  }
779  it++;
780  }
781 
782  return false;
783 }
784 
785 // Send IGMP packet generated by the GMP to particular destination
786 bool GmpProto::SendPacket(GmpIntf *gif, uint8_t *pkt, uint32_t pkt_len,
787  IpAddress dest) {
788 
789  GmpPacket packet(pkt, pkt_len, dest);
790 
791  if (!cb_) {
792  return false;
793  }
794 
795  const VrfEntry *vrf = agent_->vrf_table()->FindVrfFromName(
796  gif->get_vrf_name());
797  if (!vrf) {
798  return false;
799  }
800 
801  return cb_(vrf, gif->get_ip_address(), &packet);
802 }
803 
805  const std::string &task_name, int instance,
806  boost::asio::io_context &io) {
807 
808  GmpProto *proto_inst = new GmpProto(type, agent, task_name, instance, io);
809  if (!proto_inst) {
810  return NULL;
811  }
812 
813  return proto_inst;
814 }
815 
817  if (!proto_inst) {
818  return false;
819  }
820 
821  delete proto_inst;
822 
823  return true;
824 }
825 
826 // Callback registered with GMP to check <S,G> for multicast policy
828  gmp_addr_string source, gmp_addr_string group)
829 {
830  if (!gd || !intf) {
831  return FALSE;
832  }
833 
834  if (gd->mgm_gd_af != MCAST_AF_IPV4) {
835  return FALSE;
836  }
837 
838  GmpProto *gmp_proto = (GmpProto *)gd->gmp_sm;
839  GmpIntf *gif = (GmpIntf *)intf->vm_interface;
840 
841  if (!gmp_proto || !gif) {
842  return FALSE;
843  }
844 
845  uint32_t addr;
846  memcpy(&addr, &source, IPV4_ADDR_LEN);
847  IpAddress source_addr = Ip4Address(ntohl(addr));
848  memcpy(&addr, &group, IPV4_ADDR_LEN);
849  IpAddress group_addr = Ip4Address(ntohl(addr));
850 
851  bool permit = gmp_proto->MulticastPolicyCheck(gif, source_addr, group_addr);
852 
853  return (permit ? TRUE : FALSE);
854 }
855 
857 {
858  if (!gd) {
859  return;
860  }
861 
862  GmpProto *gmp_proto = (GmpProto *)gd->gmp_sm;
863 
864  gmp_proto->GmpNotificationReady();
865 
866  return;
867 }
868 
869 // Function to handle per-<S,G> notifications
871  int group_action, gmp_addr_string source,
872  gmp_addr_string group)
873 {
874  if (!gd || !intf) {
875  return;
876  }
877 
878  if (gd->mgm_gd_af != MCAST_AF_IPV4) {
879  return;
880  }
881 
882  GmpProto *gmp_proto = (GmpProto *)gd->gmp_sm;
883  GmpIntf *gif = (GmpIntf *)intf->vm_interface;
884 
885  if (!gmp_proto || !gif) {
886  return;
887  }
888 
889  uint32_t addr;
890  memcpy(&addr, &source, IPV4_ADDR_LEN);
891  IpAddress source_addr = Ip4Address(ntohl(addr));
892  memcpy(&addr, &group, IPV4_ADDR_LEN);
893  IpAddress group_addr = Ip4Address(ntohl(addr));
894 
895  gmp_proto->GroupNotify(gif, source_addr, group_addr, group_action);
896 }
897 
898 // C-based function to handle per-<S,G> resync notifications
900  gmp_addr_string source, gmp_addr_string group)
901 {
902  if (!gd || !intf) {
903  return;
904  }
905 
906  if (gd->mgm_gd_af != MCAST_AF_IPV4) {
907  return;
908  }
909 
910  GmpProto *gmp_proto = (GmpProto *)gd->gmp_sm;
911  GmpIntf *gif = (GmpIntf *)intf->vm_interface;
912 
913  if (!gmp_proto || !gif) {
914  return;
915  }
916 
917  uint32_t addr;
918  memcpy(&addr, &source, IPV4_ADDR_LEN);
919  IpAddress source_addr = Ip4Address(ntohl(addr));
920  memcpy(&addr, &group, IPV4_ADDR_LEN);
921  IpAddress group_addr = Ip4Address(ntohl(addr));
922 
923  gmp_proto->ResyncNotify(gif, source_addr, group_addr);
924 }
925 
926 // C-based function to handle per-host, per-<S,G> notifications
927 void gmp_host_update(mgm_global_data *gd, gmp_intf *intf, boolean join,
928  gmp_addr_string host, gmp_addr_string source,
929  gmp_addr_string group)
930 {
931  if (!gd || !intf) {
932  return;
933  }
934 
935  if (gd->mgm_gd_af != MCAST_AF_IPV4) {
936  return;
937  }
938 
939  GmpProto *gmp_proto = (GmpProto *)gd->gmp_sm;
940  GmpIntf *gif = (GmpIntf *)intf->vm_interface;
941 
942  if (!gmp_proto || !gif) {
943  return;
944  }
945 
946  uint32_t addr;
947  memcpy(&addr, &host, IPV4_ADDR_LEN);
948  IpAddress host_addr = Ip4Address(ntohl(addr));
949  memcpy(&addr, &source, IPV4_ADDR_LEN);
950  IpAddress source_addr = Ip4Address(ntohl(addr));
951  memcpy(&addr, &group, IPV4_ADDR_LEN);
952  IpAddress group_addr = Ip4Address(ntohl(addr));
953 
954  gmp_proto->UpdateHostInSourceGroup(gif, join ? true : false, host_addr,
955  source_addr, group_addr);
956 }
957 
958 // Allocate buffer for use in sending IGMP packet
960 {
961  if (!gd || !intf) {
962  return NULL;
963  }
964 
965  GmpProto *gmp_proto = (GmpProto *)gd->gmp_sm;
966  return gmp_proto->GmpBufferGet();
967 }
968 
969 // Free the allocated buffer used in sending IGMP packet
970 void gmp_free_send_buffer(mgm_global_data *gd, gmp_intf *intf, uint8_t *buffer)
971 {
972  if (!gd || !intf) {
973  return;
974  }
975 
976  GmpProto *gmp_proto = (GmpProto *)gd->gmp_sm;
977  gmp_proto->GmpBufferFree(buffer);
978 
979  return;
980 }
981 
982 // Send IGMP packet out to the VMs.
983 void gmp_send_one_packet(mgm_global_data *gd, gmp_intf *intf, uint8_t *pkt,
984  uint32_t pkt_len, gmp_addr_string dest)
985 {
986  if (!gd || !intf) {
987  return;
988  }
989 
990  GmpProto *gmp_proto = (GmpProto *)gd->gmp_sm;
991  GmpIntf *gif = (GmpIntf *)intf->vm_interface;
992 
993  uint32_t addr;
994  memcpy(&addr, &dest, IPV4_ADDR_LEN);
995  IpAddress dst_addr = IpAddress(Ip4Address(ntohl(addr)));
996 
997  gmp_proto->SendPacket(gif, pkt, pkt_len, dst_addr);
998 
999  return;
1000 }
MulticastHandler * multicast() const
Definition: operdb_init.h:53
string vrf_name_
Definition: gmp_proto.h:106
uint32_t gmp_g_del_count_
Definition: gmp_proto.h:135
bool GmpNotificationHandler()
Definition: gmp_proto.cc:492
void AddVmInterfaceToSourceGroup(const std::string &mvpn_vrf_name, const std::string &vn_name, const VmInterface *vm_itf, const Ip4Address &src_addr, const Ip4Address &grp_addr)
Definition: multicast.cc:1795
static bool DeleteTaskMap(TaskMap *task_map)
Definition: task_map.cc:57
Callback cb_
Definition: gmp_proto.h:199
friend class GmpProto
Definition: gmp_proto.h:217
#define MGM_GROUP_ADDED
Definition: gmp_map.h:28
friend class GmpIntf
Definition: gmp_proto.h:207
void TriggerMvpnNotification(const VmInterface *vm_intf, bool join, IpAddress source, IpAddress group)
Definition: gmp_proto.cc:697
uint8_t flags_
Definition: gmp_proto.h:50
Type type() const
Definition: interface.h:112
static GmpProto * CreateGmpProto(GmpType::Type type, Agent *agent, const std::string &name, int instance, boost::asio::io_context &io)
Definition: gmp_proto.cc:804
void gmp_free_send_buffer(mgm_global_data *gd, gmp_intf *intf, uint8_t *buffer)
Definition: gmp_proto.cc:970
bool GmpProcessPkt(const VmInterface *vm_itf, void *rcv_pkt, uint32_t packet_len, IpAddress ip_saddr, IpAddress ip_daddr)
Definition: gmp_proto.cc:443
VnGmpSGList gmp_sg_list_
Definition: gmp_proto.h:79
Definition: vrf.h:86
void GmpItfNotify(DBTablePartBase *part, DBEntryBase *entry)
Definition: gmp_proto.cc:337
TaskTrigger * gmp_notif_trigger_
Definition: gmp_proto.h:197
DBTableBase::ListenerId itf_listener_id_
Definition: gmp_proto.h:193
Agent * agent_
Definition: gmp_proto.h:187
DBState * GetState(DBTableBase *tbl_base, ListenerId listener) const
Definition: db_entry.cc:37
#define TRUE
Definition: mcast_common.h:15
bool IsSet() const
Definition: task_trigger.h:42
uint8_t * gmp_get_send_buffer(mgm_global_data *gd, gmp_intf *intf)
Definition: gmp_proto.cc:959
const boost::uuids::uuid & GetUuid() const
Definition: interface.h:113
bool Stop()
Definition: gmp_proto.cc:139
static bool DeleteGmpProto(GmpProto *gmp_proto)
Definition: gmp_proto.cc:816
VrfEntry * FindVrfFromName(const string &name)
Definition: vrf.cc:873
VnGmpIntfMap gmp_intf_map_
Definition: gmp_proto.h:78
GmpProto(GmpType::Type type, Agent *agent, const std::string &task_name, int instance, boost::asio::io_context &io)
Definition: gmp_proto.cc:76
const VnIpam * GetIpam(const IpAddress &ip) const
Definition: vn.cc:651
void * vm_interface
Definition: gmp_intf.h:49
uint32_t gmp_sg_add_count_
Definition: gmp_proto.h:137
VnGmpIntfSGList gmp_intf_sg_list_
Definition: gmp_proto.h:68
Definition: vn.h:28
const IpAddress get_ip_address()
Definition: gmp_proto.h:98
DBTableBase::ListenerId vn_listener_id_
Definition: gmp_proto.h:192
bool querying_
Definition: gmp_proto.h:109
const string & get_vrf_name()
Definition: gmp_proto.h:100
#define MCTRACE(obj,...)
Definition: multicast.h:18
struct gmp_intf_ gmp_intf
bool IsDeleted() const
Definition: db_entry.h:49
void * gmp_sm
Definition: gmp_map.h:16
void SetState(DBTableBase *tbl_base, ListenerId listener, DBState *state)
Definition: db_entry.cc:22
SandeshTraceBufferPtr MulticastTraceBuf
boost::asio::ip::address IpAddress
Definition: address.h:13
int instance_
Definition: gmp_proto.h:189
#define IPV4_ADDR_LEN
Definition: gmp.h:24
GmpType::Type type_
Definition: gmp_proto.h:186
uint8_t * GmpBufferGet()
Definition: gmp_proto.cc:483
DBTableBase * parent()
std::string vrf_name_
Definition: gmp_proto.h:87
~GmpProto()
Definition: gmp_proto.cc:94
AgentDBEntry * FindActiveEntry(const DBEntry *key)
Definition: agent_db.cc:110
InterfaceTable * interface_table() const
Definition: agent.h:465
boost::uuids::uuid uuid
VnTable * vn_table() const
Definition: agent.h:495
void CreateMulticastVrfSourceGroup(const std::string &vrf_name, const std::string &vn_name, const Ip4Address &src_addr, const Ip4Address &grp_addr)
Definition: multicast.cc:1620
gmp_intf * gmp_attach_intf(mgm_global_data *gd, void *mif_state)
Definition: gmp_map.cc:177
void DeleteVmInterfaceFromVrfSourceGroup(const std::string &vrf_name, const VmInterface *vm_itf, const Ip4Address &src_addr, const Ip4Address &grp_addr)
Definition: multicast.cc:1843
VnGmpSGList::iterator VnGmpSGListIter
Definition: gmp_proto.h:73
const string & GetName() const
Definition: vrf.h:100
bool Start()
Definition: gmp_proto.cc:98
#define FALSE
Definition: mcast_common.h:14
void SetEvpnMulticastSGFlags(const std::string &vrf_name, const Ip4Address &src_addr, const Ip4Address &grp_addr, uint32_t flags)
Definition: multicast.cc:1970
boost::shared_ptr< TraceBuffer< SandeshTrace > > SandeshTraceBufferPtr
Definition: sandesh_trace.h:18
void UpdateHostInSourceGroup(GmpIntf *gif, bool join, IpAddress host, IpAddress source, IpAddress group)
Definition: gmp_proto.cc:655
bool MulticastPolicyCheck(GmpIntf *gif, IpAddress source, IpAddress group)
Definition: gmp_proto.cc:751
VrfEntry * vrf() const
Definition: interface.h:115
gmp_proto
Definition: gmp.h:45
void DeleteMulticastVrfSourceGroup(const std::string &vrf_name, const Ip4Address &src_addr, const Ip4Address &grp_addr)
Definition: multicast.cc:1709
IpAddress vmi_v4_addr_
Definition: gmp_proto.h:88
void Unregister(ListenerId listener)
Definition: db_table.cc:186
OperDB * oper_db() const
Definition: agent.cc:1013
void ResyncNotify(GmpIntf *gif, IpAddress source, IpAddress group)
Definition: gmp_proto.cc:649
task * task_
Definition: task_map.h:22
InterfaceConstRef FindVmi(const boost::uuids::uuid &u)
Definition: interface.cc:419
ListenerId Register(ChangeCallback callback, const std::string &name="unspecified")
Definition: db_table.cc:181
const std::string & fabric_vrf_name() const
Definition: agent.h:903
IpAddress ip_addr_
Definition: gmp_proto.h:107
bool mvpn_ipv4_enable() const
Definition: agent_param.h:565
bool AddVmInterfaceToVrfSourceGroup(const std::string &vrf_name, const std::string &vn_name, const VmInterface *vm_itf, const Ip4Address &src_addr, const Ip4Address &grp_addr)
Definition: multicast.cc:1752
void gmp_deinit(mc_af mcast_af)
Definition: gmp_map.cc:146
uint8_t type
Definition: load_balance.h:109
IpAddress default_gw
Definition: vn.h:31
Definition: agent.h:358
uint32_t refcount_
Definition: gmp_proto.h:52
static TaskScheduler * GetInstance()
Definition: task.cc:547
boost::intrusive_ptr< const Interface > InterfaceConstRef
Definition: agent.h:51
mgm_global_data * gmp_init(mc_af mcast_af, task *tp, void *gmp_sm)
Definition: gmp_map.cc:115
bool DeleteIntf(GmpIntf *gif)
Definition: gmp_proto.cc:434
const std::vector< VnIpam > & GetVnIpam() const
Definition: vn.h:171
const VnEntry * vn() const
boolean gmp_update_intf_state(mgm_global_data *gd, gmp_intf *gif, const gmp_addr_string *intf_addr)
Definition: gmp_map.cc:221
uint32_t gmp_sg_del_count_
Definition: gmp_proto.h:138
uint32_t gmp_g_add_count_
Definition: gmp_proto.h:134
void SetGif(gmp_intf *gif)
Definition: gmp_proto.h:96
AgentParam * params() const
Definition: agent.h:1218
boolean gmp_policy_check(mgm_global_data *gd, gmp_intf *intf, gmp_addr_string source, gmp_addr_string group)
Definition: gmp_proto.cc:827
#define MGM_GROUP_SRC_REMOVED
Definition: gmp_map.h:30
static Timer * CreateTimer(boost::asio::io_context &service, const std::string &name, int task_id=Timer::GetTimerTaskId(), int task_instance=Timer::GetTimerInstanceId(), bool delete_on_completion=false)
Definition: timer.cc:201
static const int kGmpTriggerRestartTimer
Definition: gmp_proto.h:122
void ClearState(DBTableBase *tbl_base, ListenerId listener)
Definition: db_entry.cc:73
void GmpBufferFree(uint8_t *pkt)
Definition: gmp_proto.cc:487
IpAddress dns_server
Definition: vn.h:33
std::vector< boost::uuids::uuid > UuidList
Definition: agent.h:203
boost::asio::ip::address_v4 Ip4Address
Definition: address.h:14
boost::asio::io_context & io_
Definition: gmp_proto.h:190
bool Cancel()
Definition: timer.cc:150
Definition: vn.h:151
gmp_intf * GetGif()
Definition: gmp_proto.h:97
mc_af mgm_gd_af
Definition: gmp_map.h:18
VrfTable * vrf_table() const
Definition: agent.h:485
Timer * gmp_trigger_timer_
Definition: gmp_proto.h:196
void Reset()
Definition: task_trigger.cc:54
const Ip4Address & primary_ip_addr() const
IpAddress group_
Definition: gmp_proto.h:49
bool set_ip_address(const IpAddress &ip_addr)
Definition: gmp_proto.cc:40
boolean gmp_process_pkt(mgm_global_data *gd, gmp_intf *gif, void *rcv_pkt, u_int32_t packet_len, const gmp_addr_string *src_addr, const gmp_addr_string *dst_addr)
Definition: gmp_map.cc:241
IpAddress source_
Definition: gmp_proto.h:48
bool SendPacket(GmpIntf *gif, uint8_t *pkt, uint32_t pkt_len, IpAddress dest)
Definition: gmp_proto.cc:786
void gmp_notification_ready(mgm_global_data *gd)
Definition: gmp_proto.cc:856
VnGmpIntfSGList::iterator VnGmpSGIntfListIter
Definition: gmp_proto.h:59
VrfEntry * GetVrf() const
Definition: vn.h:170
VmInterface::VmiType vmi_type() const
bool GmpNotificationTimer()
Definition: gmp_proto.cc:511
bool Start(int time, Handler handler, ErrorHandler error_handler=NULL)
Definition: timer.cc:108
bool set_vrf_name(const std::string &vrf_name)
Definition: gmp_proto.cc:58
#define GMP_TX_BUFF_LEN
Definition: gmp_proto.h:14
VnEntry * vn() const
Definition: vrf.h:101
VmIpInterfaceMap vm_ip_to_vmi_
Definition: gmp_proto.h:205
void gmp_group_notify(mgm_global_data *gd, gmp_intf *gif, int group_action, gmp_addr_string source, gmp_addr_string group)
Definition: gmp_proto.cc:870
bool igmp_enabled() const
int itf_attach_count_
Definition: gmp_proto.h:202
TaskMap * task_map_
Definition: gmp_proto.h:195
GmpIntf * CreateIntf()
Definition: gmp_proto.cc:420
#define MGM_GROUP_REMOVED
Definition: gmp_map.h:29
gmp_intf * gif_
Definition: gmp_proto.h:108
static TaskMap * CreateTaskMap(Agent *agent, const std::string &name, int instance, boost::asio::io_context &io)
Definition: task_map.cc:38
void gmp_cache_resync_notify(mgm_global_data *gd, gmp_intf *gif, gmp_addr_string source, gmp_addr_string group)
Definition: gmp_proto.cc:899
void GmpIntfSGClear(VnGmpDBState *state, VnGmpDBState::VnGmpIntfState *gmp_intf_state)
Definition: gmp_proto.cc:168
const string & GetName() const
Definition: vn.h:162
void gmp_detach_intf(mgm_global_data *gd, gmp_intf *gif)
Definition: gmp_map.cc:207
DBTablePartBase * get_table_partition() const
Definition: db_entry.cc:115
MulticastPolicyTable * mp_table() const
Definition: agent.h:642
const std::string & fabric_vn_name() const
Definition: agent.h:901
bool set_gmp_querying(bool querying)
Definition: gmp_proto.cc:64
const UuidList & mp_list() const
Definition: vn.h:230
GmpIntf(const GmpProto *)
Definition: gmp_proto.cc:30
boolean gmp_notification_handler(mgm_global_data *gd)
Definition: gmp_map.cc:511
const GmpProto * gmp_proto_
Definition: gmp_proto.h:105
void gmp_host_update(mgm_global_data *gd, gmp_intf *intf, boolean join, gmp_addr_string host, gmp_addr_string source, gmp_addr_string group)
Definition: gmp_proto.cc:927
void gmp_send_one_packet(mgm_global_data *gd, gmp_intf *intf, uint8_t *pkt, uint32_t pkt_len, gmp_addr_string dest)
Definition: gmp_proto.cc:983
SourceGroupInfo::Action GetAction(IpAddress source, IpAddress group) const
GmpStats stats_
Definition: gmp_proto.h:201
void TriggerEvpnNotification(const VmInterface *vm_intf, bool join, IpAddress source, IpAddress group)
Definition: gmp_proto.cc:726
void GmpVnNotify(DBTablePartBase *part, DBEntryBase *entry)
Definition: gmp_proto.cc:210
void GmpNotificationReady()
Definition: gmp_proto.cc:525
boolean gmp_update_intf_querying(mgm_global_data *gd, gmp_intf *gif, boolean query)
Definition: gmp_map.cc:230
void GroupNotify(GmpIntf *gif, IpAddress source, IpAddress group, int group_action)
Definition: gmp_proto.cc:537
struct task_ task
const std::string & name_
Definition: gmp_proto.h:188
static bool DeleteTimer(Timer *Timer)
Definition: timer.cc:222
mgm_global_data * gd_
Definition: gmp_proto.h:198
void DeleteVmInterfaceFromSourceGroup(const std::string &mvpn_vrf_name, const VmInterface *vm_itf, const Ip4Address &src_addr, const Ip4Address &grp_addr)
Definition: multicast.cc:1872
const std::string & fabric_policy_vrf_name() const
Definition: agent.h:908