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 "sandesh/sandesh_types.h"
7 : #include "sandesh/sandesh.h"
8 : #include "base/address_util.h"
9 : #include "init/agent_init.h"
10 : #include "oper/nexthop.h"
11 : #include "oper/tunnel_nh.h"
12 : #include "oper/mirror_table.h"
13 : #include "oper/route_common.h"
14 : #include "pkt/pkt_init.h"
15 : #include "services/arp_proto.h"
16 : #include "services/services_sandesh.h"
17 : #include "services_init.h"
18 : #include "mac_learning/mac_learning_proto.h"
19 :
20 2 : ArpProto::ArpProto(Agent *agent, boost::asio::io_context &io,
21 2 : bool run_with_vrouter) :
22 : Proto(agent, "Agent::Services", PktHandler::ARP, io),
23 2 : run_with_vrouter_(run_with_vrouter), ip_fabric_interface_index_(-1),
24 4 : ip_fabric_interface_(NULL), max_retries_(kMaxRetries),
25 2 : retry_timeout_(kRetryTimeout), aging_timeout_(kAgingTimeout) {
26 : // limit the number of entries in the workqueue
27 2 : work_queue_.SetSize(agent->params()->services_queue_limit());
28 2 : work_queue_.SetBounded(true);
29 :
30 2 : vrf_table_listener_id_ = agent->vrf_table()->Register(
31 : boost::bind(&ArpProto::VrfNotify, this, _1, _2));
32 2 : interface_table_listener_id_ = agent->interface_table()->Register(
33 : boost::bind(&ArpProto::InterfaceNotify,
34 : this, _2));
35 2 : nexthop_table_listener_id_ = agent->nexthop_table()->Register(
36 : boost::bind(&ArpProto::NextHopNotify, this, _2));
37 2 : }
38 :
39 4 : ArpProto::~ArpProto() {
40 4 : }
41 :
42 2 : void ArpProto::Shutdown() {
43 : // we may have arp entries in arp cache without ArpNH, empty them
44 2 : for (ArpIterator it = arp_cache_.begin(); it != arp_cache_.end(); ) {
45 0 : it = DeleteArpEntry(it);
46 : }
47 :
48 2 : for (GratuitousArpIterator it = gratuitous_arp_cache_.begin();
49 2 : it != gratuitous_arp_cache_.end(); it++) {
50 0 : for (ArpEntrySet::iterator sit = it->second.begin();
51 0 : sit != it->second.end();) {
52 0 : ArpEntry *entry = *sit;
53 0 : it->second.erase(sit++);
54 0 : delete entry;
55 : }
56 : }
57 2 : gratuitous_arp_cache_.clear();
58 2 : agent_->vrf_table()->Unregister(vrf_table_listener_id_);
59 2 : agent_->interface_table()->Unregister(interface_table_listener_id_);
60 2 : agent_->nexthop_table()->Unregister(nexthop_table_listener_id_);
61 2 : }
62 :
63 736 : ProtoHandler *ArpProto::AllocProtoHandler(boost::shared_ptr<PktInfo> info,
64 : boost::asio::io_context &io) {
65 736 : return new ArpHandler(agent(), info, io);
66 : }
67 :
68 683 : void ArpProto::VrfNotify(DBTablePartBase *part, DBEntryBase *entry) {
69 683 : VrfEntry *vrf = static_cast<VrfEntry *>(entry);
70 : ArpVrfState *state;
71 :
72 683 : state = static_cast<ArpVrfState *>(entry->GetState(part->parent(),
73 : vrf_table_listener_id_));
74 683 : if (entry->IsDeleted()) {
75 541 : if (state) {
76 223 : for (ArpProto::ArpIterator it = arp_cache_.begin();
77 434 : it != arp_cache_.end();) {
78 211 : ArpEntry *arp_entry = it->second;
79 211 : if (arp_entry->key().vrf == vrf && arp_entry->DeleteArpRoute()) {
80 0 : it = DeleteArpEntry(it);
81 : } else
82 211 : it++;
83 : }
84 223 : for (GratuitousArpIterator it = gratuitous_arp_cache_.begin();
85 2706 : it != gratuitous_arp_cache_.end(); ) {
86 2483 : ArpKey key = it->first;
87 2483 : if (key.vrf == vrf) {
88 138 : for (ArpEntrySet::iterator sit = it->second.begin();
89 259 : sit != it->second.end();) {
90 121 : ArpEntry *entry = *sit;
91 121 : it->second.erase(sit++);
92 121 : delete entry;
93 : }
94 138 : gratuitous_arp_cache_.erase(it++);
95 : }else {
96 2345 : it++;
97 : }
98 : }
99 223 : state->Delete();
100 : }
101 541 : return;
102 : }
103 :
104 142 : if (!state){
105 74 : state = new ArpVrfState(agent_, this, vrf,
106 74 : vrf->GetInet4UnicastRouteTable(),
107 74 : vrf->GetEvpnRouteTable());
108 74 : state->route_table_listener_id = vrf->
109 74 : GetInet4UnicastRouteTable()->
110 74 : Register(boost::bind(&ArpVrfState::RouteUpdate, state, _1, _2));
111 74 : state->evpn_route_table_listener_id = vrf->GetEvpnRouteTable()->
112 74 : Register(boost::bind(&ArpVrfState::EvpnRouteUpdate, state, _1, _2));
113 74 : entry->SetState(part->parent(), vrf_table_listener_id_, state);
114 : }
115 : }
116 :
117 782 : void intrusive_ptr_add_ref(ArpPathPreferenceState *aps) {
118 782 : aps->refcount_++;
119 782 : }
120 :
121 782 : void intrusive_ptr_release(ArpPathPreferenceState *aps) {
122 782 : ArpVrfState *state = aps->vrf_state();
123 782 : int prev = aps->refcount_.fetch_sub(1);
124 782 : if (prev == 1) {
125 559 : state->Erase(aps->ip(), aps->plen());
126 559 : delete aps;
127 : }
128 782 : }
129 :
130 559 : ArpPathPreferenceState::ArpPathPreferenceState(ArpVrfState *state,
131 : uint32_t vrf_id,
132 : const IpAddress &ip,
133 559 : uint8_t plen):
134 559 : vrf_state_(state), arp_req_timer_(NULL), vrf_id_(vrf_id),
135 559 : vm_ip_(ip), plen_(plen) {
136 559 : refcount_ = 0;
137 559 : }
138 :
139 559 : ArpPathPreferenceState::~ArpPathPreferenceState() {
140 559 : if (arp_req_timer_) {
141 126 : arp_req_timer_->Cancel();
142 126 : TimerManager::DeleteTimer(arp_req_timer_);
143 : }
144 559 : assert(refcount_ == 0);
145 559 : }
146 :
147 1179 : void ArpPathPreferenceState::StartTimer() {
148 1179 : if (arp_req_timer_ == NULL) {
149 252 : arp_req_timer_ = TimerManager::CreateTimer(
150 126 : *(vrf_state_->agent->event_manager()->io_service()),
151 : "Arp Entry timer for VM",
152 : TaskScheduler::GetInstance()->
153 : GetTaskId("Agent::Services"), PktHandler::ARP);
154 : }
155 1179 : arp_req_timer_->Start(kTimeout,
156 : boost::bind(&ArpPathPreferenceState::SendArpRequest,
157 : this));
158 1179 : }
159 :
160 2362 : bool ArpPathPreferenceState::SendArpRequest(WaitForTrafficIntfMap
161 : &wait_for_traffic_map,
162 : ArpTransmittedIntfMap
163 : &arp_transmitted_map) {
164 2362 : bool ret = false;
165 2362 : boost::shared_ptr<PktInfo> pkt(new PktInfo(vrf_state_->agent,
166 : ARP_TX_BUFF_LEN,
167 2362 : PktHandler::ARP, 0));
168 2362 : ArpHandler arp_handler(vrf_state_->agent, pkt,
169 2362 : *(vrf_state_->agent->event_manager()->io_service()));
170 :
171 2362 : WaitForTrafficIntfMap::iterator it = wait_for_traffic_map.begin();
172 5230 : for (;it != wait_for_traffic_map.end(); it++) {
173 : const VmInterface *vm_intf = static_cast<const VmInterface *>(
174 2868 : vrf_state_->agent->interface_table()->FindInterface(it->first));
175 2868 : if (!vm_intf) {
176 1168 : continue;
177 : }
178 :
179 2844 : InterfaceArpPathPreferenceInfo &data = it->second;
180 2844 : bool inserted = arp_transmitted_map.insert(it->first).second;
181 2844 : ++data.arp_retry_count;
182 2844 : if (inserted == false) {
183 : //ARP request already sent due to IP route
184 1144 : continue;
185 : }
186 1700 : if ((plen_ != 32) && (!data.prev_responded_ip.is_unspecified())) {
187 0 : if ((data.arp_send_count >= 1) && (data.arp_reply_count == 0)) {
188 0 : ++data.arp_failure_count;
189 : }
190 0 : if (data.arp_failure_count >= ArpProto::kMaxFailures) {
191 0 : data.prev_responded_ip = Ip4Address(0);
192 0 : data.arp_failure_count = 0;
193 0 : data.arp_reply_count = 0;
194 0 : data.arp_send_count = 0;
195 : }
196 : }
197 1700 : ++data.arp_send_count;
198 :
199 : // Post message to delete MIL entry.
200 1700 : MacAddress mil_mac = vrf_state_->agent->mac_learning_proto()->
201 : GetMacIpLearningTable()->GetPairedMacAddress(
202 1700 : vm_intf->vrf_id(), ip());
203 1700 : if (mil_mac != MacAddress()) {
204 0 : ++data.arp_try_count;
205 0 : if (data.arp_try_count == kArpTryCount) {
206 0 : IpAddress ip = vm_ip_;
207 0 : MacAddress mac = mil_mac;
208 0 : vrf_state_->agent->mac_learning_proto()->
209 0 : GetMacIpLearningTable()->MacIpEntryUnreachable(
210 : vm_intf->vrf_id(), ip, mac);
211 0 : return true;
212 : }
213 : }
214 :
215 1700 : MacAddress smac = vm_intf->GetVifMac(vrf_state_->agent);
216 1700 : arp_handler.SendArpRequestByPlen(vm_intf, smac, this,
217 1700 : data.prev_responded_ip);
218 :
219 : // reduce the frequency of ARP requests after some tries
220 1700 : if (data.arp_send_count >= kMaxRetry) {
221 0 : if ((mac() != MacAddress()) && (mac() != vm_intf->vm_mac())) {
222 0 : arp_req_timer_->Reschedule(5000);
223 0 : } else if (vm_intf->vmi_type() != VmInterface::REMOTE_VM) {
224 : // change frequency only if not in gateway mode with remote VMIs
225 0 : arp_req_timer_->Reschedule(kTimeout * 5);
226 : }
227 : }
228 :
229 1700 : ret = true;
230 : }
231 2362 : return ret;
232 2362 : }
233 :
234 1181 : bool ArpPathPreferenceState::SendArpRequest() {
235 1194 : if (l3_wait_for_traffic_map_.size() == 0 &&
236 13 : evpn_wait_for_traffic_map_.size() == 0) {
237 0 : return false;
238 : }
239 :
240 1181 : bool ret = false;
241 1181 : ArpTransmittedIntfMap arp_transmitted_map;
242 1181 : if (SendArpRequest(l3_wait_for_traffic_map_, arp_transmitted_map)) {
243 1168 : ret = true;
244 : }
245 :
246 1181 : if (SendArpRequest(evpn_wait_for_traffic_map_, arp_transmitted_map)) {
247 16 : ret = true;
248 : }
249 :
250 1181 : return ret;
251 1181 : }
252 :
253 : //Send ARP request on interface in Active-BackUp mode
254 : //So that preference of route can be incremented if the VM replies to ARP
255 1901 : void ArpPathPreferenceState::SendArpRequestForAllIntf(const
256 : AgentRoute *route) {
257 1901 : WaitForTrafficIntfMap new_wait_for_traffic_map;
258 1901 : WaitForTrafficIntfMap wait_for_traffic_map = evpn_wait_for_traffic_map_;
259 1901 : if (dynamic_cast<const InetUnicastRouteEntry *>(route)) {
260 1218 : wait_for_traffic_map = l3_wait_for_traffic_map_;
261 : }
262 :
263 5796 : for (Route::PathList::const_iterator it = route->GetPathList().begin();
264 11592 : it != route->GetPathList().end(); it++) {
265 3895 : const AgentPath *path = static_cast<const AgentPath *>(it.operator->());
266 7790 : if (path->peer() &&
267 3895 : path->peer()->GetType() == Peer::LOCAL_VM_PORT_PEER) {
268 2159 : const NextHop *nh = path->ComputeNextHop(vrf_state_->agent);
269 2159 : if (nh->GetType() != NextHop::INTERFACE) {
270 683 : continue;
271 : }
272 1903 : if (path->is_health_check_service()) {
273 : // skip sending ARP request for Health Check Service IP
274 0 : continue;
275 : }
276 :
277 1903 : const InterfaceNH *intf_nh =
278 : static_cast<const InterfaceNH *>(nh);
279 : const Interface *intf =
280 1903 : static_cast<const Interface *>(intf_nh->GetInterface());
281 1903 : if (intf->type() != Interface::VM_INTERFACE) {
282 : //Ignore non vm interface nexthop
283 0 : continue;
284 : }
285 1903 : if (path->subnet_service_ip().is_v4() == false) {
286 0 : continue;
287 : }
288 1903 : if (path->path_preference().IsDependentRt() == true) {
289 427 : continue;
290 : }
291 1476 : uint32_t intf_id = intf->id();
292 : WaitForTrafficIntfMap::const_iterator wait_for_traffic_it =
293 1476 : wait_for_traffic_map.find(intf_id);
294 1476 : if (wait_for_traffic_it == wait_for_traffic_map.end()) {
295 492 : InterfaceArpPathPreferenceInfo data;
296 492 : new_wait_for_traffic_map.insert(WaitForTrafficIntfPair(intf_id,
297 : data));
298 : } else {
299 984 : new_wait_for_traffic_map.insert(WaitForTrafficIntfPair(intf_id,
300 984 : wait_for_traffic_it->second));
301 : }
302 : }
303 : }
304 :
305 1901 : if (dynamic_cast<const InetUnicastRouteEntry *>(route)) {
306 1218 : l3_wait_for_traffic_map_ = new_wait_for_traffic_map;
307 : } else {
308 683 : evpn_wait_for_traffic_map_ = new_wait_for_traffic_map;
309 : }
310 1901 : if (new_wait_for_traffic_map.size() > 0) {
311 1179 : SendArpRequest();
312 1179 : StartTimer();
313 : }
314 1901 : }
315 :
316 909 : ArpDBState::ArpDBState(ArpVrfState *vrf_state, uint32_t vrf_id, IpAddress ip,
317 1818 : uint8_t plen) : vrf_state_(vrf_state),
318 909 : sg_list_(), tag_list_(), policy_(false), resolve_route_(false) {
319 909 : if (ip != Ip4Address(0)) {
320 782 : arp_path_preference_state_.reset(vrf_state->Locate(ip, plen));
321 : }
322 909 : }
323 :
324 1818 : ArpDBState::~ArpDBState() {
325 1818 : }
326 :
327 1434 : void ArpDBState::UpdateMac(const InterfaceNH *nh) {
328 :
329 1434 : if (nh && arp_path_preference_state_.get()) {
330 827 : arp_path_preference_state_.get()->set_mac(nh->GetDMac());
331 : }
332 :
333 :
334 1434 : return;
335 : }
336 :
337 0 : void ArpDBState::UpdateArpRoutes(const InetUnicastRouteEntry *rt) {
338 0 : int plen = rt->prefix_length();
339 0 : uint32_t start_ip = rt->prefix_address().to_v4().to_ulong();
340 0 : ArpKey start_key(start_ip, rt->vrf());
341 :
342 : ArpProto::ArpIterator start_iter =
343 0 : vrf_state_->arp_proto->FindUpperBoundArpEntry(start_key);
344 :
345 :
346 0 : while (start_iter != vrf_state_->arp_proto->arp_cache().end() &&
347 0 : start_iter->first.vrf == rt->vrf() &&
348 0 : IsIp4SubnetMember(Ip4Address(start_iter->first.ip),
349 0 : rt->prefix_address().to_v4(), plen)) {
350 0 : start_iter->second->Resync(policy_, vn_list_, sg_list_, tag_list_);
351 0 : start_iter++;
352 : }
353 0 : }
354 :
355 571 : void ArpDBState::Delete(const InetUnicastRouteEntry *rt) {
356 571 : int plen = rt->prefix_length();
357 571 : uint32_t start_ip = rt->prefix_address().to_v4().to_ulong();
358 :
359 571 : ArpKey start_key(start_ip, rt->vrf());
360 :
361 : ArpProto::ArpIterator start_iter =
362 571 : vrf_state_->arp_proto->FindUpperBoundArpEntry(start_key);
363 :
364 586 : while (start_iter != vrf_state_->arp_proto->arp_cache().end() &&
365 586 : start_iter->first.vrf == rt->vrf() &&
366 6 : IsIp4SubnetMember(Ip4Address(start_iter->first.ip),
367 579 : rt->prefix_address().to_v4(), plen)) {
368 2 : ArpProto::ArpIterator tmp = start_iter++;
369 2 : if (tmp->second->DeleteArpRoute()) {
370 0 : vrf_state_->arp_proto->DeleteArpEntry(tmp->second);
371 : }
372 : }
373 571 : }
374 :
375 2744 : void ArpDBState::Update(const AgentRoute *rt) {
376 2744 : if (arp_path_preference_state_) {
377 1901 : arp_path_preference_state_->SendArpRequestForAllIntf(rt);
378 : }
379 :
380 : const InetUnicastRouteEntry *ip_rt =
381 2744 : dynamic_cast<const InetUnicastRouteEntry *>(rt);
382 2744 : if (ip_rt == NULL) {
383 1509 : return;
384 : }
385 1235 : const NextHop *anh =ip_rt->GetActiveNextHop();
386 1235 : if (anh == NULL) {
387 0 : return;
388 : }
389 :
390 1235 : if (anh->GetType() == NextHop::RESOLVE) {
391 0 : resolve_route_ = true;
392 : }
393 :
394 1235 : bool policy = anh->PolicyEnabled();
395 1235 : const SecurityGroupList sg = ip_rt->GetActivePath()->sg_list();
396 1235 : const TagList tag = ip_rt->GetActivePath()->tag_list();
397 :
398 :
399 2215 : if (policy_ != policy || sg != sg_list_ || tag != tag_list_ ||
400 980 : vn_list_ != ip_rt->GetActivePath()->dest_vn_list()) {
401 403 : policy_ = policy;
402 403 : sg_list_ = sg;
403 403 : tag_list_ = tag;
404 403 : vn_list_ = ip_rt->GetActivePath()->dest_vn_list();
405 403 : if (resolve_route_) {
406 0 : UpdateArpRoutes(ip_rt);
407 : }
408 : }
409 1235 : }
410 :
411 1847 : void ArpVrfState::EvpnRouteUpdate(DBTablePartBase *part, DBEntryBase *entry) {
412 1847 : EvpnRouteEntry *route = static_cast<EvpnRouteEntry *>(entry);
413 : /* Ignore route updates for Non-IPv4 addresses */
414 1847 : if (!route->prefix_address().is_v4()) {
415 0 : return;
416 : }
417 :
418 1847 : ArpDBState *state = static_cast<ArpDBState *>(entry->GetState(part->parent(),
419 : evpn_route_table_listener_id));
420 :
421 1847 : if (entry->IsDeleted() || deleted) {
422 338 : if (state) {
423 338 : entry->ClearState(part->parent(), evpn_route_table_listener_id);
424 338 : delete state;
425 : }
426 338 : return;
427 : }
428 :
429 1509 : if (state == NULL) {
430 338 : state = new ArpDBState(this, route->vrf_id(), route->prefix_address(),
431 338 : route->prefix_length());
432 338 : entry->SetState(part->parent(), evpn_route_table_listener_id, state);
433 : }
434 :
435 1509 : state->Update(route);
436 : }
437 :
438 2047 : void ArpVrfState::RouteUpdate(DBTablePartBase *part, DBEntryBase *entry) {
439 2047 : InetUnicastRouteEntry *route = static_cast<InetUnicastRouteEntry *>(entry);
440 :
441 : ArpDBState *state =
442 : static_cast<ArpDBState *>
443 2047 : (entry->GetState(part->parent(), route_table_listener_id));
444 :
445 2047 : const InterfaceNH *intf_nh = dynamic_cast<const InterfaceNH *>(
446 2047 : route->GetActiveNextHop());
447 2047 : const Interface *intf = (intf_nh) ?
448 827 : static_cast<const Interface *>(intf_nh->GetInterface()) : NULL;
449 :
450 2047 : ArpKey key(route->prefix_address().to_v4().to_ulong(), route->vrf());
451 2047 : ArpEntry *arpentry = arp_proto->GratuitousArpEntry(key, intf);
452 2047 : if (entry->IsDeleted() || deleted) {
453 613 : if (state) {
454 571 : arp_proto->DeleteGratuitousArpEntry(arpentry);
455 571 : entry->ClearState(part->parent(), route_table_listener_id);
456 571 : state->Delete(route);
457 571 : delete state;
458 : }
459 613 : return;
460 : }
461 :
462 1434 : if (!state) {
463 571 : state = new ArpDBState(this, route->vrf_id(), route->prefix_address(),
464 571 : route->prefix_length());
465 571 : entry->SetState(part->parent(), route_table_listener_id, state);
466 : }
467 :
468 1434 : state->UpdateMac(intf_nh);
469 :
470 1798 : if (route->vrf()->GetName() == agent->fabric_vrf_name() && intf_nh &&
471 1798 : route->GetActiveNextHop()->GetType() == NextHop::RECEIVE &&
472 1434 : arp_proto->agent()->router_id() == route->prefix_address().to_v4()) {
473 : //Send Grat ARP
474 0 : arp_proto->AddGratuitousArpEntry(key);
475 0 : arp_proto->SendArpIpc(ArpProto::ARP_SEND_GRATUITOUS,
476 0 : route->prefix_address().to_v4().to_ulong(), route->vrf(),
477 0 : arp_proto->ip_fabric_interface());
478 : } else {
479 1434 : if (intf_nh) {
480 1553 : if (intf->type() == Interface::VM_INTERFACE &&
481 726 : static_cast<const VmInterface*>(intf)->IsActive()) {
482 726 : ArpKey intf_key(route->prefix_address().to_v4().to_ulong(), route->vrf());
483 726 : arp_proto->AddGratuitousArpEntry(intf_key);
484 2178 : arp_proto->SendArpIpc(ArpProto::ARP_SEND_GRATUITOUS,
485 1452 : route->prefix_address().to_v4().to_ulong(), intf->vrf(), intf);
486 : }
487 : }
488 : }
489 :
490 : //Check if there is a local VM path, if yes send a
491 : //ARP request, to trigger route preference state machine
492 1434 : if (state && route->vrf()->GetName() != agent->fabric_vrf_name()) {
493 1235 : state->Update(route);
494 : }
495 : }
496 :
497 40 : bool ArpVrfState::DeleteRouteState(DBTablePartBase *part, DBEntryBase *entry) {
498 40 : RouteUpdate(part, entry);
499 40 : return true;
500 : }
501 :
502 0 : bool ArpVrfState::DeleteEvpnRouteState(DBTablePartBase *part,
503 : DBEntryBase *entry) {
504 0 : EvpnRouteUpdate(part, entry);
505 0 : return true;
506 : }
507 :
508 :
509 223 : void ArpVrfState::Delete() {
510 223 : if (managed_delete_walk_ref.get() == NULL)
511 95 : return;
512 :
513 128 : rt_table->WalkAgain(managed_delete_walk_ref);
514 128 : if (evpn_walk_ref_.get())
515 128 : evpn_rt_table->WalkAgain(evpn_walk_ref_);
516 128 : deleted = true;
517 : }
518 :
519 148 : void ArpVrfState::WalkDone(DBTableBase *partition, ArpVrfState *state) {
520 148 : if (partition == state->rt_table) {
521 74 : state->rt_table->ReleaseWalker(state->managed_delete_walk_ref);
522 74 : state->managed_delete_walk_ref = NULL;
523 74 : state->l3_walk_completed_ = true;
524 : } else {
525 : //Get rt table from partition
526 74 : state->evpn_rt_table->ReleaseWalker(state->evpn_walk_ref_);
527 74 : state->evpn_walk_ref_ = NULL;
528 74 : state->evpn_walk_completed_ = true;
529 : }
530 148 : if (state->PreWalkDone(partition)) {
531 74 : delete state;
532 : }
533 148 : }
534 :
535 148 : bool ArpVrfState::PreWalkDone(DBTableBase *partition) {
536 148 : if (arp_proto->ValidateAndClearVrfState(vrf, this) == false) {
537 74 : return false;
538 : }
539 :
540 74 : rt_table->Unregister(route_table_listener_id);
541 74 : table_delete_ref.Reset(NULL);
542 :
543 74 : evpn_rt_table->Unregister(evpn_route_table_listener_id);
544 74 : evpn_table_delete_ref.Reset(NULL);
545 74 : return true;
546 : }
547 :
548 782 : ArpPathPreferenceState* ArpVrfState::Locate(const IpAddress &ip, uint8_t plen) {
549 782 : ArpPathPreferenceStateKey key(ip, plen);
550 782 : ArpPathPreferenceState* ptr = NULL;
551 782 : ArpPathPreferenceStateMap::iterator it = arp_path_preference_map_.find(key);
552 782 : if (it == arp_path_preference_map_.end()) {
553 559 : ptr = new ArpPathPreferenceState(this, vrf->vrf_id(), ip, plen);
554 559 : arp_path_preference_map_.insert(ArpPathPreferenceStatePair(key, ptr));
555 : } else {
556 223 : ptr = it->second;
557 : }
558 782 : return ptr;
559 : }
560 :
561 559 : void ArpVrfState::Erase(const IpAddress &ip, uint8_t plen) {
562 559 : ArpPathPreferenceStateKey key(ip, plen);
563 559 : ArpPathPreferenceStateMap::iterator it = arp_path_preference_map_.find(key);
564 559 : if (it != arp_path_preference_map_.end()) {
565 559 : arp_path_preference_map_.erase(it);
566 : }
567 559 : }
568 :
569 :
570 0 : ArpPathPreferenceState* ArpVrfState::Get(const IpAddress ip, uint8_t plen) {
571 0 : ArpPathPreferenceStateKey key(ip, plen);
572 0 : ArpPathPreferenceStateMap::iterator it = arp_path_preference_map_.find(key);
573 0 : if (it != arp_path_preference_map_.end()) {
574 0 : return it->second;
575 : }
576 0 : return NULL;
577 : }
578 :
579 74 : ArpVrfState::ArpVrfState(Agent *agent_ptr, ArpProto *proto, VrfEntry *vrf_entry,
580 74 : AgentRouteTable *table, AgentRouteTable *evpn_table):
581 74 : agent(agent_ptr), arp_proto(proto), vrf(vrf_entry), rt_table(table),
582 74 : evpn_rt_table(evpn_table), route_table_listener_id(DBTableBase::kInvalidId),
583 74 : evpn_route_table_listener_id(DBTableBase::kInvalidId),
584 74 : table_delete_ref(this, table->deleter()),
585 74 : evpn_table_delete_ref(this, evpn_table->deleter()),
586 74 : deleted(false),
587 148 : l3_walk_completed_(false), evpn_walk_completed_(false) {
588 148 : evpn_walk_ref_ = evpn_rt_table->AllocWalker(
589 : boost::bind(&ArpVrfState::DeleteEvpnRouteState, this, _1, _2),
590 74 : boost::bind(&ArpVrfState::WalkDone, _2, this));
591 148 : managed_delete_walk_ref = rt_table->AllocWalker(
592 : boost::bind(&ArpVrfState::DeleteRouteState, this, _1, _2),
593 74 : boost::bind(&ArpVrfState::WalkDone, _2, this));
594 74 : }
595 :
596 148 : ArpVrfState::~ArpVrfState() {
597 74 : assert(arp_path_preference_map_.size() == 0);
598 148 : }
599 :
600 1421 : void ArpProto::InterfaceNotify(DBEntryBase *entry) {
601 1421 : Interface *intf = static_cast<Interface *>(entry);
602 : ArpInterfaceState *state = static_cast<ArpInterfaceState *>
603 1421 : (entry->GetState(entry->get_table_partition()->parent(),
604 : interface_table_listener_id_));
605 :
606 : /* On phy intf down, delete its associated arp route and set state to resolving */
607 1421 : if (agent_->is_l3mh() && intf->type() == Interface::PHYSICAL && intf->os_oper_state() == false) {
608 0 : InterfaceArpInfo &intf_entry = ArpMapIndexToEntry(intf->id());
609 0 : ArpKeySet::iterator key_it = intf_entry.arp_key_list.begin();
610 0 : while (key_it != intf_entry.arp_key_list.end()) {
611 0 : ArpKey key = *key_it;
612 0 : ++key_it;
613 0 : ArpEntry *arp_entry = FindArpEntry(key);
614 0 : if (arp_entry) {
615 0 : arp_entry->SetState(ArpEntry::RESOLVING);
616 0 : arp_entry->DeleteArpRoute();
617 : }
618 : }
619 0 : return;
620 : }
621 :
622 1421 : Interface *itf = static_cast<Interface *>(entry);
623 1421 : if (entry->IsDeleted()) {
624 176 : if (state) {
625 176 : intf->ClearState(intf->get_table_partition()->parent(),
626 : interface_table_listener_id_);
627 176 : delete state;
628 : }
629 :
630 176 : InterfaceArpMap::iterator it = interface_arp_map_.find(itf->id());
631 176 : if (it != interface_arp_map_.end()) {
632 4 : InterfaceArpInfo &intf_entry = it->second;
633 4 : ArpKeySet::iterator key_it = intf_entry.arp_key_list.begin();
634 6 : while (key_it != intf_entry.arp_key_list.end()) {
635 2 : ArpKey key = *key_it;
636 2 : ++key_it;
637 2 : ArpIterator arp_it = arp_cache_.find(key);
638 2 : if (arp_it != arp_cache_.end()) {
639 0 : ArpEntry *arp_entry = arp_it->second;
640 0 : if (arp_entry->DeleteArpRoute()) {
641 0 : DeleteArpEntry(arp_it);
642 : }
643 : }
644 : }
645 4 : intf_entry.arp_key_list.clear();
646 4 : interface_arp_map_.erase(it);
647 : }
648 :
649 176 : if (itf->type() == Interface::VM_INTERFACE) {
650 : ArpKey key(static_cast<VmInterface *>
651 169 : (itf)->primary_ip_addr().to_ulong(), itf->vrf());
652 169 : ArpEntry *arpentry = GratuitousArpEntry(key, itf);
653 169 : if (arpentry) {
654 0 : DeleteGratuitousArpEntry(arpentry);
655 : }
656 : }
657 :
658 179 : if (itf->type() == Interface::PHYSICAL &&
659 3 : itf->name() == agent_->fabric_interface_name()) {
660 2 : set_ip_fabric_interface(NULL);
661 2 : set_ip_fabric_interface_index(-1);
662 : }
663 : } else {
664 1245 : if (state == NULL) {
665 176 : state = new ArpInterfaceState(intf);
666 176 : intf->SetState(entry->get_table_partition()->parent(),
667 : interface_table_listener_id_, state);
668 : }
669 :
670 1249 : if (itf->type() == Interface::PHYSICAL &&
671 4 : itf->name() == agent_->fabric_interface_name()) {
672 2 : set_ip_fabric_interface(itf);
673 2 : set_ip_fabric_interface_index(itf->id());
674 2 : if (run_with_vrouter_) {
675 0 : set_ip_fabric_interface_mac(itf->mac());
676 : } else {
677 2 : set_ip_fabric_interface_mac(MacAddress());
678 : }
679 : }
680 :
681 1245 : if (itf->type() == Interface::VM_INTERFACE) {
682 1231 : const VmInterface *vm_intf =
683 : static_cast<const VmInterface *>(itf);
684 1231 : VrfEntry *forwarding_vrf = NULL;
685 1231 : if (vm_intf->vrf()) {
686 977 : forwarding_vrf = vm_intf->vrf()->forwarding_vrf();
687 : }
688 1231 : state->SetVrf(vm_intf->vrf(), forwarding_vrf);
689 : }
690 : }
691 : }
692 :
693 4 : ArpProto::InterfaceArpInfo& ArpProto::ArpMapIndexToEntry(uint32_t idx) {
694 4 : InterfaceArpMap::iterator it = interface_arp_map_.find(idx);
695 4 : if (it == interface_arp_map_.end()) {
696 2 : InterfaceArpInfo entry;
697 2 : std::pair<InterfaceArpMap::iterator, bool> ret;
698 2 : ret = interface_arp_map_.insert(InterfaceArpPair(idx, entry));
699 2 : return ret.first->second;
700 2 : } else {
701 2 : return it->second;
702 : }
703 : }
704 :
705 4 : void ArpProto::IncrementStatsArpRequest(uint32_t idx) {
706 4 : InterfaceArpInfo &entry = ArpMapIndexToEntry(idx);
707 4 : entry.stats.arp_req++;
708 4 : }
709 :
710 0 : void ArpProto::IncrementStatsArpReply(uint32_t idx) {
711 0 : InterfaceArpInfo &entry = ArpMapIndexToEntry(idx);
712 0 : entry.stats.arp_replies++;
713 0 : }
714 :
715 0 : void ArpProto::IncrementStatsResolved(uint32_t idx) {
716 0 : InterfaceArpInfo &entry = ArpMapIndexToEntry(idx);
717 0 : entry.stats.resolved++;
718 0 : }
719 :
720 0 : uint32_t ArpProto::ArpRequestStatsCounter(uint32_t idx) {
721 0 : InterfaceArpInfo &entry = ArpMapIndexToEntry(idx);
722 0 : return entry.stats.arp_req;
723 : }
724 :
725 0 : uint32_t ArpProto::ArpReplyStatsCounter(uint32_t idx) {
726 0 : InterfaceArpInfo &entry = ArpMapIndexToEntry(idx);
727 0 : return entry.stats.arp_replies;
728 : }
729 :
730 0 : uint32_t ArpProto::ArpResolvedStatsCounter(uint32_t idx) {
731 0 : InterfaceArpInfo &entry = ArpMapIndexToEntry(idx);
732 0 : return entry.stats.resolved;
733 : }
734 :
735 0 : void ArpProto::ClearInterfaceArpStats(uint32_t idx) {
736 0 : InterfaceArpInfo &entry = ArpMapIndexToEntry(idx);
737 0 : entry.stats.Reset();
738 0 : }
739 :
740 3457 : void ArpProto::NextHopNotify(DBEntryBase *entry) {
741 3457 : NextHop *nh = static_cast<NextHop *>(entry);
742 :
743 3457 : switch(nh->GetType()) {
744 6 : case NextHop::ARP: {
745 6 : ArpNH *arp_nh = (static_cast<ArpNH *>(nh));
746 6 : if (arp_nh->IsDeleted()) {
747 2 : SendArpIpc(ArpProto::ARP_DELETE, arp_nh->GetIp()->to_ulong(),
748 : arp_nh->GetVrf(), arp_nh->GetInterface());
749 4 : } else if (arp_nh->IsValid() == false && arp_nh->GetInterface()) {
750 4 : SendArpIpc(ArpProto::ARP_RESOLVE, arp_nh->GetIp()->to_ulong(),
751 : arp_nh->GetVrf(), arp_nh->GetInterface());
752 : }
753 6 : break;
754 : }
755 :
756 3451 : default:
757 3451 : break;
758 : }
759 3457 : }
760 :
761 4 : bool ArpProto::TimerExpiry(ArpKey &key, uint32_t timer_type,
762 : const Interface* itf) {
763 6 : if (arp_cache_.find(key) != arp_cache_.end() ||
764 6 : gratuitous_arp_cache_.find(key) != gratuitous_arp_cache_.end()) {
765 4 : if (itf) {
766 4 : SendArpIpc((ArpProto::ArpMsgType)timer_type, key, itf);
767 : }
768 : }
769 4 : return false;
770 : }
771 :
772 726 : void ArpProto::AddGratuitousArpEntry(ArpKey &key) {
773 726 : ArpEntrySet empty_set;
774 726 : gratuitous_arp_cache_.insert(GratuitousArpCachePair(key, empty_set));
775 726 : }
776 :
777 572 : void ArpProto::DeleteGratuitousArpEntry(ArpEntry *entry) {
778 572 : if (!entry)
779 571 : return ;
780 :
781 1 : ArpProto::GratuitousArpIterator iter = gratuitous_arp_cache_.find(entry->key());
782 1 : if (iter == gratuitous_arp_cache_.end()) {
783 0 : return;
784 : }
785 :
786 1 : iter->second.erase(entry);
787 1 : delete entry;
788 1 : if (iter->second.empty()) {
789 1 : gratuitous_arp_cache_.erase(iter);
790 : }
791 : }
792 :
793 : ArpEntry *
794 2218 : ArpProto::GratuitousArpEntry(const ArpKey &key, const Interface *intf) {
795 2218 : ArpProto::GratuitousArpIterator it = gratuitous_arp_cache_.find(key);
796 2218 : if (it == gratuitous_arp_cache_.end())
797 1327 : return NULL;
798 :
799 891 : for (ArpEntrySet::iterator sit = it->second.begin();
800 1025 : sit != it->second.end(); sit++) {
801 555 : ArpEntry *entry = *sit;
802 555 : if (entry->get_interface() == intf)
803 421 : return *sit;
804 : }
805 :
806 470 : return NULL;
807 : }
808 :
809 : ArpProto::GratuitousArpIterator
810 726 : ArpProto::GratuitousArpEntryIterator(const ArpKey &key, bool *key_valid) {
811 726 : ArpProto::GratuitousArpIterator it = gratuitous_arp_cache_.find(key);
812 726 : if (it == gratuitous_arp_cache_.end())
813 185 : return it;
814 541 : const VrfEntry *vrf = key.vrf;
815 541 : if (!vrf)
816 0 : return it;
817 : const ArpVrfState *state = static_cast<const ArpVrfState *>
818 541 : (vrf->GetState(vrf->get_table_partition()->parent(),
819 : vrf_table_listener_id_));
820 : // If VRF is delete marked, do not add ARP entries to cache
821 541 : if (state == NULL || state->deleted == true)
822 0 : return it;
823 541 : *key_valid = true;
824 541 : return it;
825 : }
826 :
827 732 : void ArpProto::SendArpIpc(ArpProto::ArpMsgType type, in_addr_t ip,
828 : const VrfEntry *vrf, InterfaceConstRef itf) {
829 732 : ArpIpc *ipc = new ArpIpc(type, ip, vrf, itf);
830 732 : agent_->pkt()->pkt_handler()->SendMessage(PktHandler::ARP, ipc);
831 732 : }
832 :
833 4 : void ArpProto::SendArpIpc(ArpProto::ArpMsgType type, ArpKey &key,
834 : InterfaceConstRef itf) {
835 4 : ArpIpc *ipc = new ArpIpc(type, key, itf);
836 4 : agent_->pkt()->pkt_handler()->SendMessage(PktHandler::ARP, ipc);
837 4 : }
838 :
839 2 : bool ArpProto::AddArpEntry(ArpEntry *entry) {
840 2 : const VrfEntry *vrf = entry->key().vrf;
841 : const ArpVrfState *state = static_cast<const ArpVrfState *>
842 2 : (vrf->GetState(vrf->get_table_partition()->parent(),
843 : vrf_table_listener_id_));
844 : // If VRF is delete marked, do not add ARP entries to cache
845 2 : if (state == NULL || state->deleted == true)
846 0 : return false;
847 :
848 2 : bool ret = arp_cache_.insert(ArpCachePair(entry->key(), entry)).second;
849 2 : uint32_t intf_id = entry->get_interface()->id();
850 2 : InterfaceArpMap::iterator it = interface_arp_map_.find(intf_id);
851 2 : if (it == interface_arp_map_.end()) {
852 2 : InterfaceArpInfo intf_entry;
853 2 : intf_entry.arp_key_list.insert(entry->key());
854 2 : interface_arp_map_.insert(InterfaceArpPair(intf_id, intf_entry));
855 2 : } else {
856 0 : InterfaceArpInfo &intf_entry = it->second;
857 0 : ArpKeySet::iterator key_it = intf_entry.arp_key_list.find(entry->key());
858 0 : if (key_it == intf_entry.arp_key_list.end()) {
859 0 : intf_entry.arp_key_list.insert(entry->key());
860 : }
861 : }
862 2 : return ret;
863 : }
864 :
865 2 : bool ArpProto::DeleteArpEntry(ArpEntry *entry) {
866 2 : if (!entry)
867 0 : return false;
868 :
869 2 : ArpProto::ArpIterator iter = arp_cache_.find(entry->key());
870 2 : if (iter == arp_cache_.end()) {
871 0 : return false;
872 : }
873 :
874 2 : DeleteArpEntry(iter);
875 2 : return true;
876 : }
877 :
878 : ArpProto::ArpIterator
879 2 : ArpProto::DeleteArpEntry(ArpProto::ArpIterator iter) {
880 2 : ArpEntry *entry = iter->second;
881 2 : arp_cache_.erase(iter++);
882 2 : delete entry;
883 2 : return iter;
884 : }
885 :
886 193 : ArpEntry *ArpProto::FindArpEntry(const ArpKey &key) {
887 193 : ArpIterator it = arp_cache_.find(key);
888 193 : if (it == arp_cache_.end())
889 187 : return NULL;
890 6 : return it->second;
891 : }
892 :
893 148 : bool ArpProto::ValidateAndClearVrfState(VrfEntry *vrf,
894 : const ArpVrfState *vrf_state) {
895 148 : if (!vrf_state->deleted) {
896 0 : ARP_TRACE(Trace, "ARP state not cleared - VRF is not delete marked",
897 : "", vrf->GetName(), "");
898 0 : return false;
899 : }
900 :
901 148 : if (vrf_state->l3_walk_completed() == false) {
902 0 : return false;
903 : }
904 :
905 148 : if (vrf_state->evpn_walk_completed() == false) {
906 74 : return false;
907 : }
908 :
909 148 : if (vrf_state->managed_delete_walk_ref.get() != NULL ||
910 74 : vrf_state->evpn_walk_ref_.get() != NULL) {
911 0 : ARP_TRACE(Trace, "ARP state not cleared - Route table walk not complete",
912 : "", vrf->GetName(), "");
913 0 : return false;
914 : }
915 :
916 : DBState *state = static_cast<DBState *>
917 74 : (vrf->GetState(vrf->get_table_partition()->parent(),
918 : vrf_table_listener_id_));
919 74 : if (state) {
920 74 : vrf->ClearState(vrf->get_table_partition()->parent(),
921 : vrf_table_listener_id_);
922 : }
923 74 : return true;
924 : }
925 :
926 : ArpProto::ArpIterator
927 571 : ArpProto::FindUpperBoundArpEntry(const ArpKey &key) {
928 571 : return arp_cache_.upper_bound(key);
929 : }
930 :
931 : ArpProto::ArpIterator
932 0 : ArpProto::FindLowerBoundArpEntry(const ArpKey &key) {
933 0 : return arp_cache_.lower_bound(key);
934 : }
935 :
936 0 : void ArpPathPreferenceState::HandleArpReply(Ip4Address sip, uint32_t itf) {
937 0 : WaitForTrafficIntfMap::iterator it = l3_wait_for_traffic_map_.find(itf);
938 0 : if (it == l3_wait_for_traffic_map_.end()) {
939 0 : return;
940 : }
941 :
942 0 : InterfaceArpPathPreferenceInfo &data = it->second;
943 : // reset arp_try_count to 0.
944 0 : data.arp_try_count = 0;
945 :
946 0 : if (data.prev_responded_ip == sip) {
947 0 : ++data.arp_reply_count;
948 0 : data.arp_failure_count = 0;
949 : } else {
950 0 : data.prev_responded_ip = sip;
951 0 : data.arp_send_count = 0;
952 : }
953 : }
954 :
955 0 : void ArpProto::HandlePathPreferenceArpReply(const VrfEntry *vrf, uint32_t itf,
956 : Ip4Address sip) {
957 0 : if (!vrf) {
958 0 : return;
959 : }
960 0 : InetUnicastRouteEntry *rt = vrf->GetUcRoute(sip);
961 0 : if (!rt) {
962 0 : return;
963 : }
964 :
965 : ArpVrfState *state = static_cast<ArpVrfState *>
966 0 : (vrf->GetState(vrf->get_table_partition()->parent(),
967 : vrf_table_listener_id_));
968 0 : if (!state) {
969 0 : return;
970 : }
971 0 : ArpPathPreferenceState* pstate = state->Get(sip, rt->prefix_length());
972 0 : if (!pstate) {
973 0 : return;
974 : }
975 0 : pstate->HandleArpReply(sip, itf);
976 : }
977 :
978 176 : ArpInterfaceState::ArpInterfaceState(Interface *intf):
979 176 : intf_(intf), vrf_(NULL), fabric_vrf_(NULL), walk_ref_(NULL) {
980 176 : }
981 :
982 352 : ArpInterfaceState::~ArpInterfaceState() {
983 176 : if (walk_ref_.get() && vrf_) {
984 2 : vrf_->GetEvpnRouteTable()->ReleaseWalker(walk_ref_);
985 : }
986 352 : }
987 :
988 1231 : void ArpInterfaceState::SetVrf(VrfEntry *vrf, VrfEntry *fabric_vrf) {
989 1231 : bool walk = false;
990 :
991 1231 : if (vrf_ != vrf) {
992 169 : if (walk_ref_.get() && vrf_) {
993 0 : vrf_->GetEvpnRouteTable()->ReleaseWalker(walk_ref_);
994 : }
995 169 : vrf_ = vrf;
996 : }
997 :
998 1231 : if (fabric_vrf_ != fabric_vrf) {
999 2 : fabric_vrf_ = fabric_vrf;
1000 2 : walk = true;
1001 : }
1002 :
1003 1231 : if (vrf_ == NULL) {
1004 254 : return;
1005 : }
1006 :
1007 977 : if (walk && walk_ref_.get() == NULL) {
1008 4 : walk_ref_ = vrf_->GetEvpnRouteTable()->AllocWalker(
1009 : boost::bind(&ArpInterfaceState::WalkNotify, this, _1, _2),
1010 2 : boost::bind(&ArpInterfaceState::WalkDone, this, _2));
1011 : }
1012 :
1013 977 : if (vrf_->vn() && vrf_->vn()->bridging()) {
1014 934 : if (walk) {
1015 0 : vrf_->GetEvpnRouteTable()->WalkAgain(walk_ref_);
1016 : }
1017 : }
1018 : }
1019 :
1020 0 : void ArpInterfaceState::WalkDone(DBTableBase *part) {
1021 0 : }
1022 :
1023 0 : bool ArpInterfaceState::WalkNotify(DBTablePartBase *partition,
1024 : DBEntryBase *e) {
1025 0 : const EvpnRouteEntry *evpn = static_cast<const EvpnRouteEntry *>(e);
1026 :
1027 0 : if (evpn->prefix_address().is_v4() == false) {
1028 0 : return true;
1029 : }
1030 :
1031 0 : if (evpn->prefix_address() == Ip4Address(0)) {
1032 0 : return true;
1033 : }
1034 :
1035 : const InterfaceNH *nh =
1036 0 : dynamic_cast<const InterfaceNH *>(evpn->GetActiveNextHop());
1037 0 : if (nh && nh->GetInterface() == intf_) {
1038 0 : return true;
1039 : }
1040 :
1041 0 : EvpnAgentRouteTable *table = static_cast<EvpnAgentRouteTable *>(evpn->get_table());
1042 0 : const VmInterface *vmi = static_cast<const VmInterface *>(intf_.get());
1043 0 : Agent *agent = table->agent();
1044 : boost::shared_ptr<PktInfo> pkt(new PktInfo(agent, ARP_TX_BUFF_LEN,
1045 0 : PktHandler::ARP, 0));
1046 0 : ArpHandler arp_handler(agent, pkt, *(agent->event_manager()->io_service()));
1047 :
1048 0 : MacAddress smac = vmi->GetVifMac(agent);
1049 0 : if (vrf_->forwarding_vrf() == NULL) {
1050 0 : smac = evpn->mac();
1051 : }
1052 :
1053 0 : agent->GetArpProto()->IncrementStatsVmGarpReq();
1054 0 : arp_handler.SendArp(ARPOP_REQUEST, smac, evpn->prefix_address().to_v4().to_ulong(),
1055 0 : smac, vmi->vm_mac(), evpn->prefix_address().to_v4().to_ulong(),
1056 : intf_->id(), intf_->vrf()->vrf_id());
1057 0 : return true;
1058 0 : }
|