OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
arp_entry.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 #include "base/os.h"
6 #include "services/arp_proto.h"
9 #include "oper/route_common.h"
10 
11 ArpEntry::ArpEntry(boost::asio::io_context &io, ArpHandler *handler,
12  ArpKey &key, const VrfEntry *vrf, State state,
13  const Interface *itf)
14  : io_(io), key_(key), nh_vrf_(vrf), state_(state), retry_count_(0),
15  handler_(handler), arp_timer_(NULL), interface_(itf) {
16  if (!IsDerived()) {
17  arp_timer_ = TimerManager::CreateTimer(io, "Arp Entry timer",
18  TaskScheduler::GetInstance()->GetTaskId("Agent::Services"),
20  }
21 }
22 
24  if (!IsDerived()) {
25  arp_timer_->Cancel();
27  }
28  handler_.reset(NULL);
29 }
30 
32  ArpProto *arp_proto = handler_->agent()->GetArpProto();
33  //Add ArpRoute for Derived entry
35 
37  ArpEntry *entry = arp_proto->FindArpEntry(key);
38  if (entry) {
39  entry->HandleArpRequest();
40  } else {
41  entry = new ArpEntry(io_, handler_.get(), key, nh_vrf_, ArpEntry::INITING,
42  interface_.get());
43  if (arp_proto->AddArpEntry(entry) == false) {
44  delete entry;
45  return;
46  }
47  entry->HandleArpRequest();
48  }
49 }
50 
52  if (IsDerived()) {
54  return true;
55  }
56  if (IsResolved())
57  AddArpRoute(true);
58  else {
59  AddArpRoute(false);
60  if (state_ & ArpEntry::INITING) {
63  }
64  }
65  return true;
66 }
67 
69 
70  if (IsDerived()) {
71  /* We don't expect ARP replies in derived Vrf */
72  return;
73  }
76  ArpProto *arp_proto = handler_->agent()->GetArpProto();
77  arp_timer_->Cancel();
78  retry_count_ = 0;
79  mac_address_ = mac;
80  if (state_ == ArpEntry::RESOLVING) {
81  arp_proto->IncrementStatsResolved();
82  arp_proto->IncrementStatsResolved(interface_->id());
83  }
86  AddArpRoute(true);
87  }
88 }
89 
92  return true;
93  ArpProto *arp_proto = handler_->agent()->GetArpProto();
94  if (retry_count_ < arp_proto->max_retries()) {
95  retry_count_++;
97  } else {
98  std::vector<Ip4Address> gateway_list =
99  handler_->agent()->vhost_default_gateway();
100  Ip4Address ip(key_.ip);
101  if (std::find(gateway_list.begin(), gateway_list.end(), ip) !=
102  gateway_list.end()) {
104  ARP_TRACE(Trace, "Retry exceeded, set arp to resolving",
105  ip.to_string(), key_.vrf->GetName(), "");
106  }
107  ARP_TRACE(Trace, "Retry exceeded", ip.to_string(),
108  key_.vrf->GetName(), "");
109  arp_proto->IncrementStatsMaxRetries();
110 
111  // if Arp NH is not present, let the entry be deleted
112  if (DeleteArpRoute())
113  return false;
114 
115  // keep retrying till Arp NH is deleted
116  retry_count_ = 0;
117  SendArpRequest();
118  }
119  return true;
120 }
121 
123  Ip4Address ip(key_.ip);
124  const string& vrf_name = key_.vrf->GetName();
125  ArpNHKey nh_key(vrf_name, ip, false);
126  ArpNH *arp_nh = static_cast<ArpNH *>(handler_->agent()->nexthop_table()->
127  FindActiveEntry(&nh_key));
128  if (!arp_nh) {
129  // do not re-resolve if Arp NH doesnt exist
130  return false;
131  }
133  SendArpRequest();
134  return true;
135 }
136 
138  Agent *agent = handler_->agent();
139  ArpProto *arp_proto = agent->GetArpProto();
140  if (agent->router_id_configured()) {
141  if (interface_->type() == Interface::VM_INTERFACE) {
142  const VmInterface *vmi =
143  static_cast<const VmInterface *>(interface_.get());
144  MacAddress smac = vmi->GetVifMac(agent);
145  if (key_.vrf && key_.vrf->vn()) {
147  (Ip4Address(key_.ip));
148  IpAddress dns_ip = key_.vrf->vn()->GetDnsFromIpam
149  (Ip4Address(key_.ip));
150  if (!gw_ip.is_unspecified() && gw_ip.is_v4()) {
151  handler_->SendArp(ARPOP_REQUEST, smac,
152  gw_ip.to_v4().to_ulong(),
153  smac, vmi->vm_mac(), gw_ip.to_v4().to_ulong(),
154  vmi->id(), key_.vrf->vrf_id());
155  }
156  if (!dns_ip.is_unspecified() && dns_ip.is_v4() &&
157  dns_ip != gw_ip) {
158  handler_->SendArp(ARPOP_REQUEST, smac,
159  dns_ip.to_v4().to_ulong(),
160  smac, vmi->vm_mac(), dns_ip.to_v4().to_ulong(),
161  vmi->id(), key_.vrf->vrf_id());
162  }
163  }
164  } else {
165  handler_->SendArp(ARPOP_REQUEST, arp_proto->ip_fabric_interface_mac(),
166  agent->router_id().to_ulong(), MacAddress(),
167  MacAddress::BroadcastMac(), agent->router_id().to_ulong(),
168  arp_proto->ip_fabric_interface_index(),
169  key_.vrf->vrf_id());
170  }
171 
172  }
173 
174  retry_count_++;
176 }
177 
180 }
181 
183  if (key_.vrf != nh_vrf_) {
184  return true;
185  }
186  return false;
187 }
188 
189 void ArpEntry::StartTimer(uint32_t timeout, uint32_t mtype) {
190  arp_timer_->Cancel();
191  arp_timer_->Start(timeout, boost::bind(&ArpProto::TimerExpiry,
192  handler_->agent()->GetArpProto(),
193  key_, mtype, interface_.get()));
194 }
195 
197  assert(!IsDerived());
198  Agent *agent = handler_->agent();
199  ArpProto *arp_proto = agent->GetArpProto();
200  uint32_t vrf_id = VrfEntry::kInvalidIndex;
201  uint32_t intf_id = arp_proto->ip_fabric_interface_index();
202  Ip4Address ip;
203  MacAddress smac;
204  if (interface_->type() == Interface::VM_INTERFACE) {
205  const VmInterface *vmi =
206  static_cast<const VmInterface *>(interface_.get());
207  ip = vmi->GetServiceIp(Ip4Address(key_.ip)).to_v4();
208  if (vmi->vmi_type() == VmInterface::VHOST) {
209  ip = agent->router_id();
210  }
211  vrf_id = nh_vrf_->vrf_id();
212  if (vmi->parent()) {
213  intf_id = vmi->parent()->id();
214  }
215  smac = vmi->GetVifMac(agent);
216  } else {
217  if (agent->is_l3mh() == true) {
218  intf_id = interface_->id();
219  ip = agent->ip_fabric_intf_addr_list()[intf_id];
220  } else {
221  ip = agent->router_id();
222  }
223  VrfEntry *vrf =
224  agent->vrf_table()->FindVrfFromName(agent->fabric_vrf_name());
225  if (vrf) {
226  vrf_id = vrf->vrf_id();
227  }
228  smac = interface_->mac();
229  }
230 
231  if (vrf_id != VrfEntry::kInvalidIndex) {
232  handler_->SendArp(ARPOP_REQUEST, smac, ip.to_ulong(),
233  MacAddress(), MacAddress::BroadcastMac(), key_.ip, intf_id, vrf_id);
234  }
235 
237 }
238 
239 void ArpEntry::AddArpRoute(bool resolved) {
240  if (key_.vrf->GetName() == handler_->agent()->linklocal_vrf_name()) {
241  // Do not squash existing route entry.
242  // should be smarter and not replace an existing route.
243  return;
244  }
245 
246  Ip4Address ip(key_.ip);
247  const string& vrf_name = key_.vrf->GetName();
248  ArpNHKey nh_key(nh_vrf_->GetName(), ip, false);
249  ArpNH *arp_nh = static_cast<ArpNH *>(handler_->agent()->nexthop_table()->
250  FindActiveEntry(&nh_key));
251 
252  MacAddress mac = mac_address();
253  if (arp_nh && arp_nh->GetResolveState() &&
254  mac.CompareTo(arp_nh->GetMac()) == 0) {
255  // MAC address unchanged, ignore
256  if (!IsDerived()) {
257  return;
258  } else {
259  /* Return if the route is already existing */
261  handler_->agent()->local_peer(), vrf_name, ip, 32);
263  FindActiveEntry(rt_key);
264  delete rt_key;
265  if (entry) {
266  return;
267  }
268  resolved = true;
269  }
270  }
271 
272  ARP_TRACE(Trace, "Add", ip.to_string(), vrf_name, mac.ToString());
274 
275  bool policy = false;
277  TagList tag;
278  VnListType vn_list;
279  const NextHop *anh;
280  if (entry && (anh = entry->GetActiveNextHop()) != NULL) {
281  policy = anh->PolicyEnabled();
282  sg = entry->GetActivePath()->sg_list();
283  tag = entry->GetActivePath()->tag_list();
284  vn_list = entry->GetActivePath()->dest_vn_list();
285  }
286 
287  const Interface *itf = handler_->agent()->GetArpProto()->ip_fabric_interface();
288  if (interface_->type() == Interface::PHYSICAL) {
289  itf = interface_.get();
290  }
291  if (interface_->type() == Interface::VM_INTERFACE) {
292  const VmInterface *vintf =
293  static_cast<const VmInterface *>(interface_.get());
294  if (vintf->vmi_type() == VmInterface::VHOST) {
295  for (InterfaceList::size_type i = 0; i != vintf->parent_list().size(); i++) {
296  itf = vintf->parent_list()[i];
297  handler_->agent()->fabric_inet4_unicast_table()->ArpRoute(
298  DBRequest::DB_ENTRY_ADD_CHANGE, vrf_name, ip, mac,
299  nh_vrf_->GetName(), *itf, resolved, 32, policy,
300  vn_list, sg, tag);
301  }
302  return;
303  }
304  }
305 
306  handler_->agent()->fabric_inet4_unicast_table()->ArpRoute(
307  DBRequest::DB_ENTRY_ADD_CHANGE, vrf_name, ip, mac,
308  nh_vrf_->GetName(), *itf, resolved, 32, policy,
309  vn_list, sg, tag);
310 }
311 
313  if (key_.vrf->GetName() == handler_->agent()->linklocal_vrf_name()) {
314  return true;
315  }
316 
317  Ip4Address ip(key_.ip);
318  const string& vrf_name = key_.vrf->GetName();
319  ArpNHKey nh_key(nh_vrf_->GetName(), ip, false);
320  ArpNH *arp_nh = static_cast<ArpNH *>(handler_->agent()->nexthop_table()->
321  FindActiveEntry(&nh_key));
322  if (!arp_nh)
323  return true;
324 
325  MacAddress mac = mac_address();
326  ARP_TRACE(Trace, "Delete", ip.to_string(), vrf_name, mac.ToString());
327  if (IsDerived()) {
328  //Just enqueue a delete, no need to mark nexthop invalid
329  InetUnicastAgentRouteTable::Delete(handler_->agent()->local_peer(),
330  vrf_name, ip, 32);
331  return true;
332  }
333 
334  handler_->agent()->fabric_inet4_unicast_table()->ArpRoute(
335  DBRequest::DB_ENTRY_DELETE, vrf_name, ip, mac, nh_vrf_->GetName(),
336  *interface_, false, 32, false, Agent::NullStringList(),
338  return false;
339 }
340 
341 void ArpEntry::Resync(bool policy, const VnListType &vnlist,
342  const SecurityGroupList &sg,
343  const TagList &tag) {
344  Ip4Address ip(key_.ip);
345  const string& vrf_name = key_.vrf->GetName();
346  ARP_TRACE(Trace, "Resync", ip.to_string(), vrf_name,
347  mac_address().ToString());
348  handler_->agent()->fabric_inet4_unicast_table()->ArpRoute(
351  32, policy, vnlist, sg, tag);
352 }
uint32_t ip_fabric_interface_index() const
Definition: arp_proto.h:108
IpAddress GetDnsFromIpam(const IpAddress &ip) const
Definition: vn.cc:668
const MacAddress & vm_mac() const
void HandleArpReply(const MacAddress &)
Definition: arp_entry.cc:68
void StartTimer(uint32_t timeout, uint32_t mtype)
Definition: arp_entry.cc:189
Definition: vrf.h:86
InetUnicastRouteEntry * FindLPM(const IpAddress &ip)
const ArpKey & key() const
Definition: arp_entry.h:36
void Resync(bool policy, const VnListType &vnlist, const SecurityGroupList &sg, const TagList &tag)
Definition: arp_entry.cc:341
VrfEntry * FindVrfFromName(const string &name)
Definition: vrf.cc:873
const uint32_t id() const
Definition: interface.h:123
int retry_count_
Definition: arp_entry.h:65
bool AddArpEntry(ArpEntry *entry)
Definition: arp_proto.cc:838
bool is_l3mh() const
Definition: agent.h:725
ArpKey key_
Definition: arp_entry.h:61
boost::asio::ip::address IpAddress
Definition: address.h:13
bool AgingExpiry()
Definition: arp_entry.cc:122
const MacAddress & GetVifMac(const Agent *) const
std::vector< int > SecurityGroupList
Definition: agent.h:201
InetUnicastAgentRouteTable * GetInet4UnicastRouteTable() const
Definition: vrf.cc:319
const string & GetName() const
Definition: vrf.h:100
boost::asio::io_context & io_
Definition: arp_entry.h:60
IpAddress GetServiceIp(const IpAddress &ip) const
ArpProto * GetArpProto() const
Definition: agent.h:978
Base class for all Route entries in agent.
Definition: agent_route.h:224
bool RetryExpiry()
Definition: arp_entry.cc:90
AddressList ip_fabric_intf_addr_list() const
Definition: agent.h:661
std::string ToString() const
Definition: mac_address.cc:53
void IncrementStatsResolved()
Definition: arp_proto.h:130
void SendArpRequest()
Definition: arp_entry.cc:196
void AddArpRoute(bool resolved)
Definition: arp_entry.cc:239
const std::string & fabric_vrf_name() const
Definition: agent.h:903
ArpEntry(boost::asio::io_context &io, ArpHandler *handler, ArpKey &key, const VrfEntry *vrf, State state, const Interface *itf)
Definition: arp_entry.cc:11
static void Delete(const Peer *peer, const string &vrf_name, const IpAddress &addr, uint8_t plen)
virtual ~ArpEntry()
Definition: arp_entry.cc:23
const VrfEntry * nh_vrf_
Definition: arp_entry.h:62
Definition: agent.h:358
static TaskScheduler * GetInstance()
Definition: task.cc:547
MacAddress mac_address_
Definition: arp_entry.h:63
Ip4Address router_id() const
Definition: agent.h:666
int CompareTo(const MacAddress &rhs, int len=0) const
Definition: mac_address.cc:87
void IncrementStatsMaxRetries()
Definition: arp_proto.h:131
State state_
Definition: arp_entry.h:64
Definition: nexthop.h:820
uint32_t aging_timeout() const
Definition: arp_proto.h:168
Definition: trace.h:220
boost::intrusive_ptr< ArpHandler > handler_
Definition: arp_entry.h:66
ArpEntry * FindArpEntry(const ArpKey &key)
Definition: arp_proto.cc:885
static const MacAddress & BroadcastMac()
Definition: mac_address.h:152
bool IsDerived()
Definition: arp_entry.cc:182
static const std::set< std::string > & NullStringList()
Definition: agent.h:438
const uint32_t vrf_id() const
Definition: vrf.h:99
std::set< std::string > VnListType
Definition: agent.h:212
static Timer * CreateTimer(boost::asio::io_context &service, const std::string &name, int task_id=Timer::GetTimerTaskId(), int task_instance=Timer::GetTimerInstanceId(), bool delete_on_completion=false)
Definition: timer.cc:201
boost::asio::ip::address_v4 Ip4Address
Definition: address.h:14
bool TimerExpiry(ArpKey &key, uint32_t timer_type, const Interface *itf)
Definition: arp_proto.cc:760
bool Cancel()
Definition: timer.cc:150
VrfTable * vrf_table() const
Definition: agent.h:485
bool router_id_configured()
Definition: agent.h:676
#define ARP_TRACE(obj,...)
Definition: arp_proto.h:12
VmInterface::VmiType vmi_type() const
bool DeleteArpRoute()
Definition: arp_entry.cc:312
bool Start(int time, Handler handler, ErrorHandler error_handler=NULL)
Definition: timer.cc:108
VnEntry * vn() const
Definition: vrf.h:101
bool HandleArpRequest()
Definition: arp_entry.cc:51
static const uint32_t kInvalidIndex
Definition: vrf.h:88
uint32_t retry_timeout() const
Definition: arp_proto.h:167
void SendGratuitousArp()
Definition: arp_entry.cc:137
bool PolicyEnabled() const
Definition: nexthop.h:407
void HandleDerivedArpRequest()
Definition: arp_entry.cc:31
const VrfEntry * vrf
Definition: arp_entry.h:18
const MacAddress & mac_address() const
Definition: arp_entry.h:38
InterfaceList parent_list() const
static const uint32_t kGratRetryTimeout
Definition: arp_proto.h:23
const Interface * parent() const
bool IsResolved()
Definition: arp_entry.cc:178
const MacAddress & ip_fabric_interface_mac() const
Definition: arp_proto.h:111
IpAddress GetGatewayFromIpam(const IpAddress &ip) const
Definition: vn.cc:660
static bool DeleteTimer(Timer *Timer)
Definition: timer.cc:222
Timer * arp_timer_
Definition: arp_entry.h:67
std::vector< int > TagList
Definition: agent.h:202
InterfaceConstRef interface_
Definition: arp_entry.h:68
in_addr_t ip
Definition: arp_entry.h:17