OpenSDN source code
vxlan_templates.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018 Juniper Networks, Inc. All rights reserved.
3  * Copyright (c) 2022 - 2026 Matvey Kraposhin.
4  * Copyright (c) 2024 - 2026 Elena Zizganova.
5  */
6 
7 #include <oper/bgp_as_service.h>
8 
9 template <class ItType>
10 std::vector<IpAddress> VxlanRoutingManager::ItemNexthopsToVector(ItType *item) {
11  std::vector<IpAddress> nh_addr;
12  const uint32_t n_items = item->entry.next_hops.next_hop.size();
13  for (uint32_t i_nh=0; i_nh < n_items; i_nh++) {
14  const IpAddress nh_ip = IpAddress::from_string(
15  item->entry.next_hops.next_hop[i_nh].address);
16  nh_addr.insert(nh_addr.end(), nh_ip);
17  }
18 
19  return nh_addr;
20 }
21 
22 // A nexthop is counted as BGPaaS when it has MPLS label and this
23 // label points to the VmInterface linked with the BGPaaS object
24 static bool IsBgpaasInterfaceNexthop(const Agent* agent, const NextHop* nh) {
25  if (nh->GetType() != NextHop::INTERFACE ||
26  nh->mpls_label() == NULL) {
27  return false;
28  }
29 
30  const InterfaceNH *intf_nh = static_cast<const InterfaceNH *>(nh);
31  const Interface *interface = intf_nh->GetInterface();
32  if (interface->type() != Interface::VM_INTERFACE)
33  return false;
34 
35  const VmInterface *vm_intf =
36  dynamic_cast<const VmInterface*>(interface);
37  const Ip4Address& intf_ip4 = vm_intf->primary_ip_addr();
38  const Ip6Address& intf_ip6 = vm_intf->primary_ip6_addr();
39 
40  if (agent->oper_db()->bgp_as_a_service()->
41  IsBgpService(vm_intf, IpAddress(intf_ip4), IpAddress(intf_ip4))) {
42  return true;
43  }
44  if (agent->oper_db()->bgp_as_a_service()->
45  IsBgpService(vm_intf, IpAddress(intf_ip6), IpAddress(intf_ip6))) {
46  return true;
47  }
48  return false;
49 }
50 
51 // A composite nexthop is counted as BGPaaS when at least one component is
52 // an interface
53 static bool IsBgpaasCompositeNexthop(const Agent* agent, const NextHop* nh) {
54  if (nh->GetType() != NextHop::COMPOSITE)
55  return false;
56  const CompositeNH *composite_nh = dynamic_cast<const CompositeNH*>(nh);
57  uint32_t n_comps = composite_nh->ComponentNHCount();
58  for (uint32_t i=0; i < n_comps; i++) {
59  const NextHop *c_nh = composite_nh->GetNH(i);
60  if (c_nh != nullptr &&
61  IsBgpaasInterfaceNexthop(agent, c_nh) == true) {
62  return true;
63  }
64  }
65  return false;
66 }
67 
68 template<typename NhType>
70  const std::string& vrf_name,
71  const NhType &nh_item,
72  ComponentNHKeyList& comp_nh_list,
73  std::vector<std::string> &peer_sources) {
74 
75  for (const auto &nexthop_addr : peer_sources) {
76  const Agent *agent = Agent::GetInstance();
77  IpAddress nh_ip;
78  uint32_t prefix_len;
79  boost::system::error_code ec;
80 
81  if (is_ipv4_string(nexthop_addr)) {
82  nh_ip = Ip4Address::from_string(ipv4_prefix(nexthop_addr), ec);
83  prefix_len = ipv4_prefix_len(nexthop_addr);
84  } else if (is_ipv6_string(nexthop_addr)) {
85  nh_ip = Ip6Address::from_string(ipv6_prefix(nexthop_addr), ec);
86  prefix_len = ipv6_prefix_len(nexthop_addr);
87  } else {
88  LOG(ERROR, "Error in VxlanRoutingManager"
89  << "::AddBgpaasInterfaceComponentToList"
90  << ", nexthop_addr = " << nexthop_addr
91  << " is not an IPv4 or IPv6 prefix");
92  return;
93  }
94  if (ec) {
95  continue;
96  }
97  const AgentRoute *intf_rt =
98  FindEvpnOrInetRoute(agent, vrf_name, nh_ip, prefix_len, nh_item);
99  const AgentPath *loc_path =
101  if (loc_path == nullptr) {
102  continue;
103  }
104  if (loc_path->nexthop() == nullptr) {
105  continue;
106  }
107  if (IsBgpaasInterfaceNexthop(agent, loc_path->nexthop())) {
108  DBEntryBase::KeyPtr key_ptr =
109  loc_path->nexthop()->GetDBRequestKey();
110  NextHopKey *nh_key =
111  static_cast<NextHopKey *>(key_ptr.release());
112  std::unique_ptr<const NextHopKey> nh_key_ptr(nh_key);
113  ComponentNHKeyPtr component_nh_key(new
115  std::move(nh_key_ptr)));
116  comp_nh_list.push_back(component_nh_key);
117  } else if (IsBgpaasCompositeNexthop(agent, loc_path->nexthop())) {
118  CompositeNH *loc_comp_nh = dynamic_cast<CompositeNH*>
119  (loc_path->nexthop());
120 
121  DBEntryBase::KeyPtr key_ptr =
122  loc_comp_nh->GetDBRequestKey();
123  CompositeNHKey *nh_key =
124  static_cast<CompositeNHKey *>(key_ptr.release());
125  std::unique_ptr<const NextHopKey> nh_key_ptr(nh_key);
126 
127  if (nh_key == nullptr){
128  LOG(ERROR, "Error in VxlanRoutingManager::"
129  << "::AddBgpaasInterfaceComponentToList"
130  << ", null nh key");
131  }
132 
133  const ComponentNHList& component_nh_list =
134  loc_comp_nh->component_nh_list();
135  for (auto &component_nh : component_nh_list) {
136  std::unique_ptr<const NextHopKey> nh_key_ptr;
137  ComponentNHKeyPtr component_nh_key;
138  if (component_nh.get() == nullptr) {
139  // component_nh_key.reset(NULL);
140  } else {
141  DBEntryBase::KeyPtr key =
142  component_nh.get()->nh()->GetDBRequestKey();
143  NextHopKey *nh_key =
144  static_cast<NextHopKey *>(key.release());
145  nh_key_ptr.reset(nh_key);
146  component_nh_key.reset(
148  std::move(nh_key_ptr)));
149  }
150  comp_nh_list.push_back(component_nh_key);
151  }
152  }
153  }
154 }
155 
156 template<typename NhType>
158  const std::string& prefix_str,
159  const std::string& vrf_name,
160  const NhType &nh_item,
161  ComponentNHKeyList& comp_nh_list,
162  std::vector<std::string> &peer_sources) {
163  const Agent *agent = Agent::GetInstance();
164  IpAddress ip_addr;
165  uint32_t prefix_len;
166  boost::system::error_code ec;
167 
168  if (is_ipv4_string(prefix_str)) {
169  ip_addr = Ip4Address::from_string(ipv4_prefix(prefix_str), ec);
170  prefix_len = ipv4_prefix_len(prefix_str);
171  } else if (is_ipv6_string(prefix_str)) {
172  std::string addr_str = ipv6_prefix(prefix_str);
173  prefix_len = ipv6_prefix_len(prefix_str);
174  ip_addr = Ip6Address::from_string(addr_str, ec);
175  } else {
176  LOG(ERROR, "Error in VxlanRoutingManager::AddInterfaceComponentToList"
177  << ", prefix_str = " << prefix_str
178  << " is not an IPv4 or IPv6 prefix");
179  return;
180  }
181 
182  if (ec) {
183  LOG(ERROR, "Possible error in "
184  << "VxlanRoutingManager::AddInterfaceComponentToList"
185  << ", cannot convert prefix_str = " << prefix_str
186  << " to IPv4 or IPv6 address");
187  return;
188  }
189 
190  const AgentRoute *intf_rt =
191  FindEvpnOrInetRoute(agent, vrf_name, ip_addr, prefix_len, nh_item);
192  if (intf_rt == NULL) {
193  AddBgpaasInterfaceComponentToList(vrf_name, nh_item, comp_nh_list,
194  peer_sources);
195  return;
196  }
197 
198  const AgentPath *loc_path =
200  if (loc_path == NULL) {
201  AddBgpaasInterfaceComponentToList(vrf_name, nh_item, comp_nh_list,
202  peer_sources);
203  return;
204  }
205  if (loc_path->nexthop() == NULL) {
206  AddBgpaasInterfaceComponentToList(vrf_name, nh_item, comp_nh_list,
207  peer_sources);
208  return;
209  }
210 
211  // Case 1. NextHop is an interface
212  if (loc_path->nexthop()->GetType() == NextHop::INTERFACE) {
213  DBEntryBase::KeyPtr key_ptr =
214  loc_path->nexthop()->GetDBRequestKey();
215  NextHopKey *nh_key =
216  static_cast<NextHopKey *>(key_ptr.release());
217  std::unique_ptr<const NextHopKey> nh_key_ptr(nh_key);
218  ComponentNHKeyPtr component_nh_key(new ComponentNHKey(MplsTable::kInvalidLabel, // label
219  std::move(nh_key_ptr)));
220  comp_nh_list.push_back(component_nh_key);
221  return;
222  }
223 
224  // Case 2. NextHop is a composite of interfaces
225  // Copy all interfaces from this composite
226  // into the components list
227  if (loc_path->nexthop()->GetType() == NextHop::COMPOSITE) {
228  CompositeNH *loc_comp_nh = dynamic_cast<CompositeNH*>
229  (loc_path->nexthop());
230 
231  DBEntryBase::KeyPtr key_ptr =
232  loc_comp_nh->GetDBRequestKey();
233  CompositeNHKey *nh_key =
234  static_cast<CompositeNHKey *>(key_ptr.release());
235  std::unique_ptr<const NextHopKey> nh_key_ptr(nh_key);
236 
237  if (nh_key == NULL){
238  LOG(ERROR, "Error in VxlanRoutingManager::AddInterfaceComponentToList"
239  << ", null nh key");
240  assert(nh_key != NULL);
241  }
242 
243  // Refresh on path_preference.sequence change
244  const ComponentNHList& component_nh_list =
245  loc_comp_nh->component_nh_list();
246  for (ComponentNHList::const_iterator
247  it_nh = component_nh_list.begin();
248  it_nh != component_nh_list.end(); it_nh++) {
249  // nullptr means deleted component, which
250  // can be reused later
251  std::unique_ptr<const NextHopKey> nh_key_ptr;
252  ComponentNHKeyPtr component_nh_key;
253  if (it_nh->get() == NULL) {
254  // component_nh_key.reset(NULL);
255  } else {
256  DBEntryBase::KeyPtr key =
257  it_nh->get()->nh()->GetDBRequestKey();
258  NextHopKey *nh_key =
259  static_cast<NextHopKey *>(key.release());
260  nh_key_ptr.reset(nh_key);
261  component_nh_key.reset(
262  new ComponentNHKey(MplsTable::kInvalidLabel, std::move(nh_key_ptr)));
263  }
264  comp_nh_list.push_back(component_nh_key);
265  }
266  }
267 } // AddInterfaceComponentToList func
268 
269 //
270 // END-OF-FILE
271 //
boost::asio::ip::address_v6 Ip6Address
Definition: address.h:15
boost::asio::ip::address IpAddress
Definition: address.h:13
boost::asio::ip::address_v4 Ip4Address
Definition: address.h:14
NextHop * nexthop() const
Definition: agent_path.cc:87
Base class for all Route entries in agent.
Definition: agent_route.h:224
const AgentPath * FindIntfOrCompLocalVmPortPath() const
Finds path to an interface or a composite of interfaces and returns it. The priority is given to comp...
Definition: agent_route.cc:817
Definition: agent.h:360
OperDB * oper_db() const
Definition: agent.cc:1016
static Agent * GetInstance()
Definition: agent.h:438
size_t ComponentNHCount() const
Definition: nexthop.h:1815
const ComponentNHList & component_nh_list() const
Definition: nexthop.h:1869
const NextHop * GetNH(uint32_t idx) const
Definition: nexthop.h:1832
virtual KeyPtr GetDBRequestKey() const
Definition: nexthop.cc:2183
std::unique_ptr< DBRequestKey > KeyPtr
Definition: db_entry.h:24
virtual KeyPtr GetDBRequestKey() const =0
@ VM_INTERFACE
Definition: interface.h:37
static const uint32_t kInvalidLabel
Definition: mpls.h:101
const MplsLabel * mpls_label() const
Definition: nexthop.h:434
@ COMPOSITE
Definition: nexthop.h:354
@ INTERFACE
Definition: nexthop.h:351
Type GetType() const
Definition: nexthop.h:405
BgpAsAService * bgp_as_a_service() const
Definition: operdb_init.h:77
const Ip4Address & primary_ip_addr() const
const Ip6Address & primary_ip6_addr() const
static void AddBgpaasInterfaceComponentToList(const std::string &vrf_name, const NhType &nh_item, ComponentNHKeyList &comp_nh_list, std::vector< std::string > &peer_sources)
static bool is_ipv4_string(const std::string &prefix_str)
Determines whether the address string contains an IPv4 address as substring or not.
static AgentRoute * FindEvpnOrInetRoute(const Agent *agent, const std::string &vrf_name, const IpAddress &ip_addr, uint32_t prefix_len, const autogen::EnetNextHopType &nh_item)
Finds a route with the given prefix address and len in the EVPN table.
static std::string ipv6_prefix(const std::string &prefix_str)
Extracts an IPv6 address string from the prefix string.
static std::vector< IpAddress > ItemNexthopsToVector(ItType *item)
Templates.
static uint32_t ipv4_prefix_len(const std::string &prefix_str)
Extracts length of IPv4 subnet address from the prefix string.
static void AddInterfaceComponentToList(const std::string &prefix_str, const std::string &vrf_name, const NhType &nh_item, ComponentNHKeyList &comp_nh_list, std::vector< std::string > &peer_sources)
Adds an interface or a composite of interfaces nexthops to the list of components NH keys needed for ...
static bool is_ipv6_string(const std::string &prefix_str)
Determines whether the address string contains an IPv6 address as substring or not.
static std::string ipv4_prefix(const std::string &prefix_str)
Extracts an IPv4 address string from the prefix string.
static uint32_t ipv6_prefix_len(const std::string &prefix_str)
Extracts length of IPv6 subnet address from the prefix string.
#define LOG(_Level, _Msg)
Definition: logging.h:34
std::vector< ComponentNHPtr > ComponentNHList
Definition: nexthop.h:1637
boost::shared_ptr< const ComponentNHKey > ComponentNHKeyPtr
Definition: nexthop.h:1639
std::vector< ComponentNHKeyPtr > ComponentNHKeyList
Definition: nexthop.h:1641
static bool IsBgpaasCompositeNexthop(const Agent *agent, const NextHop *nh)
static bool IsBgpaasInterfaceNexthop(const Agent *agent, const NextHop *nh)