Line data Source code
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 0 : static bool IsBgpaasInterfaceNexthop(const Agent* agent, const NextHop* nh) {
25 0 : if (nh->GetType() != NextHop::INTERFACE ||
26 0 : nh->mpls_label() == NULL) {
27 0 : return false;
28 : }
29 :
30 0 : const InterfaceNH *intf_nh = static_cast<const InterfaceNH *>(nh);
31 0 : const Interface *interface = intf_nh->GetInterface();
32 0 : if (interface->type() != Interface::VM_INTERFACE)
33 0 : return false;
34 :
35 : const VmInterface *vm_intf =
36 0 : dynamic_cast<const VmInterface*>(interface);
37 0 : const Ip4Address& intf_ip4 = vm_intf->primary_ip_addr();
38 0 : const Ip6Address& intf_ip6 = vm_intf->primary_ip6_addr();
39 :
40 0 : if (agent->oper_db()->bgp_as_a_service()->
41 0 : IsBgpService(vm_intf, IpAddress(intf_ip4), IpAddress(intf_ip4))) {
42 0 : return true;
43 : }
44 0 : if (agent->oper_db()->bgp_as_a_service()->
45 0 : IsBgpService(vm_intf, IpAddress(intf_ip6), IpAddress(intf_ip6))) {
46 0 : return true;
47 : }
48 0 : return false;
49 : }
50 :
51 : // A composite nexthop is counted as BGPaaS when at least one component is
52 : // an interface
53 0 : static bool IsBgpaasCompositeNexthop(const Agent* agent, const NextHop* nh) {
54 0 : if (nh->GetType() != NextHop::COMPOSITE)
55 0 : return false;
56 0 : const CompositeNH *composite_nh = dynamic_cast<const CompositeNH*>(nh);
57 0 : uint32_t n_comps = composite_nh->ComponentNHCount();
58 0 : for (uint32_t i=0; i < n_comps; i++) {
59 0 : const NextHop *c_nh = composite_nh->GetNH(i);
60 0 : if (c_nh != nullptr &&
61 0 : IsBgpaasInterfaceNexthop(agent, c_nh) == true) {
62 0 : return true;
63 : }
64 : }
65 0 : return false;
66 : }
67 :
68 : template<typename NhType>
69 0 : void VxlanRoutingManager::AddBgpaasInterfaceComponentToList(
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 0 : for (const auto &nexthop_addr : peer_sources) {
76 0 : const Agent *agent = Agent::GetInstance();
77 0 : IpAddress nh_ip;
78 : uint32_t prefix_len;
79 0 : boost::system::error_code ec;
80 :
81 0 : if (is_ipv4_string(nexthop_addr)) {
82 0 : nh_ip = Ip4Address::from_string(ipv4_prefix(nexthop_addr), ec);
83 0 : prefix_len = ipv4_prefix_len(nexthop_addr);
84 0 : } else if (is_ipv6_string(nexthop_addr)) {
85 0 : nh_ip = Ip6Address::from_string(ipv6_prefix(nexthop_addr), ec);
86 0 : prefix_len = ipv6_prefix_len(nexthop_addr);
87 : } else {
88 0 : LOG(ERROR, "Error in VxlanRoutingManager"
89 : << "::AddBgpaasInterfaceComponentToList"
90 : << ", nexthop_addr = " << nexthop_addr
91 : << " is not an IPv4 or IPv6 prefix");
92 0 : return;
93 : }
94 0 : if (ec) {
95 0 : continue;
96 : }
97 : const AgentRoute *intf_rt =
98 0 : FindEvpnOrInetRoute(agent, vrf_name, nh_ip, prefix_len, nh_item);
99 : const AgentPath *loc_path =
100 0 : intf_rt->FindIntfOrCompLocalVmPortPath();
101 0 : if (loc_path == nullptr) {
102 0 : continue;
103 : }
104 0 : if (loc_path->nexthop() == nullptr) {
105 0 : continue;
106 : }
107 0 : if (IsBgpaasInterfaceNexthop(agent, loc_path->nexthop())) {
108 0 : DBEntryBase::KeyPtr key_ptr =
109 0 : loc_path->nexthop()->GetDBRequestKey();
110 : NextHopKey *nh_key =
111 0 : static_cast<NextHopKey *>(key_ptr.release());
112 0 : std::unique_ptr<const NextHopKey> nh_key_ptr(nh_key);
113 0 : ComponentNHKeyPtr component_nh_key(new
114 : ComponentNHKey(MplsTable::kInvalidLabel,
115 0 : std::move(nh_key_ptr)));
116 0 : comp_nh_list.push_back(component_nh_key);
117 0 : } else if (IsBgpaasCompositeNexthop(agent, loc_path->nexthop())) {
118 0 : CompositeNH *loc_comp_nh = dynamic_cast<CompositeNH*>
119 0 : (loc_path->nexthop());
120 :
121 0 : DBEntryBase::KeyPtr key_ptr =
122 0 : loc_comp_nh->GetDBRequestKey();
123 : CompositeNHKey *nh_key =
124 0 : static_cast<CompositeNHKey *>(key_ptr.release());
125 0 : std::unique_ptr<const NextHopKey> nh_key_ptr(nh_key);
126 :
127 0 : if (nh_key == nullptr){
128 0 : LOG(ERROR, "Error in VxlanRoutingManager::"
129 : << "::AddBgpaasInterfaceComponentToList"
130 : << ", null nh key");
131 : }
132 :
133 : const ComponentNHList& component_nh_list =
134 0 : loc_comp_nh->component_nh_list();
135 0 : for (auto &component_nh : component_nh_list) {
136 0 : std::unique_ptr<const NextHopKey> nh_key_ptr;
137 0 : ComponentNHKeyPtr component_nh_key;
138 0 : if (component_nh.get() == nullptr) {
139 : // component_nh_key.reset(NULL);
140 : } else {
141 0 : DBEntryBase::KeyPtr key =
142 0 : component_nh.get()->nh()->GetDBRequestKey();
143 : NextHopKey *nh_key =
144 0 : static_cast<NextHopKey *>(key.release());
145 0 : nh_key_ptr.reset(nh_key);
146 0 : component_nh_key.reset(
147 0 : new ComponentNHKey(MplsTable::kInvalidLabel,
148 0 : std::move(nh_key_ptr)));
149 0 : }
150 0 : comp_nh_list.push_back(component_nh_key);
151 : }
152 0 : }
153 : }
154 : }
155 :
156 : template<typename NhType>
157 0 : void VxlanRoutingManager::AddInterfaceComponentToList(
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 0 : const Agent *agent = Agent::GetInstance();
164 0 : IpAddress ip_addr;
165 : uint32_t prefix_len;
166 0 : boost::system::error_code ec;
167 :
168 0 : if (is_ipv4_string(prefix_str)) {
169 0 : ip_addr = Ip4Address::from_string(ipv4_prefix(prefix_str), ec);
170 0 : prefix_len = ipv4_prefix_len(prefix_str);
171 0 : } else if (is_ipv6_string(prefix_str)) {
172 0 : std::string addr_str = ipv6_prefix(prefix_str);
173 0 : prefix_len = ipv6_prefix_len(prefix_str);
174 0 : ip_addr = Ip6Address::from_string(addr_str, ec);
175 0 : } else {
176 0 : LOG(ERROR, "Error in VxlanRoutingManager::AddInterfaceComponentToList"
177 : << ", prefix_str = " << prefix_str
178 : << " is not an IPv4 or IPv6 prefix");
179 0 : return;
180 : }
181 :
182 0 : if (ec) {
183 0 : LOG(ERROR, "Possible error in "
184 : << "VxlanRoutingManager::AddInterfaceComponentToList"
185 : << ", cannot convert prefix_str = " << prefix_str
186 : << " to IPv4 or IPv6 address");
187 0 : return;
188 : }
189 :
190 : const AgentRoute *intf_rt =
191 0 : FindEvpnOrInetRoute(agent, vrf_name, ip_addr, prefix_len, nh_item);
192 0 : if (intf_rt == NULL) {
193 0 : AddBgpaasInterfaceComponentToList(vrf_name, nh_item, comp_nh_list,
194 : peer_sources);
195 0 : return;
196 : }
197 :
198 : const AgentPath *loc_path =
199 0 : intf_rt->FindIntfOrCompLocalVmPortPath();
200 0 : if (loc_path == NULL) {
201 0 : AddBgpaasInterfaceComponentToList(vrf_name, nh_item, comp_nh_list,
202 : peer_sources);
203 0 : return;
204 : }
205 0 : if (loc_path->nexthop() == NULL) {
206 0 : AddBgpaasInterfaceComponentToList(vrf_name, nh_item, comp_nh_list,
207 : peer_sources);
208 0 : return;
209 : }
210 :
211 : // Case 1. NextHop is an interface
212 0 : if (loc_path->nexthop()->GetType() == NextHop::INTERFACE) {
213 0 : DBEntryBase::KeyPtr key_ptr =
214 0 : loc_path->nexthop()->GetDBRequestKey();
215 : NextHopKey *nh_key =
216 0 : static_cast<NextHopKey *>(key_ptr.release());
217 0 : std::unique_ptr<const NextHopKey> nh_key_ptr(nh_key);
218 0 : ComponentNHKeyPtr component_nh_key(new ComponentNHKey(MplsTable::kInvalidLabel, // label
219 0 : std::move(nh_key_ptr)));
220 0 : comp_nh_list.push_back(component_nh_key);
221 0 : return;
222 0 : }
223 :
224 : // Case 2. NextHop is a composite of interfaces
225 : // Copy all interfaces from this composite
226 : // into the components list
227 0 : if (loc_path->nexthop()->GetType() == NextHop::COMPOSITE) {
228 0 : CompositeNH *loc_comp_nh = dynamic_cast<CompositeNH*>
229 0 : (loc_path->nexthop());
230 :
231 0 : DBEntryBase::KeyPtr key_ptr =
232 0 : loc_comp_nh->GetDBRequestKey();
233 : CompositeNHKey *nh_key =
234 0 : static_cast<CompositeNHKey *>(key_ptr.release());
235 0 : std::unique_ptr<const NextHopKey> nh_key_ptr(nh_key);
236 :
237 0 : if (nh_key == NULL){
238 0 : LOG(ERROR, "Error in VxlanRoutingManager::AddInterfaceComponentToList"
239 : << ", null nh key");
240 0 : assert(nh_key != NULL);
241 : }
242 :
243 : // Refresh on path_preference.sequence change
244 : const ComponentNHList& component_nh_list =
245 0 : loc_comp_nh->component_nh_list();
246 0 : for (ComponentNHList::const_iterator
247 0 : it_nh = component_nh_list.begin();
248 0 : it_nh != component_nh_list.end(); it_nh++) {
249 : // nullptr means deleted component, which
250 : // can be reused later
251 0 : std::unique_ptr<const NextHopKey> nh_key_ptr;
252 0 : ComponentNHKeyPtr component_nh_key;
253 0 : if (it_nh->get() == NULL) {
254 : // component_nh_key.reset(NULL);
255 : } else {
256 0 : DBEntryBase::KeyPtr key =
257 0 : it_nh->get()->nh()->GetDBRequestKey();
258 : NextHopKey *nh_key =
259 0 : static_cast<NextHopKey *>(key.release());
260 0 : nh_key_ptr.reset(nh_key);
261 0 : component_nh_key.reset(
262 0 : new ComponentNHKey(MplsTable::kInvalidLabel, std::move(nh_key_ptr)));
263 0 : }
264 0 : comp_nh_list.push_back(component_nh_key);
265 : }
266 0 : }
267 : } // AddInterfaceComponentToList func
268 :
269 : //
270 : // END-OF-FILE
271 : //
|