Line data Source code
1 : /*
2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3 : * Copyright Contributors to the OpenSDN project
4 : */
5 :
6 : #include <sys/types.h>
7 : #include <net/ethernet.h>
8 : #include <boost/uuid/uuid_io.hpp>
9 :
10 : #include "base/address_util.h"
11 : #include "base/logging.h"
12 : #include "db/db.h"
13 : #include "db/db_entry.h"
14 : #include "db/db_table.h"
15 : #include "ifmap/ifmap_node.h"
16 :
17 : #include <cfg/cfg_init.h>
18 : #include <cmn/agent.h>
19 : #include <init/agent_param.h>
20 : #include <oper/operdb_init.h>
21 : #include <oper/route_common.h>
22 : #include <oper/vm.h>
23 : #include <oper/vn.h>
24 : #include <oper/vrf.h>
25 : #include <oper/nexthop.h>
26 : #include <oper/mpls.h>
27 : #include <oper/mirror_table.h>
28 : #include <oper/interface_common.h>
29 : #include <oper/vrf_assign.h>
30 : #include <oper/vxlan.h>
31 :
32 : #include <vnc_cfg_types.h>
33 : #include <oper/agent_sandesh.h>
34 : #include <oper/sg.h>
35 : #include "sandesh/sandesh_trace.h"
36 : #include "sandesh/common/vns_types.h"
37 : #include "sandesh/common/vns_constants.h"
38 : #include <resource_manager/resource_manager.h>
39 : #include <resource_manager/resource_table.h>
40 : #include <resource_manager/mpls_index.h>
41 :
42 : using namespace std;
43 : using namespace boost::uuids;
44 :
45 : /////////////////////////////////////////////////////////////////////////////
46 : // Inet Interface Key and Data methods
47 : /////////////////////////////////////////////////////////////////////////////
48 10 : InetInterfaceKey::InetInterfaceKey(const std::string &name) :
49 20 : InterfaceKey(AgentKey::ADD_DEL_CHANGE, Interface::INET, nil_uuid(), name,
50 10 : false) {
51 10 : }
52 :
53 9 : Interface *InetInterfaceKey::AllocEntry(const InterfaceTable *table) const {
54 9 : return new InetInterface(name_);
55 : }
56 :
57 1 : Interface *InetInterfaceKey::AllocEntry(const InterfaceTable *table,
58 : const InterfaceData *data)const {
59 1 : const InetInterfaceData *vhost_data =
60 : static_cast<const InetInterfaceData *>(data);
61 :
62 1 : VrfKey key(data->vrf_name_);
63 1 : VrfEntry *vrf = static_cast<VrfEntry *>
64 1 : (table->agent()->vrf_table()->FindActiveEntry(&key));
65 1 : assert(vrf);
66 :
67 1 : Interface *xconnect = NULL;
68 1 : if (vhost_data->sub_type_ == InetInterface::VHOST) {
69 0 : PhysicalInterfaceKey key(vhost_data->xconnect_);
70 0 : xconnect = static_cast<Interface *>
71 0 : (table->agent()->interface_table()->FindActiveEntry(&key));
72 0 : assert(xconnect != NULL);
73 0 : }
74 :
75 1 : InetInterface *intf = new InetInterface(name_, vhost_data->sub_type_, vrf,
76 1 : vhost_data->ip_addr_,
77 1 : vhost_data->plen_, vhost_data->gw_,
78 1 : xconnect, vhost_data->vn_name_);
79 1 : return intf;
80 1 : }
81 :
82 2 : InterfaceKey *InetInterfaceKey::Clone() const {
83 2 : return new InetInterfaceKey(name_);
84 : }
85 :
86 1 : InetInterfaceData::InetInterfaceData(InetInterface::SubType sub_type,
87 : const std::string &vrf_name,
88 : const Ip4Address &addr, int plen,
89 : const Ip4Address &gw,
90 : const std::string &xconnect,
91 : const std::string vn_name,
92 1 : Interface::Transport transport) :
93 1 : InterfaceData(NULL, NULL, transport), sub_type_(sub_type), ip_addr_(addr),
94 1 : plen_(plen), gw_(gw), xconnect_(xconnect), vn_name_(vn_name) {
95 1 : InetInit(vrf_name);
96 1 : }
97 :
98 : /////////////////////////////////////////////////////////////////////////////
99 : // SIMPLE GATEWAY Utility functions
100 : /////////////////////////////////////////////////////////////////////////////
101 1 : void InetInterface::ActivateSimpleGateway() {
102 1 : InterfaceTable *table = static_cast<InterfaceTable *>(get_table());
103 1 : Agent *agent = table->agent();
104 :
105 : // Create InterfaceNH before MPLS is created
106 1 : InterfaceNH::CreateInetInterfaceNextHop(name(), vrf()->GetName(),
107 : agent->pkt_interface_mac());
108 :
109 : //There is no policy enabled nexthop created for VGW interface,
110 : //hence use interface nexthop without policy as flow key index
111 1 : InterfaceNHKey key(new InetInterfaceKey(name()),
112 : false, InterfaceNHFlags::INET4,
113 2 : agent->pkt_interface_mac());
114 : flow_key_nh_ = static_cast<const NextHop *>(
115 1 : agent->nexthop_table()->FindActiveEntry(&key));
116 1 : assert(flow_key_nh_);
117 1 : label_ = flow_key_nh_->mpls_label()->label();
118 1 : }
119 :
120 1 : void InetInterface::DeActivateSimpleGateway() {
121 : InetUnicastAgentRouteTable *uc_rt_table =
122 1 : (VrfTable::GetInstance()->GetInet4UnicastRouteTable(vrf()->GetName()));
123 :
124 1 : InterfaceTable *table = static_cast<InterfaceTable *>(get_table());
125 1 : Agent *agent = table->agent();
126 :
127 : // Delete routes
128 1 : Ip4Address addr = Address::GetIp4SubnetAddress(ip_addr_, plen_);
129 1 : uc_rt_table->DeleteReq(agent->local_vm_peer(), agent->fabric_vrf_name(),
130 1 : addr, plen_, NULL);
131 :
132 1 : uc_rt_table->DeleteReq(agent->local_vm_peer(),
133 1 : vrf()->GetName(), Ip4Address(0), 0, NULL);
134 :
135 : // Delete NH
136 1 : InterfaceNH::DeleteInetInterfaceNextHop(name(), agent->pkt_interface_mac());
137 :
138 : // Reset Label
139 1 : label_ = MplsTable::kInvalidLabel;
140 1 : flow_key_nh_ = NULL;
141 1 : }
142 :
143 : /////////////////////////////////////////////////////////////////////////////
144 : // VHOST / LL Utility functions
145 : /////////////////////////////////////////////////////////////////////////////
146 :
147 : // Add default route with given gateway
148 0 : static void AddDefaultRoute(Agent *agent, InetUnicastAgentRouteTable *table,
149 : const VrfEntry *vrf, const Interface *xconnect,
150 : const Ip4Address &gw, const string &vn_name) {
151 :
152 0 : if (xconnect) {
153 0 : const PhysicalInterface *physical_intf =
154 : static_cast<const PhysicalInterface *>(xconnect);
155 0 : if (physical_intf->no_arp() ||
156 0 : (physical_intf->encap_type() == PhysicalInterface::RAW_IP)) {
157 0 : table->AddInterfaceRouteReq(agent, agent->local_peer(),
158 0 : vrf->GetName(), Ip4Address(0), 0,
159 : xconnect, vn_name);
160 0 : return;
161 : }
162 : }
163 :
164 0 : VnListType vn_list;
165 0 : vn_list.insert(vn_name);
166 0 : table->AddGatewayRoute(agent->local_peer(),
167 0 : vrf->GetName(), Ip4Address(0), 0, AddressList(1, gw), vn_list,
168 0 : MplsTable::kInvalidLabel, SecurityGroupList(),
169 0 : TagList(), CommunityList(), true);
170 0 : return;
171 0 : }
172 :
173 0 : static void DeleteDefaultRoute(Agent *agent, InetUnicastAgentRouteTable *table,
174 : const VrfEntry *vrf, const Ip4Address &addr) {
175 0 : table->Delete(agent->local_peer(), vrf->GetName(), Ip4Address(0), 0);
176 0 : }
177 :
178 : // Following routes are added due o an inet interface
179 : // - Receive route for IP address assigned
180 : // - Receive route for the sub-net broadcast address
181 : // - Resolve route for the subnet address
182 0 : static void AddHostRoutes(Agent *agent, InetUnicastAgentRouteTable *table,
183 : const VrfEntry *vrf, const string &interface,
184 : const Interface *xconnect, const Ip4Address &addr,
185 : int plen, const string &vn_name) {
186 :
187 0 : InetInterfaceKey intf_key(interface);
188 0 : table->AddVHostRecvRoute(agent->local_peer(), vrf->GetName(), intf_key,
189 : addr, 32, vn_name, false, true);
190 :
191 0 : const PhysicalInterface *physical_intf =
192 : static_cast<const PhysicalInterface *>(xconnect);
193 0 : if (physical_intf) {
194 0 : if (physical_intf->no_arp())
195 0 : return;
196 0 : if (physical_intf->encap_type() != PhysicalInterface::ETHERNET)
197 0 : return;
198 : }
199 :
200 0 : table->AddVHostSubnetRecvRoute(agent->local_peer(), vrf->GetName(),
201 : intf_key,
202 0 : GetIp4SubnetBroadcastAddress(addr, plen),
203 : 32, vn_name, false);
204 0 : if (agent->params()->subnet_hosts_resolvable() == true) {
205 0 : InetInterfaceKey intf_key(interface);
206 0 : table->AddResolveRoute(agent->local_peer(), vrf->GetName(),
207 0 : Address::GetIp4SubnetAddress(addr, plen), plen,
208 : intf_key, MplsTable::kInvalidLabel, false, vn_name,
209 0 : SecurityGroupList(), TagList());
210 0 : }
211 :
212 0 : if ((agent->tsn_enabled() == true) &&
213 0 : (agent->forwarding_enabled() == false)) {
214 : InetUnicastAgentRouteTable *inet_table =
215 : static_cast<InetUnicastAgentRouteTable *>
216 0 : (agent->fabric_policy_vrf()->GetInet4UnicastRouteTable());
217 0 : VmInterfaceKey vmi_key(AgentKey::ADD_DEL_CHANGE, nil_uuid(),
218 0 : agent->params()->vhost_name());
219 0 : inet_table->AddVHostRecvRouteReq(agent->local_peer(),
220 : agent->fabric_policy_vrf_name(),
221 : vmi_key,
222 0 : agent->params()->vhost_addr(),
223 : 32,
224 : agent->fabric_vn_name(),
225 : false, true);
226 0 : }
227 0 : }
228 :
229 0 : static void DeleteHostRoutes(Agent *agent, InetUnicastAgentRouteTable *table,
230 : const VrfEntry *vrf, const Interface *xconnect,
231 : const Ip4Address &addr, int plen) {
232 0 : table->Delete(agent->local_peer(), vrf->GetName(), addr, 32);
233 0 : const PhysicalInterface *physical_intf =
234 : static_cast<const PhysicalInterface *>(xconnect);
235 0 : if (physical_intf && physical_intf->no_arp()) {
236 0 : return;
237 : }
238 :
239 0 : table->Delete(agent->local_peer(), vrf->GetName(),
240 0 : Address::GetIp4SubnetAddress(addr, plen), plen);
241 0 : table->Delete(agent->local_peer(), vrf->GetName(),
242 0 : GetIp4SubnetBroadcastAddress(addr, plen), 32);
243 : }
244 :
245 0 : void InetInterface::AddHostMulticastRoutes() {
246 0 : VrfTable *vrf_table = static_cast<VrfTable *>(vrf()->get_table());
247 : InetUnicastAgentRouteTable *uc_rt_table =
248 0 : (vrf_table->GetInet4UnicastRouteTable(vrf()->GetName()));
249 0 : boost::system::error_code ec;
250 0 : InetInterfaceKey intf_key(name());
251 : // Add v4 route for covering multicast
252 : uc_rt_table->
253 0 : AddVHostRecvRoute(uc_rt_table->agent()->local_peer(),
254 : vrf()->GetName(),
255 : intf_key,
256 0 : Ip4Address::from_string(IPV4_MULTICAST_BASE_ADDRESS,
257 : ec),
258 : MULTICAST_BASE_ADDRESS_PLEN,
259 0 : vn_name_,
260 : false, true);
261 : // Add v6 route for covering multicast
262 : uc_rt_table->
263 0 : AddVHostRecvRoute(uc_rt_table->agent()->local_peer(),
264 : vrf()->GetName(),
265 : intf_key,
266 0 : Ip6Address::from_string(IPV6_MULTICAST_BASE_ADDRESS,
267 : ec),
268 : MULTICAST_BASE_ADDRESS_PLEN,
269 0 : vn_name_,
270 : false, true);
271 0 : }
272 :
273 0 : void InetInterface::DelHostMulticastRoutes() {
274 0 : VrfTable *vrf_table = static_cast<VrfTable *>(vrf()->get_table());
275 : InetUnicastAgentRouteTable *uc_rt_table =
276 0 : (vrf_table->GetInet4UnicastRouteTable(vrf()->GetName()));
277 0 : boost::system::error_code ec;
278 : // Del v4 route for covering multicast
279 0 : uc_rt_table->Delete(uc_rt_table->agent()->local_peer(),
280 : vrf()->GetName(),
281 0 : Ip4Address::from_string(IPV4_MULTICAST_BASE_ADDRESS,
282 : ec),
283 : MULTICAST_BASE_ADDRESS_PLEN);
284 : // Del v6 route for covering multicast
285 0 : uc_rt_table->Delete(uc_rt_table->agent()->local_peer(),
286 : vrf()->GetName(),
287 0 : Ip6Address::from_string(IPV6_MULTICAST_BASE_ADDRESS,
288 : ec),
289 : MULTICAST_BASE_ADDRESS_PLEN);
290 0 : }
291 :
292 : // Things to do to activate VHOST/LL interface
293 : // 1. Create the receive next-hops for interface (with policy and witout policy)
294 : // 2. Add routes needed to manage the IP address on interface
295 : // 3. Add default route for the gateway
296 : // 4. Add broadcast route in multicast route table
297 0 : void InetInterface::ActivateHostInterface() {
298 0 : InterfaceTable *table = static_cast<InterfaceTable *>(get_table());
299 0 : Agent *agent = table->agent();
300 :
301 : // Create receive nexthops
302 0 : ReceiveNH::Create(agent->nexthop_table(), this, false);
303 :
304 0 : VrfTable *vrf_table = static_cast<VrfTable *>(vrf()->get_table());
305 : InetUnicastAgentRouteTable *uc_rt_table =
306 0 : (vrf_table->GetInet4UnicastRouteTable(vrf()->GetName()));
307 0 : if (ip_addr_.to_ulong()) {
308 0 : AddHostRoutes(agent, uc_rt_table, vrf(), name(), xconnect_.get(),
309 0 : ip_addr_, plen_, vn_name_);
310 : }
311 0 : AddHostMulticastRoutes();
312 :
313 0 : if (gw_.to_ulong()) {
314 0 : AddDefaultRoute(agent, uc_rt_table, vrf(), xconnect_.get(), gw_,
315 0 : vn_name_);
316 : }
317 :
318 0 : ReceiveNHKey nh_key(new InetInterfaceKey(name()), false);
319 : flow_key_nh_ = static_cast<const NextHop *>(
320 0 : agent->nexthop_table()->FindActiveEntry(&nh_key));
321 0 : }
322 :
323 0 : void InetInterface::DeActivateHostInterface() {
324 0 : ipv4_active_ = false;
325 :
326 0 : Agent *agent = static_cast<InterfaceTable *>(get_table())->agent();
327 0 : VrfTable *vrf_table = static_cast<VrfTable *>(vrf()->get_table());
328 : InetUnicastAgentRouteTable *uc_rt_table =
329 0 : (vrf_table->GetInet4UnicastRouteTable(vrf()->GetName()));
330 0 : if (ip_addr_.to_ulong()) {
331 0 : DeleteHostRoutes(agent, uc_rt_table, vrf(), xconnect_.get(), ip_addr_,
332 : plen_);
333 : }
334 0 : DelHostMulticastRoutes();
335 :
336 0 : if (gw_.to_ulong()) {
337 0 : DeleteDefaultRoute(agent, uc_rt_table, vrf(), gw_);
338 : }
339 :
340 : // Delete receive nexthops
341 0 : ReceiveNH::Delete(agent->nexthop_table(), this, false);
342 0 : flow_key_nh_ = NULL;
343 0 : }
344 :
345 : /////////////////////////////////////////////////////////////////////////////
346 : // Inet Interface methods
347 : /////////////////////////////////////////////////////////////////////////////
348 9 : InetInterface::InetInterface(const std::string &name) :
349 9 : Interface(Interface::INET, nil_uuid(), name, NULL, true, nil_uuid()),
350 9 : sub_type_(VHOST), ip_addr_(0), plen_(0), gw_(0), xconnect_(NULL),
351 27 : vn_name_("") {
352 9 : ipv4_active_ = false;
353 9 : l2_active_ = false;
354 9 : }
355 :
356 1 : InetInterface::InetInterface(const std::string &name, SubType sub_type,
357 : VrfEntry *vrf, const Ip4Address &ip_addr, int plen,
358 : const Ip4Address &gw, Interface *xconnect,
359 1 : const std::string &vn_name) :
360 1 : Interface(Interface::INET, nil_uuid(), name, vrf, true, nil_uuid()),
361 1 : sub_type_(sub_type),
362 1 : ip_addr_(ip_addr),
363 1 : plen_(plen),
364 1 : gw_(gw),
365 1 : xconnect_(xconnect),
366 3 : vn_name_(vn_name) {
367 1 : ipv4_active_ = false;
368 1 : l2_active_ = false;
369 1 : }
370 :
371 18 : bool InetInterface::CmpInterface(const DBEntry &rhs) const {
372 18 : const InetInterface &intf = static_cast<const InetInterface &>(rhs);
373 18 : return name() < intf.name();
374 : }
375 :
376 1 : DBEntryBase::KeyPtr InetInterface::GetDBRequestKey() const {
377 1 : InterfaceKey *key = new InetInterfaceKey(name());
378 1 : return DBEntryBase::KeyPtr(key);
379 : }
380 :
381 1 : void InetInterface::Activate() {
382 1 : ipv4_active_ = true;
383 1 : if (sub_type_ == SIMPLE_GATEWAY) {
384 1 : InetInterface::ActivateSimpleGateway();
385 : } else {
386 0 : InetInterface::ActivateHostInterface();
387 : }
388 :
389 1 : return;
390 : }
391 :
392 1 : void InetInterface::DeActivate() {
393 1 : ipv4_active_ = false;
394 :
395 1 : if (sub_type_ == SIMPLE_GATEWAY) {
396 1 : InetInterface::DeActivateSimpleGateway();
397 : } else {
398 0 : InetInterface::DeActivateHostInterface();
399 : }
400 1 : }
401 :
402 1 : bool InetInterface::Delete(const DBRequest *req) {
403 1 : DeActivate();
404 1 : return true;
405 : }
406 :
407 : // Interface Activate cannot be done in AllocEntry. It must be done in PostAdd
408 : // Activating an interface results in adding Interface Nexthops. Creating of
409 : // Interface NH from AllocEntry will fail since the interface is not yet added
410 : // in DB Table PartitionInterface. So, Activate an interface in PostAdd
411 1 : void InetInterface::PostAdd() {
412 1 : Activate();
413 1 : }
414 :
415 0 : bool InetInterface::OnChange(InetInterfaceData *data) {
416 0 : bool ret = false;
417 :
418 : // A Delete followed by Add will result in OnChange callback. Interface is
419 : // Deactivated on delete. Activate it again to create Interface NH etc...
420 0 : if (ipv4_active_ != true) {
421 0 : Activate();
422 0 : ret = true;
423 : }
424 :
425 0 : if (sub_type_ == SIMPLE_GATEWAY) {
426 0 : return ret;
427 : }
428 :
429 0 : InterfaceTable *table = static_cast<InterfaceTable *>(get_table());
430 0 : Agent *agent = table->agent();
431 :
432 0 : VrfTable *vrf_table = static_cast<VrfTable *>(vrf()->get_table());
433 : InetUnicastAgentRouteTable *uc_rt_table =
434 0 : (vrf_table->GetInet4UnicastRouteTable(vrf()->GetName()));
435 :
436 0 : if (ip_addr_ != data->ip_addr_ || plen_ != data->plen_) {
437 : // Delete routes based on old ip-addr and prefix
438 0 : if (ip_addr_.to_ulong()) {
439 0 : DeleteHostRoutes(agent, uc_rt_table, vrf(), xconnect_.get(),
440 0 : ip_addr_, plen_);
441 : }
442 :
443 0 : ip_addr_ = data->ip_addr_;
444 0 : plen_ = data->plen_;
445 0 : vn_name_ = data->vn_name_;
446 : // Add routes for new ip-address and prefix
447 0 : if (data->ip_addr_.to_ulong()) {
448 0 : AddHostRoutes(agent, uc_rt_table, vrf(), name(), xconnect_.get(),
449 0 : ip_addr_, plen_, vn_name_);
450 : }
451 0 : ret = true;
452 0 : } else if (vn_name_ != data->vn_name_) {
453 : // Change in vn_name, update route with new VN Name
454 0 : vn_name_ = data->vn_name_;
455 0 : AddHostRoutes(agent, uc_rt_table, vrf(), name(), xconnect_.get(),
456 0 : ip_addr_, plen_, vn_name_);
457 0 : ret = true;
458 : }
459 :
460 0 : if (gw_ != data->gw_) {
461 : // Delete routes based on old gateway
462 0 : if (gw_.to_ulong()) {
463 0 : DeleteDefaultRoute(agent, uc_rt_table, vrf(), gw_);
464 : }
465 :
466 0 : gw_ = data->gw_;
467 : // Add route for new gateway
468 0 : if (gw_.to_ulong()) {
469 0 : AddDefaultRoute(agent, uc_rt_table, vrf(), xconnect_.get(), gw_,
470 0 : vn_name_);
471 : }
472 :
473 0 : ret = true;
474 : }
475 :
476 0 : if (transport_ != data->transport_) {
477 0 : transport_ = data->transport_;
478 : }
479 0 : return ret;
480 : }
481 :
482 : // Helper to Inet Interface
483 1 : void InetInterface::CreateReq(InterfaceTable *table, const std::string &ifname,
484 : SubType sub_type, const std::string &vrf_name,
485 : const Ip4Address &addr, int plen,
486 : const Ip4Address &gw,
487 : const std::string &xconnect,
488 : const std::string &vn_name,
489 : Interface::Transport transport) {
490 1 : DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
491 1 : req.key.reset(new InetInterfaceKey(ifname));
492 2 : req.data.reset(new InetInterfaceData(sub_type, vrf_name, Ip4Address(addr),
493 1 : plen, Ip4Address(gw), xconnect,
494 1 : vn_name, transport));
495 1 : table->Enqueue(&req);
496 1 : }
497 :
498 : // Helper to Inet Interface
499 0 : void InetInterface::Create(InterfaceTable *table, const std::string &ifname,
500 : SubType sub_type, const std::string &vrf_name,
501 : const Ip4Address &addr, int plen,
502 : const Ip4Address &gw,
503 : const std::string &xconnect,
504 : const std::string &vn_name,
505 : Interface::Transport transport) {
506 0 : DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
507 0 : req.key.reset(new InetInterfaceKey(ifname));
508 0 : req.data.reset(new InetInterfaceData(sub_type, vrf_name, Ip4Address(addr),
509 0 : plen, Ip4Address(gw), xconnect,
510 0 : vn_name, transport));
511 0 : table->Process(req);
512 0 : }
513 :
514 : // Helper to delete Inet Interface
515 1 : void InetInterface::DeleteReq(InterfaceTable *table, const string &ifname) {
516 1 : DBRequest req(DBRequest::DB_ENTRY_DELETE);
517 1 : req.key.reset(new InetInterfaceKey(ifname));
518 1 : req.data.reset(NULL);
519 1 : table->Enqueue(&req);
520 1 : }
521 :
522 0 : void InetInterface::Delete(InterfaceTable *table, const string &ifname) {
523 0 : DBRequest req(DBRequest::DB_ENTRY_DELETE);
524 0 : req.key.reset(new InetInterfaceKey(ifname));
525 0 : req.data.reset(NULL);
526 0 : table->Process(req);
527 0 : }
|