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