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