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