Line data Source code
1 : /*
2 : * Copyright (c) 2016 Juniper Networks, Inc. All rights reserved.
3 : * Copyright Contributors to the OpenSDN project
4 : */
5 :
6 : #include <oper/route_common.h>
7 : #include <oper/ecmp_load_balance.h>
8 : #include <oper/interface_common.h>
9 : #include <oper/vm_interface.h>
10 : #include <oper/inet_unicast_route.h>
11 : #include <oper/metadata_ip.h>
12 :
13 : const IpAddress MetaDataIp::kDefaultIp;
14 :
15 0 : MetaDataIp::MetaDataIp(MetaDataIpAllocator *allocator, VmInterface *intf,
16 0 : MetaDataIpType type, bool insert_metadata_ip, bool ipv4) :
17 0 : allocator_(allocator), index_(-1), intf_(intf),
18 0 : intf_label_(MplsTable::kInvalidLabel), service_ip_(), destination_ip_(),
19 0 : active_(false), type_(type), insert_metadata_ip_(insert_metadata_ip),
20 0 : ipv4_(ipv4) {
21 0 : if (insert_metadata_ip_) {
22 0 : index_ = allocator_->AllocateIndex(this);
23 0 : intf->InsertMetaDataIpInfo(this);
24 : }
25 0 : }
26 :
27 330 : MetaDataIp::MetaDataIp(MetaDataIpAllocator *allocator, VmInterface *intf,
28 330 : uint16_t index, bool ipv4) :
29 330 : allocator_(allocator), index_(index), intf_(intf),
30 330 : intf_label_(MplsTable::kInvalidLabel), service_ip_(), destination_ip_(),
31 330 : active_(false), type_(LINKLOCAL), ipv4_(ipv4) {
32 330 : allocator_->AllocateIndex(this, index_);
33 330 : intf_->InsertMetaDataIpInfo(this);
34 330 : }
35 :
36 330 : MetaDataIp::~MetaDataIp() {
37 330 : if (type_ == HEALTH_CHECK) {
38 0 : if (insert_metadata_ip_) {
39 0 : intf_->DeleteMetaDataIpInfo(this);
40 0 : allocator_->ReleaseIndex(this);
41 : }
42 : } else {
43 330 : intf_->DeleteMetaDataIpInfo(this);
44 330 : allocator_->ReleaseIndex(this);
45 : }
46 330 : set_active(false);
47 330 : }
48 :
49 : template<>
50 825 : Ip4Address MetaDataIp::IndexToIpAddress<Ip4Address>(uint32_t idx) {
51 825 : uint32_t ip = METADATA_IP_ADDR & 0xFFFF0000;
52 825 : ip += (((uint32_t)idx) & 0xFFFF);
53 825 : return Ip4Address(ip);
54 : }
55 :
56 : template<>
57 990 : Ip6Address MetaDataIp::IndexToIpAddress<Ip6Address>(uint32_t idx) {
58 990 : Ip6Address::bytes_type ip_bytes =
59 : {0xFE, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
60 : (uint32_t)idx & 0xFF00,
61 990 : (uint32_t)idx & 0x00FF};
62 990 : return Ip6Address(ip_bytes);
63 : }
64 :
65 : template<>
66 0 : uint32_t MetaDataIp::IpAddressToIndex<Ip4Address>(const Ip4Address& ip) {
67 0 : uint32_t idx = ip.to_ulong();
68 0 : if ((idx & 0xFFFF0000) != (METADATA_IP_ADDR & 0xFFFF0000))
69 0 : return (0xFFFF + 1);
70 0 : idx &= 0xFFFF;
71 0 : return idx;
72 : }
73 :
74 : template<>
75 0 : uint32_t MetaDataIp::IpAddressToIndex<Ip6Address>(const Ip6Address& ip) {
76 0 : uint32_t idx = ip.to_bytes()[15] + (ip.to_bytes()[14] << 8);
77 0 : return idx;
78 : }
79 :
80 1650 : IpAddress MetaDataIp::GetLinkLocalIp() const {
81 1650 : if (ipv4_) {
82 825 : return GetLinkLocalIp4();
83 : }
84 825 : return GetLinkLocalIp6();
85 : }
86 :
87 825 : Ip4Address MetaDataIp::GetLinkLocalIp4() const {
88 825 : return IndexToIpAddress<Ip4Address>(index_);
89 : }
90 :
91 990 : Ip6Address MetaDataIp::GetLinkLocalIp6() const {
92 990 : return IndexToIpAddress<Ip6Address>(index_);
93 : }
94 :
95 0 : IpAddress MetaDataIp::service_ip() const {
96 : // check if explicit configuration of service ip is present for
97 : // this metadata ip
98 0 : if (service_ip_ == kDefaultIp) {
99 0 : IpAddress service_ip;
100 0 : if (type_ == HEALTH_CHECK) {
101 : // for metadata IP type Health Check first verify
102 : // if service health check ip is available on interface
103 0 : service_ip = intf_->service_health_check_ip();
104 0 : if (service_ip != kDefaultIp) {
105 0 : return service_ip;
106 : }
107 : }
108 : // check if service ip on the primary ip addr of interface
109 : // is available
110 0 : service_ip = intf_->GetServiceIp(intf_->primary_ip_addr());
111 0 : if (service_ip != kDefaultIp) {
112 0 : return service_ip;
113 : }
114 : // if service IP is not available fallback to MetaData IP
115 0 : return Ip4Address(METADATA_IP_ADDR);
116 : }
117 0 : return service_ip_;
118 : }
119 :
120 0 : IpAddress MetaDataIp::destination_ip() const {
121 0 : if (destination_ip_.to_v4() == kDefaultIp) {
122 0 : return intf_->primary_ip_addr();
123 : }
124 0 : return destination_ip_;
125 : }
126 :
127 0 : void MetaDataIp::set_destination_ip(const IpAddress &dst_ip) {
128 0 : destination_ip_ = dst_ip;
129 0 : }
130 :
131 2644 : void MetaDataIp::set_active(bool active) {
132 2644 : if (active_ == active) {
133 1984 : return;
134 : }
135 660 : active_ = active;
136 660 : UpdateRoute();
137 : }
138 :
139 4463 : void MetaDataIp::UpdateInterfaceCb() {
140 4463 : if (intf_label_ != intf_->label()) {
141 330 : intf_label_ = intf_->label();
142 330 : UpdateRoute();
143 : }
144 4463 : }
145 :
146 0 : const Interface *MetaDataIp::GetInterface() const {
147 0 : return intf_;
148 : }
149 :
150 990 : void MetaDataIp::UpdateRoute() {
151 990 : if (active_ && intf_->label() != MplsTable::kInvalidLabel) {
152 330 : intf_label_ = intf_->label();
153 330 : allocator_->AddFabricRoute(this);
154 : } else {
155 660 : allocator_->DelFabricRoute(this);
156 660 : intf_label_ = MplsTable::kInvalidLabel;
157 : }
158 990 : }
159 :
160 4 : MetaDataIpAllocator::MetaDataIpAllocator(Agent *agent, uint16_t start,
161 4 : uint16_t end) :
162 4 : agent_(agent), index_table_(), start_(start), end_(end) {
163 4 : }
164 :
165 4 : MetaDataIpAllocator::~MetaDataIpAllocator() {
166 4 : }
167 :
168 0 : MetaDataIp *MetaDataIpAllocator::FindIndex(uint16_t id) {
169 0 : uint16_t index = end_ - id;
170 0 : return index_table_.At(index);
171 : }
172 :
173 0 : uint16_t MetaDataIpAllocator::AllocateIndex(MetaDataIp *ip) {
174 0 : uint16_t index = index_table_.Insert(ip);
175 0 : assert(index <= end_ && (end_ - index) >= start_);
176 0 : return (end_ - index);
177 : }
178 :
179 330 : void MetaDataIpAllocator::AllocateIndex(MetaDataIp *ip, uint16_t id) {
180 330 : assert(id <= end_ && id >= start_);
181 330 : uint16_t index = end_ - id;
182 330 : assert(index == index_table_.InsertAtIndex(index, ip));
183 330 : }
184 :
185 330 : void MetaDataIpAllocator::ReleaseIndex(MetaDataIp *ip) {
186 330 : uint16_t index = end_ - ip->index_;
187 330 : index_table_.Remove(index);
188 330 : }
189 :
190 330 : bool MetaDataIpAllocator::CanAddRoute(MetaDataIp* ip) {
191 660 : if (ip->intf_->vmi_type() == VmInterface::VHOST ||
192 660 : ip->intf_->vn() == NULL || ip->intf_->vrf() == NULL) {
193 0 : return false;
194 : }
195 :
196 330 : return true;
197 : }
198 :
199 330 : void MetaDataIpAllocator::AddFabricRoute(MetaDataIp *ip) {
200 330 : if (!CanAddRoute(ip)) {
201 0 : return;
202 : }
203 330 : PathPreference path_preference;
204 330 : EcmpLoadBalance ecmp_load_balance;
205 330 : ip->intf_->SetPathPreference(&path_preference, false, Ip4Address(0));
206 :
207 330 : VnListType vn_list;
208 330 : vn_list.insert(ip->intf_->vn()->GetName());
209 :
210 330 : if (ip->ipv4_) {
211 : InetUnicastAgentRouteTable *table =
212 : static_cast<InetUnicastAgentRouteTable*>
213 330 : (agent_->vrf_table()->GetInet4UnicastRouteTable(
214 165 : agent_->fabric_vrf_name()));
215 :
216 330 : table->AddLocalVmRouteReq(
217 165 : agent_->link_local_peer(), agent_->fabric_vrf_name(),
218 165 : ip->GetLinkLocalIp(), 32, ip->intf_->GetUuid(),
219 330 : vn_list, ip->intf_->label(), SecurityGroupList(),
220 330 : TagList(), CommunityList(), true, path_preference,
221 330 : Ip4Address(0), ecmp_load_balance, false, false, false,
222 165 : ip->intf_->name());
223 : } else {
224 : InetUnicastAgentRouteTable *table =
225 : static_cast<InetUnicastAgentRouteTable*>
226 330 : (agent_->vrf_table()->GetInet6UnicastRouteTable(
227 165 : agent_->fabric_vrf_name()));
228 :
229 330 : table->AddLocalVmRouteReq(
230 165 : agent_->link_local_peer(), agent_->fabric_vrf_name(),
231 165 : ip->GetLinkLocalIp(), 128, ip->intf_->GetUuid(),
232 330 : vn_list, ip->intf_->label(), SecurityGroupList(),
233 330 : TagList(), CommunityList(), true, path_preference,
234 330 : Ip6Address(), ecmp_load_balance, false, false, false,
235 165 : ip->intf_->name());
236 : }
237 330 : }
238 :
239 660 : void MetaDataIpAllocator::DelFabricRoute(MetaDataIp *ip) {
240 660 : if (ip->ipv4_) {
241 330 : InetUnicastAgentRouteTable::Delete(agent_->link_local_peer(),
242 330 : agent_->fabric_vrf_name(),
243 660 : ip->GetLinkLocalIp(), 32);
244 : } else {
245 330 : InetUnicastAgentRouteTable::Delete(agent_->link_local_peer(),
246 330 : agent_->fabric_vrf_name(),
247 660 : ip->GetLinkLocalIp(), 128);
248 : }
249 660 : }
250 :
|