Line data Source code
1 : /*
2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3 : * Copyright Contributors to the OpenSDN project
4 : */
5 :
6 : #include <sys/types.h>
7 : #include <net/ethernet.h>
8 : #include <boost/asio.hpp>
9 : #include <boost/bind/bind.hpp>
10 :
11 : #include <base/logging.h>
12 : #include <db/db_entry.h>
13 : #include <db/db_table.h>
14 : #include <db/db_table_partition.h>
15 : #include <ksync/ksync_index.h>
16 : #include <ksync/ksync_entry.h>
17 : #include <ksync/ksync_object.h>
18 : #include <ksync/ksync_netlink.h>
19 : #include <ksync/ksync_sock.h>
20 :
21 : #include "oper/interface_common.h"
22 : #include "oper/nexthop.h"
23 : #include "oper/mirror_table.h"
24 : #include "oper/tunnel_nh.h"
25 : #include "vrouter/ksync/nexthop_ksync.h"
26 : #include "vrouter/ksync/ksync_init.h"
27 : #include "vr_types.h"
28 : #include "oper/ecmp_load_balance.h"
29 : #include "vrouter/ksync/agent_ksync_types.h"
30 : #include <vrouter/ksync/ksync_agent_sandesh.h>
31 :
32 : using namespace boost::placeholders;
33 :
34 1652 : NHKSyncEntry::NHKSyncEntry(NHKSyncObject *obj, const NHKSyncEntry *entry,
35 1652 : uint32_t index) :
36 1652 : KSyncNetlinkDBEntry(index), ksync_obj_(obj), type_(entry->type_),
37 1652 : vrf_id_(entry->vrf_id_), label_(entry->label_),
38 1652 : interface_(entry->interface_), sip_(entry->sip_), dip_(entry->dip_),
39 1652 : sport_(entry->sport_), dport_(entry->dport_), smac_(entry->smac_),
40 1652 : dmac_(entry->dmac_), rewrite_dmac_(entry->rewrite_dmac_),
41 1652 : valid_(entry->valid_), policy_(entry->policy_),
42 1652 : is_mcast_nh_(entry->is_mcast_nh_),
43 1652 : defer_(entry->defer_), component_nh_list_(entry->component_nh_list_),
44 1652 : nh_(entry->nh_), vlan_tag_(entry->vlan_tag_),
45 1652 : is_local_ecmp_nh_(entry->is_local_ecmp_nh_),
46 1652 : is_bridge_(entry->is_bridge_),
47 1652 : is_vxlan_routing_(entry->is_vxlan_routing_),
48 1652 : comp_type_(entry->comp_type_),
49 1652 : validate_mcast_src_(entry->validate_mcast_src_),
50 1652 : tunnel_type_(entry->tunnel_type_), prefix_len_(entry->prefix_len_),
51 1652 : nh_id_(entry->nh_id()),
52 1652 : component_nh_key_list_(entry->component_nh_key_list_),
53 1652 : bridge_nh_(entry->bridge_nh_),
54 1652 : flood_unknown_unicast_(entry->flood_unknown_unicast_),
55 1652 : ecmp_hash_fieds_(entry->ecmp_hash_fieds_.HashFieldsToUse()),
56 1652 : pbb_child_nh_(entry->pbb_child_nh_), isid_(entry->isid_),
57 1652 : pbb_label_(entry->pbb_label_), learning_enabled_(entry->learning_enabled_),
58 1652 : need_pbb_tunnel_(entry->need_pbb_tunnel_), etree_leaf_(entry->etree_leaf_),
59 1652 : layer2_control_word_(entry->layer2_control_word_),
60 1652 : crypt_(entry->crypt_), crypt_path_available_(entry->crypt_path_available_),
61 1652 : crypt_interface_(entry->crypt_interface_),
62 1652 : transport_tunnel_type_(entry->transport_tunnel_type_),
63 1652 : interface_list_(entry->interface_list_),
64 1652 : encap_valid_list_(entry->encap_valid_list_),
65 3304 : dmac_list_(entry->dmac_list_) {
66 1652 : }
67 :
68 16436 : NHKSyncEntry::NHKSyncEntry(NHKSyncObject *obj, const NextHop *nh) :
69 32872 : KSyncNetlinkDBEntry(kInvalidIndex), ksync_obj_(obj), type_(nh->GetType()),
70 49308 : vrf_id_(0), interface_(NULL), dmac_(), valid_(nh->IsValid()),
71 16436 : policy_(nh->PolicyEnabled()), is_mcast_nh_(false), nh_(nh),
72 16436 : vlan_tag_(VmInterface::kInvalidVlanId), is_bridge_(false),
73 16436 : is_vxlan_routing_(false),
74 16436 : tunnel_type_(TunnelType::INVALID), prefix_len_(32), nh_id_(nh->id()),
75 16436 : bridge_nh_(false), flood_unknown_unicast_(false),
76 16436 : learning_enabled_(nh->learning_enabled()), need_pbb_tunnel_(false),
77 16436 : etree_leaf_ (false), layer2_control_word_(false),
78 16436 : crypt_(false), crypt_path_available_(false), crypt_interface_(NULL),
79 98616 : interface_list_(), encap_valid_list_(), dmac_list_() {
80 :
81 16436 : switch (type_) {
82 20 : case NextHop::ARP: {
83 20 : const ArpNH *arp = static_cast<const ArpNH *>(nh);
84 20 : vrf_id_ = arp->vrf_id();
85 20 : sip_ = *(arp->GetIp());
86 20 : break;
87 : }
88 :
89 0 : case NextHop::NDP: {
90 0 : const NdpNH *ndp = static_cast<const NdpNH *>(nh);
91 0 : vrf_id_ = ndp->vrf_id();
92 0 : sip_ = *(ndp->GetIp());
93 0 : break;
94 : }
95 :
96 11332 : case NextHop::INTERFACE: {
97 : InterfaceKSyncObject *interface_object =
98 11332 : ksync_obj_->ksync()->interface_ksync_obj();
99 11332 : const InterfaceNH *if_nh = static_cast<const InterfaceNH *>(nh);
100 11332 : InterfaceKSyncEntry if_ksync(interface_object, if_nh->GetInterface());
101 11332 : interface_ = interface_object->GetReference(&if_ksync);
102 11332 : assert(interface_);
103 11332 : is_mcast_nh_ = if_nh->is_multicastNH();
104 11332 : is_bridge_ = if_nh->IsBridge();
105 11332 : is_vxlan_routing_ = if_nh->IsVxlanRouting();
106 11332 : const VrfEntry * vrf = if_nh->GetVrf();
107 11332 : vrf_id_ = (vrf != NULL) ? vrf->vrf_id() : VrfEntry::kInvalidIndex;
108 11332 : dmac_ = if_nh->GetDMac();
109 : // VmInterface can potentially have vlan-tags. Get tag in such case
110 11332 : if (if_nh->GetInterface()->type() == Interface::VM_INTERFACE) {
111 10544 : vlan_tag_ = (static_cast<const VmInterface *>
112 10544 : (if_nh->GetInterface()))->tx_vlan_id();
113 : }
114 11332 : break;
115 11332 : }
116 :
117 0 : case NextHop::VLAN: {
118 : InterfaceKSyncObject *interface_object =
119 0 : ksync_obj_->ksync()->interface_ksync_obj();
120 0 : const VlanNH *vlan_nh = static_cast<const VlanNH *>(nh);
121 0 : InterfaceKSyncEntry if_ksync(interface_object, vlan_nh->GetInterface());
122 0 : interface_ = interface_object->GetReference(&if_ksync);
123 0 : assert(interface_);
124 0 : vlan_tag_ = vlan_nh->GetVlanTag();
125 0 : vrf_id_ = vlan_nh->GetVrf()->vrf_id();
126 0 : break;
127 0 : }
128 :
129 215 : case NextHop::TUNNEL: {
130 215 : const TunnelNH *tunnel = static_cast<const TunnelNH *>(nh);
131 215 : vrf_id_ = tunnel->vrf_id();
132 215 : sip_ = *(tunnel->GetSip());
133 215 : dip_ = *(tunnel->GetDip());
134 215 : tunnel_type_ = tunnel->GetTunnelType();
135 215 : crypt_ = tunnel->GetCrypt();
136 215 : crypt_path_available_ = tunnel->GetCryptTunnelAvailable();
137 :
138 215 : if (tunnel->GetCryptInterface()) {
139 : InterfaceKSyncObject *crypt_interface_object =
140 0 : ksync_obj_->ksync()->interface_ksync_obj();
141 0 : InterfaceKSyncEntry if_ksync(crypt_interface_object, tunnel->GetCryptInterface());
142 0 : crypt_interface_ = crypt_interface_object->GetReference(&if_ksync);
143 0 : }
144 215 : rewrite_dmac_ = tunnel->rewrite_dmac();
145 215 : if (tunnel_type_.GetType() == TunnelType::MPLS_OVER_MPLS) {
146 0 : const LabelledTunnelNH *labelled_tunnel =
147 : static_cast<const LabelledTunnelNH *>(nh);
148 0 : label_ = labelled_tunnel->GetTransportLabel();
149 0 : transport_tunnel_type_ =
150 0 : labelled_tunnel->GetTransportTunnelType();
151 : }
152 215 : break;
153 : }
154 :
155 462 : case NextHop::DISCARD: {
156 462 : break;
157 : }
158 :
159 340 : case NextHop::L2_RECEIVE: {
160 340 : break;
161 : }
162 :
163 6 : case NextHop::RESOLVE: {
164 : InterfaceKSyncObject *interface_object =
165 6 : ksync_obj_->ksync()->interface_ksync_obj();
166 6 : const ResolveNH *rsl_nh = static_cast<const ResolveNH *>(nh);
167 6 : InterfaceKSyncEntry if_ksync(interface_object, rsl_nh->get_interface());
168 6 : interface_ = interface_object->GetReference(&if_ksync);
169 6 : vrf_id_ = rsl_nh->get_interface()->vrf_id();
170 6 : if (rsl_nh->get_interface()->type() == Interface::VM_INTERFACE) {
171 : const VmInterface *vm_intf =
172 6 : static_cast<const VmInterface *>(rsl_nh->get_interface());
173 6 : if (vm_intf->vrf()->forwarding_vrf()) {
174 6 : vrf_id_ = vm_intf->vrf()->forwarding_vrf()->vrf_id();
175 : }
176 : }
177 6 : break;
178 6 : }
179 :
180 199 : case NextHop::VRF: {
181 199 : const VrfNH *vrf_nh = static_cast<const VrfNH *>(nh);
182 199 : vrf_id_ = vrf_nh->GetVrf()->vrf_id();
183 199 : bridge_nh_ = vrf_nh->bridge_nh();
184 199 : break;
185 : }
186 :
187 20 : case NextHop::RECEIVE: {
188 : InterfaceKSyncObject *interface_object =
189 20 : ksync_obj_->ksync()->interface_ksync_obj();
190 20 : const ReceiveNH *rcv_nh = static_cast<const ReceiveNH *>(nh);
191 20 : InterfaceKSyncEntry if_ksync(interface_object, rcv_nh->GetInterface());
192 20 : interface_ = interface_object->GetReference(&if_ksync);
193 20 : vrf_id_ = rcv_nh->GetInterface()->vrf_id();
194 20 : assert(interface_);
195 20 : break;
196 20 : }
197 :
198 0 : case NextHop::MIRROR: {
199 0 : const MirrorNH *mirror_nh = static_cast<const MirrorNH *>(nh);
200 0 : vrf_id_ = mirror_nh->vrf_id();
201 0 : sip_ = *(mirror_nh->GetSip());
202 0 : sport_ = mirror_nh->GetSPort();
203 0 : dip_ = *(mirror_nh->GetDip());
204 0 : dport_ = mirror_nh->GetDPort();
205 0 : break;
206 : }
207 :
208 0 : case NextHop::PBB: {
209 0 : const PBBNH *pbb_nh = static_cast<const PBBNH *>(nh);
210 0 : vrf_id_ = pbb_nh->vrf_id();
211 0 : dmac_ = pbb_nh->dest_bmac();
212 0 : isid_ = pbb_nh->isid();
213 0 : break;
214 : }
215 :
216 3842 : case NextHop::COMPOSITE: {
217 3842 : const CompositeNH *comp_nh = static_cast<const CompositeNH *>(nh);
218 3842 : component_nh_list_.clear();
219 3842 : vrf_id_ = comp_nh->vrf()->vrf_id();
220 3842 : comp_type_ = comp_nh->composite_nh_type();
221 3842 : validate_mcast_src_ = comp_nh->validate_mcast_src();
222 3842 : ecmp_hash_fieds_ =
223 3842 : const_cast<CompositeNH *>(comp_nh)->CompEcmpHashFields().HashFieldsToUse();
224 3842 : component_nh_key_list_ = comp_nh->component_nh_key_list();
225 : ComponentNHList::const_iterator component_nh_it =
226 3842 : comp_nh->begin();
227 10879 : while (component_nh_it != comp_nh->end()) {
228 7037 : const NextHop *component_nh = NULL;
229 7037 : uint32_t label = 0;
230 7037 : if (*component_nh_it) {
231 6950 : component_nh = (*component_nh_it)->nh();
232 6950 : label = (*component_nh_it)->label();
233 : }
234 7037 : KSyncEntry *ksync_nh = NULL;
235 7037 : if (component_nh != NULL) {
236 : NHKSyncObject *nh_object =
237 6950 : ksync_obj_->ksync()->nh_ksync_obj();
238 6950 : NHKSyncEntry nhksync(nh_object, component_nh);
239 6950 : ksync_nh = nh_object->GetReference(&nhksync);
240 6950 : }
241 7037 : KSyncComponentNH ksync_component_nh(label, ksync_nh);
242 7037 : component_nh_list_.push_back(ksync_component_nh);
243 7037 : component_nh_it++;
244 7037 : }
245 3842 : break;
246 : }
247 :
248 0 : default:
249 0 : assert(0);
250 : break;
251 : }
252 16436 : }
253 :
254 21390 : NHKSyncEntry::~NHKSyncEntry() {
255 21390 : }
256 :
257 23942 : KSyncDBObject *NHKSyncEntry::GetObject() const {
258 23942 : return ksync_obj_;
259 : }
260 :
261 148704 : bool NHKSyncEntry::IsLess(const KSyncEntry &rhs) const {
262 148704 : const NHKSyncEntry &entry = static_cast<const NHKSyncEntry &>(rhs);
263 :
264 148704 : if (type_ != entry.type_) {
265 23051 : return type_ < entry.type_;
266 : }
267 :
268 125653 : if (type_ == NextHop::DISCARD) {
269 924 : return false;
270 : }
271 :
272 124729 : if (type_ == NextHop::L2_RECEIVE) {
273 680 : return false;
274 : }
275 :
276 124049 : if (type_ == NextHop::ARP || type_ == NextHop::NDP) {
277 : //Policy is ignored for ARP NH
278 40 : if (vrf_id_ != entry.vrf_id_) {
279 0 : return vrf_id_ < entry.vrf_id_;
280 : }
281 40 : return sip_ < entry.sip_;
282 : }
283 :
284 124009 : if (policy_ != entry.policy_) {
285 15784 : return policy_ < entry.policy_;
286 : }
287 :
288 108225 : if (type_ == NextHop::VRF) {
289 818 : if ( vrf_id_ != entry.vrf_id_) {
290 420 : return vrf_id_ < entry.vrf_id_;
291 : }
292 398 : return bridge_nh_ < entry.bridge_nh_;
293 : }
294 :
295 107407 : if (type_ == NextHop::INTERFACE) {
296 81774 : if (is_mcast_nh_ != entry.is_mcast_nh_) {
297 6379 : return is_mcast_nh_ < entry.is_mcast_nh_;
298 : }
299 75395 : if(is_bridge_ != entry.is_bridge_) {
300 9442 : return is_bridge_ < entry.is_bridge_;
301 : }
302 :
303 65953 : if(is_vxlan_routing_ != entry.is_vxlan_routing_) {
304 0 : return is_vxlan_routing_ < entry.is_vxlan_routing_;
305 : }
306 :
307 65953 : if (dmac_ != entry.dmac_) {
308 26128 : return dmac_ < entry.dmac_;
309 : }
310 :
311 39825 : return interface() < entry.interface();
312 : }
313 :
314 25633 : if (type_ == NextHop::RECEIVE || type_ == NextHop::RESOLVE) {
315 52 : return interface() < entry.interface();
316 : }
317 :
318 :
319 25581 : if (type_ == NextHop::TUNNEL) {
320 736 : if (vrf_id_ != entry.vrf_id_) {
321 0 : return vrf_id_ < entry.vrf_id_;
322 : }
323 :
324 736 : if (sip_ != entry.sip_) {
325 0 : return sip_ < entry.sip_;
326 : }
327 :
328 736 : if (dip_ != entry.dip_) {
329 290 : return dip_ < entry.dip_;
330 : }
331 :
332 446 : if (crypt_ != entry.crypt_) {
333 0 : return crypt_ < entry.crypt_;
334 : }
335 :
336 446 : if (crypt_path_available_ != entry.crypt_path_available_) {
337 0 : return crypt_path_available_ < entry.crypt_path_available_;
338 : }
339 :
340 446 : if (crypt_interface() != entry.crypt_interface()) {
341 0 : return crypt_interface() < entry.crypt_interface();
342 : }
343 :
344 446 : if (rewrite_dmac_ != entry.rewrite_dmac_) {
345 0 : return rewrite_dmac_ < entry.rewrite_dmac_;
346 : }
347 446 : if (tunnel_type_.Compare(entry.tunnel_type_) == false) {
348 16 : return tunnel_type_.IsLess(entry.tunnel_type_);
349 : }
350 430 : if (tunnel_type_.GetType() == TunnelType::MPLS_OVER_MPLS) {
351 0 : return label_ < entry.label_;
352 : }
353 : }
354 :
355 25275 : if (type_ == NextHop::MIRROR) {
356 0 : if (vrf_id_ != entry.vrf_id_) {
357 0 : return vrf_id_ < entry.vrf_id_;
358 : }
359 :
360 0 : if (dip_ != entry.dip_) {
361 0 : return dip_ < entry.dip_;
362 : }
363 :
364 0 : return dport_ < entry.dport_;
365 : }
366 :
367 25275 : if (type_ == NextHop::PBB) {
368 0 : if (vrf_id_ != entry.vrf_id_) {
369 0 : return vrf_id_ < entry.vrf_id_;
370 : }
371 :
372 0 : if (dmac_ != entry.dmac_) {
373 0 : return dmac_ < entry.dmac_;
374 : }
375 :
376 0 : return isid_ < entry.isid_;
377 : }
378 :
379 25275 : if (type_ == NextHop::COMPOSITE) {
380 24845 : if (comp_type_ != entry.comp_type_) {
381 5877 : return comp_type_ < entry.comp_type_;
382 : }
383 :
384 18968 : if (vrf_id_ != entry.vrf_id_) {
385 5973 : return vrf_id_ < entry.vrf_id_;
386 : }
387 :
388 : ComponentNHKeyList::const_iterator it =
389 12995 : component_nh_key_list_.begin();
390 : ComponentNHKeyList::const_iterator entry_it =
391 12995 : entry.component_nh_key_list_.begin();
392 48246 : for (;it != component_nh_key_list_.end() &&
393 64373 : entry_it != entry.component_nh_key_list_.end(); it++, entry_it++) {
394 18819 : if (*it == NULL &&
395 234 : *entry_it == NULL) {
396 178 : continue;
397 : }
398 : //One of the component NH is NULL
399 36758 : if ((*it) == NULL ||
400 18351 : (*entry_it) == NULL) {
401 146 : return (*it) < (*entry_it);
402 : }
403 :
404 : //Check if the label is different
405 36522 : if ((*it)->label() !=
406 18261 : (*entry_it)->label()) {
407 9 : return (*it)->label() <
408 9 : (*entry_it)->label();
409 : }
410 :
411 : //Check if the nexthop key is different
412 : //Ideally we could find the nexthop and compare pointer alone
413 : //it wont work because this is called from Find context itself,
414 : //and it would result in deadlock
415 : //Hence compare nexthop key alone
416 18252 : const NextHopKey *left_nh = (*it)->nh_key();
417 18252 : const NextHopKey *right_nh = (*entry_it)->nh_key();
418 :
419 18252 : if (left_nh->IsEqual(*right_nh) == false) {
420 2303 : if (left_nh->GetType() != right_nh->GetType()) {
421 0 : return left_nh->GetType() < right_nh->GetType();
422 : }
423 2303 : return left_nh->IsLess(*right_nh);
424 : }
425 :
426 : }
427 :
428 20535 : if (it == component_nh_key_list_.end() &&
429 20535 : entry_it == entry.component_nh_key_list_.end()) {
430 7684 : return false;
431 : }
432 :
433 2853 : if (it == component_nh_key_list_.end()) {
434 2314 : return true;
435 : }
436 539 : return false;
437 : }
438 :
439 430 : if (type_ == NextHop::VLAN) {
440 0 : if (interface() != entry.interface()) {
441 0 : return interface() < entry.interface();
442 :
443 : }
444 :
445 0 : return vlan_tag_ < entry.vlan_tag_;
446 : }
447 :
448 430 : return false;
449 :
450 : assert(0);
451 : }
452 :
453 44407 : std::string NHKSyncEntry::ToString() const {
454 44407 : std::stringstream s;
455 44407 : s << "NextHop Index: " << nh_id() << " Type: ";
456 44407 : switch(type_) {
457 794 : case NextHop::DISCARD: {
458 794 : s << "Discard";
459 794 : break;
460 : }
461 744 : case NextHop::L2_RECEIVE: {
462 744 : s << "L2-Receive ";
463 744 : break;
464 : }
465 60 : case NextHop::RECEIVE: {
466 60 : s << "Receive ";
467 60 : break;
468 : }
469 16 : case NextHop::RESOLVE: {
470 16 : s << "Resolve ";
471 16 : break;
472 : }
473 189 : case NextHop::ARP: {
474 189 : s << "ARP ";
475 189 : break;
476 : }
477 0 : case NextHop::NDP: {
478 0 : s << "NDP ";
479 0 : break;
480 : }
481 928 : case NextHop::VRF: {
482 928 : s << "VRF assign to ";
483 : const VrfEntry* vrf =
484 928 : ksync_obj_->ksync()->agent()->vrf_table()->
485 928 : FindVrfFromId(vrf_id_);
486 928 : if (vrf) {
487 508 : s << vrf->GetName() << " ";
488 : } else {
489 420 : s << "Invalid ";
490 : }
491 928 : break;
492 : }
493 29463 : case NextHop::INTERFACE: {
494 29463 : s << "Interface ";
495 29463 : break;
496 : }
497 749 : case NextHop::TUNNEL: {
498 749 : s << "Tunnel to ";
499 749 : s << dip_.to_string();
500 749 : s << "rewrite_dmac";
501 749 : s << rewrite_dmac_.ToString();
502 749 : break;
503 : }
504 0 : case NextHop::MIRROR: {
505 0 : s << "Mirror to ";
506 0 : s << dip_.to_string() << ": " << dport_;
507 0 : break;
508 : }
509 0 : case NextHop::VLAN: {
510 0 : s << "VLAN interface ";
511 0 : break;
512 : }
513 11464 : case NextHop::COMPOSITE: {
514 11464 : s << "Composite Child members: ";
515 11464 : if (component_nh_list_.size() == 0) {
516 704 : s << "Empty ";
517 : }
518 11464 : for (KSyncComponentNHList::const_iterator it = component_nh_list_.begin();
519 30713 : it != component_nh_list_.end(); it++) {
520 19249 : KSyncComponentNH component_nh = *it;
521 19249 : if (component_nh.nh()) {
522 18967 : s << component_nh.nh()->ToString();
523 : }
524 19249 : }
525 11464 : break;
526 : }
527 0 : case NextHop::INVALID: {
528 0 : s << "Invalid ";
529 : }
530 :
531 0 : case NextHop::PBB: {
532 0 : s << "PBB";
533 0 : break;
534 : }
535 : }
536 :
537 44407 : if (interface_) {
538 29539 : s << "<" << interface_->ToString() << ">";
539 : }
540 88814 : return s.str();
541 44407 : }
542 :
543 1769 : bool NHKSyncEntry::Sync(DBEntry *e) {
544 1769 : bool ret = false;
545 1769 : const NextHop *nh = static_cast<NextHop *>(e);
546 :
547 1769 : if (valid_ != nh->IsValid()) {
548 0 : valid_ = nh->IsValid();
549 0 : ret = true;
550 : }
551 :
552 1769 : if (learning_enabled_ != nh->learning_enabled()) {
553 0 : learning_enabled_ = nh->learning_enabled();
554 0 : ret = true;
555 : }
556 :
557 1769 : if (etree_leaf_ != nh->etree_leaf()) {
558 0 : etree_leaf_ = nh->etree_leaf();
559 0 : ret = true;
560 : }
561 :
562 1769 : switch (nh->GetType()) {
563 4 : case NextHop::ARP: {
564 : InterfaceKSyncObject *interface_object =
565 4 : ksync_obj_->ksync()->interface_ksync_obj();
566 4 : ArpNH *arp_nh = static_cast<ArpNH *>(e);
567 4 : if (dmac_ != arp_nh->GetMac()) {
568 0 : dmac_ = arp_nh->GetMac();
569 0 : ret = true;
570 : }
571 :
572 4 : if (valid_) {
573 : InterfaceKSyncEntry if_ksync(interface_object,
574 0 : arp_nh->GetInterface());
575 0 : if (interface_ != interface_object->GetReference(&if_ksync)) {
576 0 : interface_ = interface_object->GetReference(&if_ksync);
577 0 : ret = true;
578 : }
579 0 : } else {
580 4 : if (interface_ != NULL) {
581 0 : interface_ = NULL;
582 0 : dmac_.Zero();
583 0 : ret = true;
584 : }
585 : }
586 4 : break;
587 : }
588 :
589 0 : case NextHop::NDP: {
590 : InterfaceKSyncObject *interface_object =
591 0 : ksync_obj_->ksync()->interface_ksync_obj();
592 0 : NdpNH *ndp_nh = static_cast<NdpNH *>(e);
593 0 : if (dmac_ != ndp_nh->GetMac()) {
594 0 : dmac_ = ndp_nh->GetMac();
595 0 : ret = true;
596 : }
597 :
598 0 : if (valid_) {
599 : InterfaceKSyncEntry if_ksync(interface_object,
600 0 : ndp_nh->GetInterface());
601 0 : if (interface_ != interface_object->GetReference(&if_ksync)) {
602 0 : interface_ = interface_object->GetReference(&if_ksync);
603 0 : ret = true;
604 : }
605 0 : } else {
606 0 : if (interface_ != NULL) {
607 0 : interface_ = NULL;
608 0 : dmac_.Zero();
609 0 : ret = true;
610 : }
611 : }
612 0 : break;
613 : }
614 :
615 843 : case NextHop::INTERFACE: {
616 843 : InterfaceNH *intf_nh = static_cast<InterfaceNH *>(e);
617 843 : dmac_ = intf_nh->GetDMac();
618 843 : uint16_t vlan_tag = VmInterface::kInvalidVlanId;
619 843 : if (intf_nh->GetInterface()->type() == Interface::VM_INTERFACE) {
620 835 : vlan_tag = vlan_tag_;
621 835 : vlan_tag_ = (static_cast<const VmInterface *>
622 835 : (intf_nh->GetInterface()))->tx_vlan_id();
623 835 : if (vlan_tag != vlan_tag_) {
624 0 : ret = true;
625 : }
626 : }
627 843 : if (layer2_control_word_ != intf_nh->layer2_control_word()) {
628 0 : layer2_control_word_ = intf_nh->layer2_control_word();
629 0 : ret = true;
630 : }
631 :
632 843 : const VrfEntry * vrf = intf_nh->GetVrf();
633 843 : uint32_t vrf_id = (vrf != NULL)? vrf->vrf_id() :VrfEntry::kInvalidIndex;
634 843 : if (vrf_id_ != vrf_id) {
635 0 : vrf_id_ = vrf_id;
636 0 : ret = true;
637 : }
638 843 : break;
639 : }
640 :
641 2 : case NextHop::DISCARD: {
642 2 : ret = false;
643 2 : break;
644 : }
645 :
646 2 : case NextHop::L2_RECEIVE: {
647 2 : ret = false;
648 2 : break;
649 : }
650 :
651 48 : case NextHop::TUNNEL: {
652 48 : ret = true;
653 :
654 : // If the nh IDs of KSyncEntry and NextHop objects dont match, sync them
655 : // along with nh_ pointer. It can happen if the NHKSyncEntry got
656 : // created in TEMP state with previous incarnation of this Tunnel NH
657 48 : if (nh_id_ != nh->id()) {
658 0 : nh_id_ = nh->id();
659 0 : nh_ = nh;
660 0 : ret = true;
661 : }
662 :
663 : // Invalid nexthop, no valid interface or mac info
664 : // present, just return
665 48 : if (valid_ == false) {
666 48 : if (interface_ != NULL) {
667 0 : interface_ = NULL;
668 0 : dmac_.Zero();
669 0 : ret = true;
670 : }
671 48 : break;
672 : }
673 :
674 0 : KSyncEntryPtr interface = NULL;
675 0 : MacAddress dmac;
676 0 : const TunnelNH *tun_nh = static_cast<TunnelNH *>(e);
677 0 : const NextHop *active_nh = tun_nh->GetRt()->GetActiveNextHop();
678 : // active nexthop can be NULL as when arp rt is delete marked and
679 : // is enqueued for notify.
680 0 : if (active_nh == NULL) {
681 0 : if (interface_ != NULL) {
682 0 : interface_ = NULL;
683 0 : dmac_.Zero();
684 0 : ret = true;
685 : }
686 0 : break;
687 : }
688 :
689 0 : if (active_nh->GetType() == NextHop::ARP) {
690 0 : const ArpNH *arp_nh = static_cast<const ArpNH *>(active_nh);
691 : InterfaceKSyncObject *interface_object =
692 0 : ksync_obj_->ksync()->interface_ksync_obj();
693 0 : InterfaceKSyncEntry if_ksync(interface_object, arp_nh->GetInterface());
694 0 : interface = interface_object->GetReference(&if_ksync);
695 0 : dmac = arp_nh->GetMac();
696 0 : } else if (active_nh->GetType() == NextHop::NDP) {
697 0 : const NdpNH *ndp_nh = static_cast<const NdpNH *>(active_nh);
698 : InterfaceKSyncObject *interface_object =
699 0 : ksync_obj_->ksync()->interface_ksync_obj();
700 0 : InterfaceKSyncEntry if_ksync(interface_object, ndp_nh->GetInterface());
701 0 : interface = interface_object->GetReference(&if_ksync);
702 0 : dmac = ndp_nh->GetMac();
703 0 : } else if (active_nh->GetType() == NextHop::INTERFACE) {
704 0 : const InterfaceNH *intf_nh =
705 : static_cast<const InterfaceNH *>(active_nh);
706 0 : const Interface *oper_intf = intf_nh->GetInterface();
707 : InterfaceKSyncObject *interface_object =
708 0 : ksync_obj_->ksync()->interface_ksync_obj();
709 0 : InterfaceKSyncEntry if_ksync(interface_object, oper_intf);
710 0 : interface = interface_object->GetReference(&if_ksync);
711 0 : dmac = oper_intf->mac();
712 0 : } else if (active_nh->GetType() == NextHop::COMPOSITE) {
713 0 : const CompositeNH *cnh =
714 : static_cast<const CompositeNH *>(active_nh);
715 0 : interface_list_.clear();
716 0 : encap_valid_list_.clear();
717 0 : dmac_list_.clear();
718 : ComponentNHList::const_iterator component_nh_it =
719 0 : cnh->begin();
720 0 : while (component_nh_it != cnh->end()) {
721 0 : const NextHop *component_nh = NULL;
722 0 : if (*component_nh_it) {
723 0 : component_nh = (*component_nh_it)->nh();
724 0 : if (component_nh->GetType() == NextHop::ARP) {
725 0 : const ArpNH *arp_nh = dynamic_cast<const ArpNH*>(component_nh);
726 : InterfaceKSyncObject *interface_object =
727 0 : ksync_obj_->ksync()->interface_ksync_obj();
728 0 : InterfaceKSyncEntry if_ksync(interface_object, arp_nh->GetInterface());
729 0 : interface_list_.push_back(interface_object->GetReference(&if_ksync));
730 0 : encap_valid_list_.push_back(arp_nh->IsValid());
731 0 : dmac_list_.push_back(arp_nh->GetMac());
732 0 : }
733 : }
734 0 : component_nh_it++;
735 : }
736 :
737 : /* vRouter expects encap_valid vector should always be size = 3.
738 : * It helps in accessing valid enacp_data and oif */
739 0 : while (encap_valid_list_.size() < MAX_VR_PHY_INTF) {
740 0 : encap_valid_list_.push_back(false);
741 : }
742 : }
743 :
744 0 : bool crypt = tun_nh->GetCrypt();
745 0 : if (crypt != crypt_) {
746 0 : crypt_ = crypt;
747 0 : ret = true;
748 : }
749 :
750 0 : bool crypt_path_available = tun_nh->GetCryptTunnelAvailable();
751 0 : if (crypt_path_available != crypt_path_available_) {
752 0 : crypt_path_available_ = crypt_path_available;
753 0 : ret = true;
754 : }
755 :
756 0 : const Interface *oper_crypt_intf = tun_nh->GetCryptInterface();
757 :
758 0 : if (tun_nh->GetCryptInterface()) {
759 : InterfaceKSyncObject *crypt_interface_object =
760 0 : ksync_obj_->ksync()->interface_ksync_obj();
761 0 : InterfaceKSyncEntry if_ksync(crypt_interface_object, oper_crypt_intf);
762 0 : KSyncEntryPtr crypt_interface = crypt_interface_object->GetReference(&if_ksync);
763 :
764 0 : if (crypt_interface != crypt_interface_) {
765 0 : crypt_interface_ = crypt_interface;
766 0 : ret = true;
767 : }
768 0 : }
769 0 : if (tunnel_type_.GetType() == TunnelType::MPLS_OVER_MPLS) {
770 0 : const LabelledTunnelNH *labelled_tunnel =
771 : static_cast<const LabelledTunnelNH *>(nh);
772 0 : if (label_ != labelled_tunnel->GetTransportLabel()) {
773 0 : label_ = labelled_tunnel->GetTransportLabel();
774 0 : ret = true;
775 : }
776 0 : if (transport_tunnel_type_ !=
777 0 : labelled_tunnel->GetTransportTunnelType()) {
778 0 : transport_tunnel_type_ =
779 0 : labelled_tunnel->GetTransportTunnelType();
780 0 : ret = true;
781 : }
782 : }
783 :
784 0 : if (dmac != dmac_) {
785 0 : dmac_ = dmac;
786 0 : ret = true;
787 : }
788 0 : if (interface_ != interface) {
789 0 : interface_ = interface;
790 0 : ret = true;
791 : }
792 0 : break;
793 0 : }
794 :
795 0 : case NextHop::MIRROR: {
796 0 : ret = true;
797 : // Invalid nexthop, no valid interface or mac info
798 : // present, just return
799 0 : if (valid_ == false || (vrf_id_ == (uint32_t)-1)) {
800 0 : if (interface_ != NULL) {
801 0 : interface_ = NULL;
802 0 : dmac_.Zero();
803 0 : ret = true;
804 : }
805 0 : break;
806 : }
807 :
808 0 : KSyncEntryPtr interface = NULL;
809 0 : MacAddress dmac;
810 0 : bool valid = valid_;
811 :
812 0 : const MirrorNH *mirror_nh = static_cast<MirrorNH *>(e);
813 0 : const NextHop *active_nh = mirror_nh->GetRt()->GetActiveNextHop();
814 0 : if (active_nh) {
815 0 : if (active_nh->GetType() == NextHop::ARP) {
816 0 : const ArpNH *arp_nh = static_cast<const ArpNH *>(active_nh);
817 : InterfaceKSyncObject *interface_object =
818 0 : ksync_obj_->ksync()->interface_ksync_obj();
819 : InterfaceKSyncEntry if_ksync(interface_object,
820 0 : arp_nh->GetInterface());
821 0 : interface = interface_object->GetReference(&if_ksync);
822 0 : dmac = arp_nh->GetMac();
823 0 : } else if (active_nh->GetType() == NextHop::NDP) {
824 0 : const NdpNH *ndp_nh = static_cast<const NdpNH *>(active_nh);
825 : InterfaceKSyncObject *interface_object =
826 0 : ksync_obj_->ksync()->interface_ksync_obj();
827 : InterfaceKSyncEntry if_ksync(interface_object,
828 0 : ndp_nh->GetInterface());
829 0 : interface = interface_object->GetReference(&if_ksync);
830 0 : dmac = ndp_nh->GetMac();
831 0 : } else if (active_nh->GetType() == NextHop::RECEIVE) {
832 0 : const ReceiveNH *rcv_nh = static_cast<const ReceiveNH *>(active_nh);
833 : InterfaceKSyncObject *interface_object =
834 0 : ksync_obj_->ksync()->interface_ksync_obj();
835 : InterfaceKSyncEntry if_ksync(interface_object,
836 0 : rcv_nh->GetInterface());
837 0 : interface = interface_object->GetReference(&if_ksync);
838 0 : Agent *agent = ksync_obj_->ksync()->agent();
839 0 : dmac = agent->vhost_interface()->mac();
840 0 : } else if (active_nh->GetType() == NextHop::DISCARD) {
841 0 : valid = false;
842 0 : interface = NULL;
843 : }
844 : } else {
845 0 : valid = false;
846 0 : interface = NULL;
847 : }
848 :
849 0 : if (valid_ != valid) {
850 0 : valid_ = valid;
851 0 : ret = true;
852 : }
853 0 : if (dmac_ != dmac) {
854 0 : dmac_ = dmac;
855 0 : ret = true;
856 : }
857 0 : if (interface_ != interface) {
858 0 : interface_ = interface;
859 0 : ret = true;
860 : }
861 0 : break;
862 0 : }
863 :
864 0 : case NextHop::PBB: {
865 0 : PBBNH *pbb_nh = static_cast<PBBNH *>(e);
866 0 : if (pbb_label_ != pbb_nh->label()) {
867 0 : pbb_label_ = pbb_nh->label();
868 0 : ret = true;
869 : }
870 :
871 : NHKSyncObject *nh_object =
872 0 : ksync_obj_->ksync()->nh_ksync_obj();
873 0 : NHKSyncEntry nhksync(nh_object, pbb_nh->child_nh());
874 0 : KSyncEntry *ksync_nh = nh_object->GetReference(&nhksync);
875 0 : if (ksync_nh != pbb_child_nh_) {
876 0 : pbb_child_nh_ = ksync_nh;
877 0 : ret = true;
878 : }
879 0 : break;
880 0 : }
881 :
882 798 : case NextHop::COMPOSITE: {
883 798 : ret = true;
884 798 : CompositeNH *comp_nh = static_cast<CompositeNH *>(e);
885 798 : component_nh_list_.clear();
886 : ComponentNHList::const_iterator component_nh_it =
887 798 : comp_nh->begin();
888 2199 : while (component_nh_it != comp_nh->end()) {
889 1401 : const NextHop *component_nh = NULL;
890 1401 : uint32_t label = 0;
891 1401 : if (*component_nh_it) {
892 1380 : component_nh = (*component_nh_it)->nh();
893 1380 : label = (*component_nh_it)->label();
894 : }
895 1401 : KSyncEntry *ksync_nh = NULL;
896 1401 : if (component_nh != NULL) {
897 : NHKSyncObject *nh_object =
898 1380 : ksync_obj_->ksync()->nh_ksync_obj();
899 1380 : NHKSyncEntry nhksync(nh_object, component_nh);
900 1380 : ksync_nh = nh_object->GetReference(&nhksync);
901 1380 : }
902 1401 : KSyncComponentNH ksync_component_nh(label, ksync_nh);
903 1401 : component_nh_list_.push_back(ksync_component_nh);
904 1401 : component_nh_it++;
905 1401 : }
906 :
907 798 : if (comp_nh->EcmpHashFieldInUse() != ecmp_hash_fieds_.HashFieldsToUse()) {
908 0 : ecmp_hash_fieds_ = comp_nh->CompEcmpHashFields().HashFieldsToUse();
909 0 : ret = true;
910 : }
911 :
912 798 : if (need_pbb_tunnel_ != comp_nh->pbb_nh()) {
913 0 : need_pbb_tunnel_ = comp_nh->pbb_nh();
914 0 : ret = true;
915 : }
916 :
917 798 : if (layer2_control_word_ != comp_nh->layer2_control_word()) {
918 0 : layer2_control_word_ = comp_nh->layer2_control_word();
919 0 : ret = true;
920 : }
921 798 : break;
922 : }
923 :
924 0 : case NextHop::VLAN: {
925 0 : VlanNH *vlan_nh = static_cast<VlanNH *>(e);
926 0 : smac_ = vlan_nh->GetSMac();
927 0 : dmac_ = vlan_nh->GetDMac();
928 0 : ret = false;
929 0 : break;
930 : }
931 :
932 66 : case NextHop::VRF: {
933 66 : VrfNH *vrf_nh = static_cast<VrfNH *>(e);
934 66 : vrf_id_ = vrf_nh->GetVrf()->vrf_id();
935 66 : ret = false;
936 66 : if (bridge_nh_ != vrf_nh->bridge_nh()) {
937 0 : bridge_nh_ = vrf_nh->bridge_nh();
938 0 : ret = true;
939 : }
940 :
941 66 : if (flood_unknown_unicast_ != vrf_nh->flood_unknown_unicast()) {
942 0 : flood_unknown_unicast_ = vrf_nh->flood_unknown_unicast();
943 0 : ret = true;
944 : }
945 :
946 66 : if (layer2_control_word_ != vrf_nh->layer2_control_word()) {
947 0 : layer2_control_word_ = vrf_nh->layer2_control_word();
948 0 : ret = true;
949 : }
950 66 : break;
951 : }
952 6 : case NextHop::RECEIVE:
953 : case NextHop::RESOLVE: {
954 6 : valid_ = true;
955 6 : ret = true;
956 6 : break;
957 : }
958 :
959 0 : default:
960 0 : assert(0);
961 : }
962 :
963 1769 : return ret;
964 : };
965 3415 : int NHKSyncEntry::Encode(sandesh_op::type op, char *buf, int buf_len) {
966 3415 : vr_nexthop_req encoder;
967 : int encode_len;
968 3415 : uint32_t crypt_intf_id = kInvalidIndex;
969 3415 : uint32_t intf_id = kInvalidIndex;
970 3415 : std::vector<int8_t> encap;
971 3415 : InterfaceKSyncEntry *if_ksync = NULL;
972 3415 : InterfaceKSyncEntry *crypt_if_ksync = NULL;
973 3415 : std::vector<KSyncEntryPtr> if_ksync_list;
974 3415 : std::vector<int32_t> nhr_encap_valid_list;
975 3415 : std::vector<int32_t> intf_id_list;
976 3415 : Agent *agent = ksync_obj_->ksync()->agent();
977 :
978 3415 : encoder.set_h_op(op);
979 3415 : encoder.set_nhr_id(nh_id());
980 3415 : if (op == sandesh_op::DEL) {
981 : /* For delete only NH-index is required by vrouter */
982 1650 : int error = 0;
983 1650 : encode_len = encoder.WriteBinary((uint8_t *)buf, buf_len, &error);
984 1650 : assert(error == 0);
985 1650 : assert(encode_len <= buf_len);
986 1650 : return encode_len;
987 : }
988 1765 : encoder.set_nhr_rid(0);
989 1765 : encoder.set_nhr_vrf(vrf_id_);
990 1765 : encoder.set_nhr_family(AF_INET);
991 1765 : uint32_t flags = 0;
992 1765 : if (valid_) {
993 1715 : flags |= NH_FLAG_VALID;
994 : }
995 :
996 1765 : if (policy_) {
997 527 : flags |= NH_FLAG_POLICY_ENABLED;
998 : }
999 :
1000 1765 : if (etree_leaf_ == false) {
1001 1765 : flags |= NH_FLAG_ETREE_ROOT;
1002 : }
1003 :
1004 1765 : if (learning_enabled_) {
1005 0 : flags |= NH_FLAG_MAC_LEARN;
1006 : }
1007 :
1008 1765 : if (layer2_control_word_) {
1009 0 : flags |= NH_FLAG_L2_CONTROL_DATA;
1010 : }
1011 :
1012 1765 : if (crypt_) {
1013 0 : flags |= NH_FLAG_CRYPT_TRAFFIC;
1014 : }
1015 :
1016 1765 : if_ksync = interface();
1017 1765 : if_ksync_list = interface_list();
1018 1765 : nhr_encap_valid_list = encap_valid_list();
1019 1765 : crypt_if_ksync = crypt_interface();
1020 :
1021 1765 : switch (type_) {
1022 845 : case NextHop::VLAN:
1023 : case NextHop::ARP:
1024 : case NextHop::NDP:
1025 : case NextHop::INTERFACE :
1026 845 : encoder.set_nhr_type(NH_ENCAP);
1027 845 : if (if_ksync) {
1028 843 : intf_id = if_ksync->interface_id();
1029 : }
1030 845 : encoder.set_nhr_encap_oif_id(std::vector<int32_t>(1, intf_id));
1031 845 : encoder.set_nhr_encap_family(ETHERTYPE_ARP);
1032 :
1033 845 : SetEncap(if_ksync, encap);
1034 845 : encoder.set_nhr_encap(encap);
1035 845 : encoder.set_nhr_tun_sip(0);
1036 845 : encoder.set_nhr_tun_dip(0);
1037 845 : if (is_vxlan_routing_) {
1038 : //Set vxlan routing flag
1039 0 : flags |= NH_FLAG_L3_VXLAN;
1040 : }
1041 845 : if (is_bridge_) {
1042 334 : encoder.set_nhr_family(AF_BRIDGE);
1043 : }
1044 845 : if (is_mcast_nh_) {
1045 167 : flags |= NH_FLAG_MCAST;
1046 : }
1047 845 : encoder.set_nhr_flags(flags);
1048 845 : break;
1049 :
1050 48 : case NextHop::TUNNEL : {
1051 48 : encoder.set_nhr_type(NH_TUNNEL);
1052 48 : encoder.set_nhr_tun_sip(htonl(sip_.to_v4().to_ulong()));
1053 48 : encoder.set_nhr_tun_dip(htonl(dip_.to_v4().to_ulong()));
1054 48 : encoder.set_nhr_encap_family(ETHERTYPE_ARP);
1055 :
1056 48 : if (if_ksync_list.empty() == false) {
1057 0 : flags |= NH_FLAG_TUNNEL_UNDERLAY_ECMP;
1058 0 : uint32_t encap_len = 0;
1059 0 : for (size_t i = 0; i < if_ksync_list.size(); ++i) {
1060 : InterfaceKSyncEntry *if_ksync_entry =
1061 0 : static_cast<InterfaceKSyncEntry *>(if_ksync_list[i].get());
1062 0 : intf_id_list.push_back(if_ksync_entry->interface_id());
1063 0 : encap_len = encap.size();
1064 0 : SetEncap(if_ksync_entry, encap, i);
1065 0 : encap_len = encap.size() - encap_len;
1066 : }
1067 0 : encoder.set_nhr_encap_len(encap_len);
1068 : } else {
1069 48 : SetEncap(if_ksync, encap);
1070 48 : intf_id_list.push_back(0);
1071 : }
1072 48 : encoder.set_nhr_encap_oif_id(intf_id_list);
1073 48 : encoder.set_nhr_encap_valid(nhr_encap_valid_list);
1074 48 : encoder.set_nhr_crypt_traffic(crypt_);
1075 48 : encoder.set_nhr_crypt_path_available(crypt_path_available_);
1076 48 : if (crypt_if_ksync && crypt_path_available_) {
1077 0 : crypt_intf_id = crypt_if_ksync->interface_id();
1078 : }
1079 48 : encoder.set_nhr_encap_crypt_oif_id(crypt_intf_id);
1080 48 : encoder.set_nhr_encap(encap);
1081 48 : if (tunnel_type_.GetType() == TunnelType::MPLS_UDP) {
1082 0 : flags |= NH_FLAG_TUNNEL_UDP_MPLS;
1083 48 : } else if (tunnel_type_.GetType() == TunnelType::MPLS_GRE) {
1084 43 : flags |= NH_FLAG_TUNNEL_GRE;
1085 5 : } else if (tunnel_type_.GetType() == TunnelType::NATIVE) {
1086 : //Ideally we should have created a new type of
1087 : //indirect nexthop to handle NATIVE encap
1088 : //reusing tunnel NH as it provides most of
1089 : //functionality now
1090 0 : encoder.set_nhr_type(NH_ENCAP);
1091 0 : encoder.set_nhr_encap_oif_id(intf_id_list);
1092 0 : encoder.set_nhr_encap_family(ETHERTYPE_ARP);
1093 0 : encoder.set_nhr_tun_sip(0);
1094 0 : encoder.set_nhr_tun_dip(0);
1095 5 : } else if (tunnel_type_.GetType() == TunnelType::MPLS_OVER_MPLS) {
1096 0 : flags |= NH_FLAG_TUNNEL_MPLS_O_MPLS;
1097 0 : if (transport_tunnel_type_ == TunnelType::MPLS_UDP) {
1098 0 : flags |= NH_FLAG_TUNNEL_UDP_MPLS;
1099 : } else {
1100 0 : flags |= NH_FLAG_TUNNEL_GRE;
1101 : }
1102 :
1103 0 : encoder.set_nhr_transport_label(label_);
1104 : } else {
1105 5 : flags |= NH_FLAG_TUNNEL_VXLAN;
1106 : }
1107 48 : std::vector<int8_t> rewrite_dmac;
1108 336 : for (size_t i = 0 ; i < rewrite_dmac_.size(); i++) {
1109 288 : rewrite_dmac.push_back(rewrite_dmac_[i]);
1110 : }
1111 48 : encoder.set_nhr_rw_dst_mac(rewrite_dmac);
1112 : //TODO remove set_nhr_pbb_mac
1113 48 : encoder.set_nhr_pbb_mac(rewrite_dmac);
1114 48 : if (rewrite_dmac_.IsZero() == false) {
1115 0 : flags |= NH_FLAG_L3_VXLAN;
1116 : }
1117 48 : break;
1118 48 : }
1119 0 : case NextHop::MIRROR :
1120 0 : encoder.set_nhr_type(NH_TUNNEL);
1121 0 : if (sip_.is_v4() && dip_.is_v4()) {
1122 0 : encoder.set_nhr_tun_sip(htonl(sip_.to_v4().to_ulong()));
1123 0 : encoder.set_nhr_tun_dip(htonl(dip_.to_v4().to_ulong()));
1124 0 : } else if (sip_.is_v6() && dip_.is_v6()) {
1125 0 : encoder.set_nhr_family(AF_INET6);
1126 0 : Ip6Address::bytes_type bytes = sip_.to_v6().to_bytes();
1127 0 : std::vector<int8_t> sip_vector(bytes.begin(), bytes.end());
1128 0 : bytes = dip_.to_v6().to_bytes();
1129 0 : std::vector<int8_t> dip_vector(bytes.begin(), bytes.end());
1130 0 : encoder.set_nhr_tun_sip6(sip_vector);
1131 0 : encoder.set_nhr_tun_dip6(dip_vector);
1132 0 : }
1133 0 : encoder.set_nhr_tun_sport(htons(sport_));
1134 0 : encoder.set_nhr_tun_dport(htons(dport_));
1135 0 : encoder.set_nhr_encap_family(ETHERTYPE_ARP);
1136 :
1137 0 : if (if_ksync) {
1138 0 : intf_id = if_ksync->interface_id();
1139 : }
1140 0 : encoder.set_nhr_encap_oif_id(std::vector<int32_t>(1, intf_id));
1141 0 : SetEncap(NULL,encap);
1142 0 : encoder.set_nhr_encap(encap);
1143 0 : flags |= NH_FLAG_TUNNEL_UDP;
1144 0 : if (vrf_id_ != agent->fabric_vrf()->vrf_id()) {
1145 0 : flags |= NH_FLAG_TUNNEL_SIP_COPY;
1146 : }
1147 0 : break;
1148 :
1149 2 : case NextHop::L2_RECEIVE:
1150 2 : encoder.set_nhr_type(NH_L2_RCV);
1151 2 : break;
1152 :
1153 2 : case NextHop::DISCARD:
1154 2 : encoder.set_nhr_type(NH_DISCARD);
1155 2 : break;
1156 :
1157 4 : case NextHop::RECEIVE:
1158 4 : if (!policy_) {
1159 2 : flags |= NH_FLAG_RELAXED_POLICY;
1160 : }
1161 4 : intf_id = if_ksync->interface_id();
1162 4 : encoder.set_nhr_encap_oif_id(std::vector<int32_t>(1, intf_id));
1163 4 : encoder.set_nhr_type(NH_RCV);
1164 4 : break;
1165 :
1166 2 : case NextHop::RESOLVE:
1167 2 : if (policy_) {
1168 : //Policy bit is used in agent to copy over the
1169 : //field to ARP nexthop that gets created from
1170 : //resolve NH in case of gateway interface,
1171 : //but the same is not needed in vrouter.
1172 : //If policy bit is enabled then first packet
1173 : //resulting flow with key NH of resolve NH
1174 : //followed by next packet with ARP NH as key
1175 : //resulting in flow drops
1176 0 : flags &= ~NH_FLAG_POLICY_ENABLED;
1177 : }
1178 2 : encoder.set_nhr_type(NH_RESOLVE);
1179 2 : break;
1180 :
1181 66 : case NextHop::VRF:
1182 66 : encoder.set_nhr_type(NH_VXLAN_VRF);
1183 66 : if (bridge_nh_ == true) {
1184 66 : encoder.set_nhr_family(AF_BRIDGE);
1185 : }
1186 66 : if (flood_unknown_unicast_) {
1187 0 : flags |= NH_FLAG_UNKNOWN_UC_FLOOD;
1188 : }
1189 66 : break;
1190 :
1191 0 : case NextHop::PBB: {
1192 0 : encoder.set_nhr_family(AF_BRIDGE);
1193 0 : encoder.set_nhr_type(NH_TUNNEL);
1194 0 : flags |= (NH_FLAG_TUNNEL_PBB | NH_FLAG_INDIRECT);
1195 0 : std::vector<int8_t> bmac;
1196 0 : for (size_t i = 0 ; i < dmac_.size(); i++) {
1197 0 : bmac.push_back(dmac_[i]);
1198 : }
1199 0 : encoder.set_nhr_pbb_mac(bmac);
1200 0 : if (pbb_child_nh_.get()) {
1201 0 : std::vector<int> sub_nh_list;
1202 : NHKSyncEntry *child_nh =
1203 0 : static_cast<NHKSyncEntry *>(pbb_child_nh_.get());
1204 0 : sub_nh_list.push_back(child_nh->nh_id());
1205 0 : encoder.set_nhr_nh_list(sub_nh_list);
1206 :
1207 0 : std::vector<int> sub_label_list;
1208 0 : sub_label_list.push_back(pbb_label_);
1209 0 : encoder.set_nhr_label_list(sub_label_list);
1210 0 : }
1211 : /*
1212 : * This is temp fix to handle CEM-25471
1213 : * Currently, vRouter doesn't differentiate PBB and MPLSoGRE/MPLSoUDP
1214 : * correctly and it uses encap_oif_id for PBB also which is not needed
1215 : * So, sending encap_oif_id as ZERO here in case of PBB so that vRouter
1216 : * can work in same way as it was working earlier.
1217 : */
1218 0 : encoder.set_nhr_encap_oif_id(std::vector<int32_t>(1, 0));
1219 0 : break;
1220 0 : }
1221 :
1222 796 : case NextHop::COMPOSITE: {
1223 796 : std::vector<int> sub_nh_id;
1224 796 : std::vector<int> sub_label_list;
1225 796 : std::vector<int> sub_flag_list;
1226 796 : encoder.set_nhr_type(NH_COMPOSITE);
1227 796 : assert(sip_.is_v4());
1228 796 : assert(dip_.is_v4());
1229 : /* TODO encoding */
1230 796 : encoder.set_nhr_tun_sip(htonl(sip_.to_v4().to_ulong()));
1231 796 : encoder.set_nhr_tun_dip(htonl(dip_.to_v4().to_ulong()));
1232 796 : encoder.set_nhr_encap_family(ETHERTYPE_ARP);
1233 796 : encoder.set_nhr_ecmp_config_hash(SetEcmpFieldsToUse());
1234 : /* Proto encode in Network byte order */
1235 796 : switch (comp_type_) {
1236 265 : case Composite::L2INTERFACE: {
1237 265 : flags |= NH_FLAG_COMPOSITE_ENCAP;
1238 265 : encoder.set_nhr_family(AF_BRIDGE);
1239 265 : break;
1240 : }
1241 0 : case Composite::L3INTERFACE: {
1242 0 : flags |= NH_FLAG_COMPOSITE_ENCAP;
1243 0 : break;
1244 : }
1245 0 : case Composite::EVPN: {
1246 0 : flags |= NH_FLAG_COMPOSITE_EVPN;
1247 0 : break;
1248 : }
1249 0 : case Composite::TOR: {
1250 0 : flags |= NH_FLAG_COMPOSITE_TOR;
1251 0 : break;
1252 : }
1253 0 : case Composite::FABRIC: {
1254 0 : encoder.set_nhr_family(AF_BRIDGE);
1255 0 : flags |= NH_FLAG_COMPOSITE_FABRIC;
1256 0 : break;
1257 : }
1258 0 : case Composite::L3FABRIC: {
1259 0 : flags |= NH_FLAG_COMPOSITE_FABRIC;
1260 0 : break;
1261 : }
1262 331 : case Composite::L2COMP: {
1263 331 : encoder.set_nhr_family(AF_BRIDGE);
1264 331 : flags |= NH_FLAG_MCAST;
1265 331 : if (validate_mcast_src_) {
1266 331 : flags |= NH_FLAG_VALIDATE_MCAST_SRC;
1267 : }
1268 331 : break;
1269 : }
1270 0 : case Composite::L3COMP: {
1271 0 : flags |= NH_FLAG_MCAST;
1272 0 : if (validate_mcast_src_) {
1273 0 : flags |= NH_FLAG_VALIDATE_MCAST_SRC;
1274 : }
1275 0 : break;
1276 : }
1277 0 : case Composite::MULTIPROTO: {
1278 0 : encoder.set_nhr_family(AF_UNSPEC);
1279 0 : break;
1280 : }
1281 200 : case Composite::ECMP:
1282 : case Composite::LOCAL_ECMP: {
1283 200 : flags |= NH_FLAG_COMPOSITE_ECMP;
1284 200 : break;
1285 : }
1286 0 : case Composite::LU_ECMP: {
1287 0 : flags |= NH_FLAG_COMPOSITE_ECMP;
1288 0 : flags |= NH_FLAG_COMPOSITE_LU_ECMP;
1289 0 : break;
1290 : }
1291 0 : case Composite::INVALID: {
1292 0 : assert(0);
1293 : }
1294 : }
1295 796 : if (need_pbb_tunnel_) {
1296 0 : flags |= NH_FLAG_TUNNEL_PBB;
1297 : }
1298 :
1299 796 : encoder.set_nhr_flags(flags);
1300 796 : for (KSyncComponentNHList::iterator it = component_nh_list_.begin();
1301 2189 : it != component_nh_list_.end(); it++) {
1302 1393 : KSyncComponentNH component_nh = *it;
1303 1393 : if (component_nh.nh()) {
1304 1372 : sub_nh_id.push_back(component_nh.nh()->nh_id());
1305 1372 : sub_label_list.push_back(component_nh.label());
1306 : } else {
1307 21 : sub_nh_id.push_back(CompositeNH::kInvalidComponentNHIdx);
1308 21 : sub_label_list.push_back(MplsTable::kInvalidLabel);
1309 : }
1310 1393 : }
1311 796 : encoder.set_nhr_nh_list(sub_nh_id);
1312 796 : encoder.set_nhr_label_list(sub_label_list);
1313 796 : break;
1314 796 : }
1315 0 : default:
1316 0 : assert(0);
1317 : }
1318 1765 : encoder.set_nhr_flags(flags);
1319 1765 : int error = 0;
1320 1765 : encode_len = encoder.WriteBinary((uint8_t *)buf, buf_len, &error);
1321 1765 : assert(error == 0);
1322 1765 : assert(encode_len <= buf_len);
1323 1765 : return encode_len;
1324 3415 : }
1325 :
1326 3415 : void NHKSyncEntry::FillObjectLog(sandesh_op::type op, KSyncNhInfo &info)
1327 : const {
1328 3415 : info.set_index(nh_id());
1329 :
1330 3415 : if (op == sandesh_op::ADD) {
1331 1765 : info.set_operation("ADD/CHANGE");
1332 : } else {
1333 1650 : info.set_operation("DELETE");
1334 : }
1335 :
1336 3415 : switch(type_) {
1337 4 : case NextHop::L2_RECEIVE: {
1338 4 : info.set_type("L2-RECEIVE");
1339 4 : break;
1340 : }
1341 4 : case NextHop::DISCARD: {
1342 4 : info.set_type("DISCARD");
1343 4 : break;
1344 : }
1345 :
1346 8 : case NextHop::RECEIVE: {
1347 8 : info.set_type("RECEIVE");
1348 8 : break;
1349 : }
1350 :
1351 4 : case NextHop::RESOLVE: {
1352 4 : info.set_type("RESOLVE");
1353 4 : break;
1354 : }
1355 :
1356 4 : case NextHop::ARP: {
1357 4 : info.set_type("ARP");
1358 : //Fill dmac and smac???
1359 4 : break;
1360 : }
1361 :
1362 0 : case NextHop::NDP: {
1363 0 : info.set_type("NDP");
1364 : //Fill dmac and smac???
1365 0 : break;
1366 : }
1367 :
1368 132 : case NextHop::VRF: {
1369 132 : info.set_type("VRF");
1370 132 : info.set_vrf(vrf_id_);
1371 132 : break;
1372 : }
1373 :
1374 1686 : case NextHop::INTERFACE: {
1375 1686 : info.set_type("INTERFACE");
1376 1686 : break;
1377 : }
1378 :
1379 96 : case NextHop::TUNNEL: {
1380 96 : info.set_type("TUNNEL");
1381 96 : info.set_sip(sip_.to_string());
1382 96 : info.set_dip(dip_.to_string());
1383 96 : info.set_crypt_path_available(crypt_);
1384 :
1385 96 : if (crypt_interface()) {
1386 0 : info.set_crypt_intf_name(crypt_interface()->interface_name());
1387 0 : info.set_crypt_out_if_index(crypt_interface()->interface_id());
1388 : } else {
1389 96 : info.set_crypt_intf_name("NULL");
1390 96 : info.set_crypt_out_if_index(kInvalidIndex);
1391 : }
1392 96 : info.set_rewrite_dmac(rewrite_dmac_.ToString());
1393 96 : break;
1394 : }
1395 :
1396 0 : case NextHop::MIRROR: {
1397 0 : info.set_type("MIRROR");
1398 0 : info.set_vrf(vrf_id_);
1399 0 : info.set_sip(sip_.to_string());
1400 0 : info.set_dip(dip_.to_string());
1401 0 : info.set_sport(sport_);
1402 0 : info.set_dport(dport_);
1403 0 : break;
1404 : }
1405 :
1406 0 : case NextHop::VLAN: {
1407 0 : info.set_type("VLAN");
1408 0 : info.set_vlan_tag(vlan_tag_);
1409 0 : break;
1410 : }
1411 1477 : case NextHop::COMPOSITE: {
1412 1477 : info.set_type("Composite");
1413 1477 : info.set_sub_type(comp_type_);
1414 1477 : info.set_dip(dip_.to_string());
1415 1477 : info.set_vrf(vrf_id_);
1416 1477 : std::vector<KSyncComponentNHLog> sub_nh_list;
1417 1477 : for (KSyncComponentNHList::const_iterator it =
1418 1477 : component_nh_list_.begin();
1419 3916 : it != component_nh_list_.end(); it++) {
1420 2439 : KSyncComponentNH component_nh = *it;
1421 2439 : if (component_nh.nh()) {
1422 2397 : KSyncComponentNHLog sub_nh;
1423 2397 : sub_nh.set_nh_idx(component_nh.nh()->nh_id());
1424 2397 : sub_nh.set_label(component_nh.label());
1425 2397 : sub_nh_list.push_back(sub_nh);
1426 2397 : }
1427 2439 : }
1428 1477 : info.set_sub_nh_list(sub_nh_list);
1429 1477 : break;
1430 1477 : }
1431 0 : default: {
1432 0 : return;
1433 : }
1434 : }
1435 :
1436 3415 : info.set_policy(policy_);
1437 3415 : info.set_valid(valid_);
1438 3415 : if (interface()) {
1439 1698 : info.set_intf_name(interface()->interface_name());
1440 1698 : info.set_out_if_index(interface()->interface_id());
1441 : } else {
1442 1717 : info.set_intf_name("NULL");
1443 1717 : info.set_out_if_index(kInvalidIndex);
1444 : }
1445 : }
1446 :
1447 1650 : int NHKSyncEntry::AddMsg(char *buf, int buf_len) {
1448 1650 : KSyncNhInfo info;
1449 1650 : FillObjectLog(sandesh_op::ADD, info);
1450 1650 : KSYNC_TRACE(NH, GetObject(), info);
1451 :
1452 3300 : return Encode(sandesh_op::ADD, buf, buf_len);
1453 1650 : }
1454 :
1455 115 : int NHKSyncEntry::ChangeMsg(char *buf, int buf_len){
1456 115 : KSyncNhInfo info;
1457 115 : FillObjectLog(sandesh_op::ADD, info);
1458 115 : KSYNC_TRACE(NH, GetObject(), info);
1459 :
1460 230 : return Encode(sandesh_op::ADD, buf, buf_len);
1461 115 : }
1462 :
1463 1650 : int NHKSyncEntry::DeleteMsg(char *buf, int buf_len) {
1464 1650 : KSyncNhInfo info;
1465 1650 : FillObjectLog(sandesh_op::DEL, info);
1466 1650 : KSYNC_TRACE(NH, GetObject(), info);
1467 :
1468 3300 : return Encode(sandesh_op::DEL, buf, buf_len);
1469 1650 : }
1470 :
1471 2687 : KSyncEntry *NHKSyncEntry::UnresolvedReference() {
1472 2687 : KSyncEntry *entry = NULL;
1473 2687 : InterfaceKSyncEntry *if_ksync = interface();
1474 :
1475 2687 : if (valid_ == false) {
1476 : //Invalid nexthop has no reference dependency
1477 50 : return NULL;
1478 : }
1479 :
1480 2637 : switch (type_) {
1481 0 : case NextHop::ARP: {
1482 0 : assert(if_ksync);
1483 0 : if (!if_ksync->IsResolvedAndInSync()) {
1484 0 : entry = if_ksync;
1485 : }
1486 0 : break;
1487 : }
1488 :
1489 0 : case NextHop::NDP: {
1490 0 : assert(if_ksync);
1491 0 : if (!if_ksync->IsResolvedAndInSync()) {
1492 0 : entry = if_ksync;
1493 : }
1494 0 : break;
1495 : }
1496 :
1497 1162 : case NextHop::VLAN:
1498 : case NextHop::INTERFACE: {
1499 1162 : assert(if_ksync);
1500 1162 : if (!if_ksync->IsResolvedAndInSync()) {
1501 319 : entry = if_ksync;
1502 : }
1503 1162 : break;
1504 : }
1505 :
1506 2 : case NextHop::L2_RECEIVE: {
1507 2 : assert(if_ksync == NULL);
1508 2 : break;
1509 : }
1510 :
1511 2 : case NextHop::DISCARD: {
1512 2 : assert(if_ksync == NULL);
1513 2 : break;
1514 : }
1515 :
1516 0 : case NextHop::TUNNEL: {
1517 0 : if (crypt_path_available_) {
1518 0 : InterfaceKSyncEntry *crypt_if_ksync = crypt_interface();
1519 0 : assert(crypt_if_ksync);
1520 0 : if (!crypt_if_ksync->IsResolvedAndInSync()) {
1521 0 : entry = crypt_if_ksync;
1522 : }
1523 : }
1524 0 : break;
1525 : }
1526 :
1527 0 : case NextHop::MIRROR: {
1528 0 : break;
1529 : }
1530 :
1531 12 : case NextHop::RECEIVE: {
1532 12 : assert(if_ksync);
1533 12 : if (!if_ksync->IsResolvedAndInSync()) {
1534 8 : entry = if_ksync;
1535 : }
1536 12 : break;
1537 : }
1538 :
1539 66 : case NextHop::VRF: {
1540 66 : break;
1541 : }
1542 :
1543 2 : case NextHop::RESOLVE: {
1544 2 : break;
1545 : }
1546 :
1547 0 : case NextHop::PBB: {
1548 0 : if (pbb_child_nh_ && !pbb_child_nh_->IsResolvedAndInSync()) {
1549 0 : entry = pbb_child_nh_.get();
1550 : }
1551 0 : break;
1552 : }
1553 :
1554 1391 : case NextHop::COMPOSITE: {
1555 1391 : for (KSyncComponentNHList::const_iterator it =
1556 1391 : component_nh_list_.begin();
1557 3026 : it != component_nh_list_.end(); it++) {
1558 2230 : KSyncComponentNH component_nh = *it;
1559 2230 : if (component_nh.nh() && !(component_nh.nh()->IsResolvedAndInSync())) {
1560 595 : entry = component_nh.nh();
1561 595 : break;
1562 : }
1563 2230 : }
1564 1391 : break;
1565 : }
1566 :
1567 0 : default:
1568 0 : assert(0);
1569 : break;
1570 : }
1571 2637 : return entry;
1572 : }
1573 :
1574 893 : static bool NeedRewrite(NHKSyncEntry *entry, InterfaceKSyncEntry *if_ksync) {
1575 :
1576 : // If interface has RAW-IP encapsulation, it doesnt need any rewrite
1577 : // information
1578 893 : if (if_ksync && if_ksync->encap_type() == PhysicalInterface::RAW_IP) {
1579 0 : return false;
1580 : }
1581 :
1582 : // For bridge nexthops, only INTERFACE nexthop has rewrite NH
1583 893 : if (entry->is_bridge() == true) {
1584 334 : if (entry->type() == NextHop::INTERFACE)
1585 334 : return true;
1586 0 : return false;
1587 : }
1588 :
1589 559 : return true;
1590 : }
1591 :
1592 893 : void NHKSyncEntry::SetEncap(InterfaceKSyncEntry *if_ksync,
1593 : std::vector<int8_t> &encap,
1594 : const int32_t index) {
1595 :
1596 893 : if (NeedRewrite(this, if_ksync) == false)
1597 0 : return;
1598 :
1599 893 : const MacAddress *smac = &MacAddress::ZeroMac();
1600 : /* DMAC encode */
1601 893 : if (type_ == NextHop::TUNNEL && index != -1) {
1602 0 : for (size_t i = 0; i < dmac_list_[index].size(); i++) {
1603 0 : encap.push_back(dmac_list_[index][i]);
1604 : }
1605 0 : } else {
1606 6251 : for (size_t i = 0 ; i < dmac_.size(); i++) {
1607 5358 : encap.push_back(dmac_[i]);
1608 : }
1609 : }
1610 : /* SMAC encode */
1611 893 : if (type_ == NextHop::VLAN) {
1612 0 : smac = &smac_;
1613 893 : } else if ((type_ == NextHop::INTERFACE || type_ == NextHop::ARP ||
1614 893 : type_ == NextHop::NDP) && if_ksync) {
1615 843 : smac = &if_ksync->mac();
1616 :
1617 : } else {
1618 50 : Agent *agent = ksync_obj_->ksync()->agent();
1619 50 : smac = &agent->vhost_interface()->mac();
1620 : }
1621 6251 : for (size_t i = 0 ; i < smac->size(); i++) {
1622 5358 : encap.push_back((*smac)[i]);
1623 : }
1624 :
1625 : // Add 802.1q header if
1626 : // - Nexthop is of type VLAN
1627 : // - Nexthop is of type INTERFACE and VLAN configured for it
1628 893 : if (type_ == NextHop::VLAN ||
1629 893 : (type_ == NextHop::INTERFACE &&
1630 843 : vlan_tag_ != VmInterface::kInvalidVlanId)) {
1631 0 : encap.push_back(0x81);
1632 0 : encap.push_back(0x00);
1633 0 : encap.push_back((vlan_tag_ & 0xFF00) >> 8);
1634 0 : encap.push_back(vlan_tag_ & 0xFF);
1635 : }
1636 : /* Proto encode in Network byte order */
1637 893 : encap.push_back(0x08);
1638 893 : encap.push_back(0x00);
1639 : }
1640 :
1641 796 : uint8_t NHKSyncEntry::SetEcmpFieldsToUse() {
1642 796 : uint8_t ecmp_hash_fields_in_use = VR_FLOW_KEY_NONE;
1643 796 : uint8_t fields_in_byte = ecmp_hash_fieds_.HashFieldsToUse();
1644 796 : if (fields_in_byte & 1 << EcmpLoadBalance::SOURCE_IP) {
1645 796 : ecmp_hash_fields_in_use |= VR_FLOW_KEY_SRC_IP;
1646 : }
1647 796 : if (fields_in_byte & 1 << EcmpLoadBalance::DESTINATION_IP) {
1648 796 : ecmp_hash_fields_in_use |= VR_FLOW_KEY_DST_IP;
1649 : }
1650 796 : if (fields_in_byte & 1 << EcmpLoadBalance::IP_PROTOCOL) {
1651 796 : ecmp_hash_fields_in_use |= VR_FLOW_KEY_PROTO;
1652 : }
1653 796 : if (fields_in_byte & 1 << EcmpLoadBalance::SOURCE_PORT) {
1654 796 : ecmp_hash_fields_in_use |= VR_FLOW_KEY_SRC_PORT;
1655 : }
1656 796 : if (fields_in_byte & 1 << EcmpLoadBalance::DESTINATION_PORT) {
1657 796 : ecmp_hash_fields_in_use |= VR_FLOW_KEY_DST_PORT;
1658 : }
1659 :
1660 796 : return ecmp_hash_fields_in_use;
1661 :
1662 : }
1663 :
1664 2 : NHKSyncObject::NHKSyncObject(KSync *ksync) :
1665 2 : KSyncDBObject("KSync Nexthop"), ksync_(ksync) {
1666 2 : }
1667 :
1668 4 : NHKSyncObject::~NHKSyncObject() {
1669 4 : }
1670 :
1671 2 : void NHKSyncObject::RegisterDBClients() {
1672 2 : RegisterDb(ksync_->agent()->nexthop_table());
1673 2 : }
1674 :
1675 1652 : KSyncEntry *NHKSyncObject::Alloc(const KSyncEntry *entry, uint32_t index) {
1676 1652 : const NHKSyncEntry *nh = static_cast<const NHKSyncEntry *>(entry);
1677 1652 : NHKSyncEntry *ksync = new NHKSyncEntry(this, nh, index);
1678 1652 : return static_cast<KSyncEntry *>(ksync);
1679 : }
1680 :
1681 1650 : KSyncEntry *NHKSyncObject::DBToKSyncEntry(const DBEntry *e) {
1682 1650 : const NextHop *nh = static_cast<const NextHop *>(e);
1683 1650 : NHKSyncEntry *key = new NHKSyncEntry(this, nh);
1684 1650 : return static_cast<KSyncEntry *>(key);
1685 : }
1686 :
1687 3415 : void vr_nexthop_req::Process(SandeshContext *context) {
1688 3415 : AgentSandeshContext *ioc = static_cast<AgentSandeshContext *>(context);
1689 3415 : ioc->NHMsgHandler(this);
1690 3415 : }
1691 :
1692 0 : void NHKSyncEntry::SetKSyncNhListSandeshData(KSyncNhListSandeshData *data) const {
1693 0 : data->set_vrf_id(vrf_id_);
1694 0 : data->set_label(label_);
1695 0 : if (valid_) {
1696 0 : data->set_valid("Enable");
1697 : } else {
1698 0 : data->set_valid("Disable");
1699 : }
1700 :
1701 0 : if (policy_) {
1702 0 : data->set_policy("Enable");
1703 : } else {
1704 0 : data->set_policy("Disable");
1705 : }
1706 :
1707 0 : if (is_mcast_nh_) {
1708 0 : data->set_is_mcast_nh("True");
1709 : } else {
1710 0 : data->set_is_mcast_nh("False");
1711 : }
1712 :
1713 0 : if (defer_) {
1714 0 : data->set_defer("Enable");
1715 : } else {
1716 0 : data->set_defer("Disable");
1717 : }
1718 :
1719 0 : data->set_vlan_tag(vlan_tag_);
1720 :
1721 0 : if (is_local_ecmp_nh_) {
1722 0 : data->set_is_local_ecmp_nh("True");
1723 : } else {
1724 0 : data->set_is_local_ecmp_nh("False");
1725 : }
1726 :
1727 0 : if (is_bridge_) {
1728 0 : data->set_is_bridge("True");
1729 : } else {
1730 0 : data->set_is_bridge("False");
1731 : }
1732 :
1733 0 : if (bridge_nh_) {
1734 0 : data->set_bridge_nh("Enable");
1735 : } else {
1736 0 : data->set_bridge_nh("Disable");
1737 : }
1738 :
1739 0 : if (flood_unknown_unicast_) {
1740 0 : data->set_flood_unknown_unicast("Enable");
1741 : } else {
1742 0 : data->set_flood_unknown_unicast("Disable");
1743 : }
1744 :
1745 0 : data->set_nh_id(nh_id_);
1746 0 : data->set_isid(isid_);
1747 0 : return;
1748 : }
1749 :
1750 0 : bool NHKSyncEntry::KSyncEntrySandesh(Sandesh *sresp) {
1751 0 : KSyncNhListResp *resp = static_cast<KSyncNhListResp *> (sresp);
1752 :
1753 0 : KSyncNhListSandeshData data;
1754 0 : SetKSyncNhListSandeshData(&data);
1755 : std::vector<KSyncNhListSandeshData> &list =
1756 0 : const_cast<std::vector<KSyncNhListSandeshData>&>(resp->get_KSyncNhList_list());
1757 0 : list.push_back(data);
1758 :
1759 0 : return true;
1760 0 : }
1761 :
1762 0 : void KSyncNhListReq::HandleRequest() const {
1763 0 : AgentKsyncSandeshPtr sand(new AgentKsyncNhListSandesh(context()));
1764 :
1765 0 : sand->DoKsyncSandesh(sand);
1766 :
1767 0 : }
|