OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
metadata_proxy_ip6.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2023 Matvey Kraposhin
3  */
4 extern "C" {
5  #include <errno.h>
6  #include <net/if.h>
7  #include <sys/socket.h>
8  #include <unistd.h>
9  #include <linux/netlink.h>
10  #include <linux/rtnetlink.h>
11  #include <linux/neighbour.h>
12  #include <linux/if_addr.h>
13  #include <arpa/inet.h>
14 }
15 #include <cstring>
16 #include <cmn/agent_cmn.h>
17 #include <oper/interface_common.h>
18 #include <oper/route_common.h>
20 #include <oper/global_vrouter.h>
24 #include "services/services_init.h"
25 
26 int MetadataProxy::VhostIndex(const std::string& vhost_name) {
27  if (vhost_name != std::string("")) {
28  int intf_idx = if_nametoindex(vhost_name.c_str());
29  if (intf_idx > 0)
30  return intf_idx;
31  }
32  return 0;
33 }
34 
36  const Ip6Address& ll_ip, const VrfEntry* intf_vrf) {
37  if (vm_intf == NULL || intf_vrf == NULL) {
38  return;
39  }
40 
41  tbb::mutex::scoped_lock lock(ll_ipv6_addr_mutex_);
42  {
43  InetUnicastAgentRouteTable *intf_inet_table =
44  intf_vrf->GetInet6UnicastRouteTable();
45  if (intf_inet_table == NULL)
46  return;
47  InetUnicastRouteEntry* rt_entry =
48  intf_inet_table->FindRoute(ll_ip);
49  // explicitly forbid advertisement of LL IPv6 route
50  // if another with the given prefix exists
51  if (rt_entry != NULL &&
52  rt_entry->prefix_address().to_v6() == ll_ip &&
53  rt_entry->prefix_length() == 128) {
54  return;
55  }
56  VnListType vn_list;
57  if (vm_intf->vn())
58  vn_list.insert(vm_intf->vn()->GetName());
59 
60  InetInterfaceKey intf_key(vm_intf->name());
62  (intf_key, vm_intf->label(), TunnelType::MplsType(),
63  vn_list, vm_intf->peer()->sequence_number());
64 
66  req.key.reset(new InetUnicastRouteKey(vm_intf->peer(),
67  intf_vrf->GetName(), ll_ip, 128));
68  req.data.reset(data);
69 
70  intf_inet_table->Process(req);
71  }
72 
73  ll_ipv6_addresses_.insert(std::make_pair(vm_intf->name(), ll_ip));
74 }
75 
77  if (vm_intf == NULL)
78  return;
79 
80  tbb::mutex::scoped_lock lock(ll_ipv6_addr_mutex_);
81 
82  Ip6Address ll_ip = Ip6Address::from_string(std::string("::"));
83  if (!ll_ipv6_addresses_.count(vm_intf->name()))
84  return;
85 
86  ll_ip = ll_ipv6_addresses_.at(vm_intf->name());
87  const VrfEntry *vrf_entry = services_->agent()->
88  vrf_table()->FindVrfFromName(vm_intf->vrf_name());
89  if (!vrf_entry)
90  return;
91 
92  DBEntryBase::KeyPtr tintf_key_ptr;
93  InetUnicastRouteEntry *c_entry = NULL;
94 
95  tintf_key_ptr = vm_intf->GetDBRequestKey();
96  const VmInterfaceKey* intf_key_ptr =
97  dynamic_cast<const VmInterfaceKey *>(tintf_key_ptr.get());
98  if (!intf_key_ptr)
99  return;
100 
101  c_entry = vrf_entry->GetUcRoute(ll_ip);
102  if (!c_entry)
103  return;
104 
105  {
106  InetUnicastAgentRouteTable *fabric_inet =
107  services_->agent()->fabric_vrf()->
108  GetInet6UnicastRouteTable();
109  fabric_inet->Delete(services_->agent()->evpn_routing_peer(),
110  services_->agent()->fabric_vrf_name(), ll_ip, 128);
111  }
112  {
113  VnListType vn_list;
114  if (vm_intf->vn())
115  vn_list.insert(vm_intf->vn()->GetName());
116  InetInterfaceKey intf_key(vm_intf->name());
117  // InetInterfaceRoute *data = new InetInterfaceRoute
118  // (intf_key, vm_intf->label(), local_path->GetTunnelType(),
119  // local_path->dest_vn_list(), local_path->sequence());
121  (intf_key, vm_intf->label(), TunnelType::MplsType(),
122  vn_list, vm_intf->peer()->sequence_number());
123 
125  vrf_entry->GetInet6UnicastRouteTable();
126  if (table) {
127  table->Delete(
128  vm_intf->peer(),
129  vrf_entry->GetName(),
130  ll_ip, c_entry->prefix_length(),
131  data);
132  }
133  }
134 
135  if (ll_ipv6_addresses_.count(vm_intf->name())) {
136  ll_ipv6_addresses_.erase(vm_intf->name());
137  }
138 }
139 
141  return ipv6_service_address_;
142 }
143 
145  if (vhost0 == NULL ||
146  !ipv6_service_address_.is_unspecified()) {
147  return;
148  }
150  LOG(ERROR, "An error has occured during retrieving IPv6 ll"
151  " address from vhost0 in"
152  " MetadataProxy::InitializeHttp6Server");
153  return;
154  }
155  const int vhost_idx = VhostIndex(
156  this->services_->agent()->vhost_interface_name());
158  boost::bind(&MetadataProxy::HandleMetadataRequest, this, _1, _2));
161  ipv6_service_address_, vhost_idx);
163 }
164 
166  PathPreference path_preference;
167  EcmpLoadBalance ecmp_load_balance;
168 
169  Agent *agent = services_->agent();
170 
171  const VmInterface *vhost_intf =
172  dynamic_cast<const VmInterface*>(agent->vhost_interface());
173 
174  VnListType vn_list;
175  vn_list.insert(agent->fabric_vn_name());
176 
178  static_cast<InetUnicastAgentRouteTable*>
180  agent->fabric_vrf_name()));
181 
182  table->AddLocalVmRouteReq(
183  agent->link_local_peer(), agent->fabric_vrf_name(),
184  Ipv6ServiceAddress(), 128, vhost_intf->GetUuid(),
185  vn_list, vhost_intf->label(), SecurityGroupList(),
186  TagList(), CommunityList(), true, path_preference,
187  Ip6Address(), ecmp_load_balance, false, false, false,
188  vhost_intf->name());
189 }
190 
192  Agent *agent = services_->agent();
193 
195  agent->fabric_vrf_name(),
196  Ipv6ServiceAddress(), 128);
197 }
198 
200 
201  VrfEntry *vrf_entry = dynamic_cast<VrfEntry*>(entry);
202 
203  // a new entry or a changed entry
204  if (vrf_entry && !vrf_entry->IsDeleted()) {
205  if (fabric_notify_id_ < 0) {
206  if (vrf_entry == services_->agent()->fabric_vrf()) {
207  InetUnicastAgentRouteTable *fabric_inet6_table =
208  vrf_entry->GetInet6UnicastRouteTable();
209  if (fabric_inet6_table) {
211  fabric_inet6_table->Register(
212  boost::bind(
214  this, _1, _2));
215  }
216  }
217  }
218  }
219 }
220 
223 
224  InetUnicastAgentRouteTable *inet_table =
225  dynamic_cast<InetUnicastAgentRouteTable*>(entry->get_table());
226  if (!inet_table)
227  return;
228 
229  InetUnicastRouteEntry *route_entry =
230  dynamic_cast<InetUnicastRouteEntry*>(entry);
231  if (!route_entry)
232  return;
233 
234  const AgentPath *active_path = route_entry->GetActivePath();
235  const NextHop *active_nh = active_path ? active_path->nexthop() : NULL;
236  const InterfaceNH *interface_nh =
237  dynamic_cast<const InterfaceNH*>(active_nh);
238  if (interface_nh == NULL) {
239  return;
240  }
241 
242  const VmInterface *interface = dynamic_cast<const VmInterface*>(
243  interface_nh->GetInterface());
244  if (interface == NULL) {
245  return;
246  }
247 
248  const Ip6Address mip6 = interface->mdata_ip6_addr();
249 
250  if (mip6 == route_entry->prefix_address().to_v6()) {
251  if (entry->IsDeleted()) {
252  } else {
253  // Create a neighbour record (ip neigh add ...)
254  this->NetlinkAddVhostNb(mip6, interface->vm_mac());
255 
256  // Create a routing record (ip route add)
257  this->NetlinkAddInterfaceRoute(mip6);
258  }
259  }
260 }
261 
263  VmInterface *vmi = dynamic_cast<VmInterface *>(entry);
264  if (!vmi)
265  return;
266 
267  if (vmi->IsDeleted() && vmi != services_->agent()->vhost_interface()) {
269  return;
270  }
271 
272  if (!vmi->IsDeleted() && vmi == services_->agent()->vhost_interface()) {
274  }
275 
276  if (vmi->IsDeleted() && vmi == services_->agent()->vhost_interface()) {
277  this->DeleteVhostRoute();
278  }
279 }
280 
284  fabric_notify_id_ = -1; // Will be registered later,
285  // since the table isn't present now
286  if (services_->agent()->vrf_table()) {
289  boost::bind(&MetadataProxy::OnAVrfChange, this, _1, _2));
290  }
291  if (services_->agent()->interface_table()) {
294  boost::bind(&MetadataProxy::OnAnInterfaceChange, this, _1, _2));
295  }
296 }
297 
299  if (vrf_table_notify_id_ > -1) {
300  services_->agent()->vrf_table()->
301  Unregister(vrf_table_notify_id_);
303  }
304  if (intf_table_notify_id_ > -1) {
306  Unregister(intf_table_notify_id_);
308  }
309  if (fabric_notify_id_ > -1) {
310  services_->agent()->fabric_vrf()->
311  GetInet6UnicastRouteTable()->
312  Unregister(fabric_notify_id_);
313  fabric_notify_id_ = -1;
314  }
315 }
316 
317 //
318 // END-OF-FILE
319 //
uint8_t prefix_length() const
!
const Interface * GetInterface() const
Definition: nexthop.h:1293
void OnAFabricRouteChange(DBTablePartBase *part, DBEntryBase *e)
A callback that is invoked each time when a route is modified in the fabric policy VRF inet4 unicast ...
Definition: vrf.h:86
void AddLocalVmRouteReq(const Peer *peer, const string &vm_vrf, const IpAddress &addr, uint8_t plen, LocalVmRoute *data)
VrfEntry * fabric_vrf() const
Definition: agent.h:915
const boost::uuids::uuid & GetUuid() const
Definition: interface.h:113
MetadataServer * http_server6_
A pointer to a HTTP server listening on a IPv6 socket for Metadata requests from tenants / virtual ma...
DBTableBase * get_table() const
Definition: db_entry.cc:119
Ip6Address ipv6_service_address_
An IPv6 address on which Metadata6 link local service listens on. We use it instead of IPv4 compute I...
const Interface * vhost_interface() const
Definition: agent.h:935
bool IsDeleted() const
Definition: db_entry.h:49
DBTableBase::ListenerId fabric_notify_id_
an ID of a listener (callback) that acts when a Fabric Policy VRF entry is modified ...
const Ip6Address & Ipv6ServiceAddress() const
Returns an IPv6 address of the Metadata TF link local service.
std::vector< int > SecurityGroupList
Definition: agent.h:201
std::map< std::string, Ip6Address > ll_ipv6_addresses_
A correspondence table between a name of a vm interface, which requests a data from the service and t...
void UnregisterListeners()
Unregisters all callbacks that were registered earlier to intercept Agent&#39;s events: MetadataProxy::On...
const std::string & vhost_interface_name() const
Definition: agent.cc:104
InterfaceTable * interface_table() const
Definition: agent.h:465
static TypeBmap MplsType()
Definition: nexthop.h:312
InetUnicastRouteEntry * FindRoute(const IpAddress &ip)
InetUnicastAgentRouteTable * GetInet6UnicastRouteTable() const
Definition: vrf.cc:338
const string & GetName() const
Definition: vrf.h:100
const Peer * peer() const
std::unique_ptr< DBRequestKey > KeyPtr
Definition: db_entry.h:25
uint32_t label() const
Definition: interface.h:127
ListenerId Register(ChangeCallback callback, const std::string &name="unspecified")
Definition: db_table.cc:181
const std::string & fabric_vrf_name() const
Definition: agent.h:903
const AgentPath * GetActivePath() const
Definition: agent_route.cc:876
bool NetlinkGetVhostIp(Ip6Address &vhost_ll_ip)
Adds an IP address specified in vhost_ll_ip to vhost0 interface inet6 addresses.
NextHop * nexthop() const
Definition: agent_path.cc:87
const Peer * link_local_peer() const
Definition: agent.h:1024
void OnAVrfChange(DBTablePartBase *part, DBEntryBase *e)
A callback that is invoked each time when a VRF entry is modified: added, changed or deleted...
static void Delete(const Peer *peer, const string &vrf_name, const IpAddress &addr, uint8_t plen)
DBTableBase::ListenerId intf_table_notify_id_
an ID of a listener (callback) that acts when an InterfaceTable entry is modified ...
KeyPtr GetDBRequestKey() const
Definition: agent.h:358
tbb::mutex ll_ipv6_addr_mutex_
A mutex which prevents simultaneous access to MetadataProxy::ll_ipv6_addresses_ table and member func...
void AdvertiseMetaDataLinkLocalRoutes(const VmInterface *vm, const Ip6Address &ll_ip, const VrfEntry *intf_vrf)
Advertises routes to a given vm-interface via a given IPv6 address. Routes are announced in the fabri...
boost::asio::ip::address_v6 Ip6Address
Definition: address.h:15
void OnAnInterfaceChange(DBTablePartBase *part, DBEntryBase *e)
A callback which is invoked everytime any vm interface is changed. Handles deletion of routes associa...
Agent * agent()
Definition: services_init.h:31
uint64_t sequence_number() const
Definition: peer.h:94
const VnEntry * vn() const
void InitializeHttp6Server(const VmInterface *vhost0)
Initializes an HTTP server for IPv6 requests.
std::vector< std::string > CommunityList
Definition: bgp_config.h:347
Ip6Address mdata_ip6_addr() const
int VhostIndex(const std::string &vhost_name)
Returns index of a network device that is specified by vhost_name.
std::set< std::string > VnListType
Definition: agent.h:212
ServicesModule * services_
virtual const PrefixType & prefix_address() const
Returns the value of a stored prefix address (IPv4, IPv6 or MAC address)
Definition: agent_route.h:375
VrfTable * vrf_table() const
Definition: agent.h:485
void DeleteVhostRoute()
Deletes the LL route to vhost0 interface in the fabric VRF instance.
const std::string & vrf_name() const
#define HTTP_WILDCARD_ENTRY
Definition: http_server.h:16
#define LOG(_Level, _Msg)
Definition: logging.h:33
virtual bool Initialize(unsigned short port)
Definition: tcp_server.cc:59
void Process(DBRequest &req)
Definition: agent_route.cc:186
const std::string & name() const
Definition: interface.h:114
DBTableBase::ListenerId vrf_table_notify_id_
an ID of a listener (callback) that acts when the VRF Table is modified
void HandleMetadataRequest(HttpSession *session, const HttpRequest *request)
const string & GetName() const
Definition: vn.h:162
uint16_t metadata_server_port() const
Definition: agent.h:959
const std::string & fabric_vn_name() const
Definition: agent.h:901
InetUnicastRouteEntry * GetUcRoute(const IpAddress &addr) const
Definition: vrf.cc:237
void RegisterHandler(const std::string &path, HttpHandlerFn handler)
Definition: http_server.cc:102
InetUnicastAgentRouteTable * GetInet6UnicastRouteTable(const std::string &vrf_name)
Definition: vrf.cc:922
void RegisterListeners()
Registers callbacks to intercept Agent&#39;s events emerging when a VRF entry is modified or an Interface...
void insert(const Path *path)
Definition: route.cc:24
void DeleteMetaDataLinkLocalRoute(const VmInterface *vm_intf)
Deletes an announced earlier route to a vm interface via a given IPv6 address.
const Peer * evpn_routing_peer() const
Definition: agent.h:1027
void AdvertiseVhostRoute()
Advertises the LL route to vhost0 interface in the fabric VRF instance.
std::vector< int > TagList
Definition: agent.h:202