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