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 "kstate.h" 7 : #include "nh_kstate.h" 8 : #include "vr_nexthop.h" 9 : #include <net/ethernet.h> 10 : #include <netinet/if_ether.h> 11 : #include <iomanip> 12 : #include <sstream> 13 : 14 : using namespace std; 15 : 16 0 : NHKState::NHKState(KNHResp *obj, const std::string &resp_ctx, 17 0 : vr_nexthop_req &req, int id) 18 0 : : KState(resp_ctx, obj) { 19 : 20 0 : req.set_nhr_id(id); 21 0 : if (id >= 0) { 22 0 : req.set_h_op(sandesh_op::GET); 23 : } else { 24 0 : req.set_h_op(sandesh_op::DUMP); 25 0 : req.set_nhr_marker(-1); 26 : } 27 0 : } 28 : 29 0 : void NHKState::SendNextRequest() { 30 0 : vr_nexthop_req req; 31 0 : req.set_nhr_id(0); 32 0 : req.set_h_op(sandesh_op::DUMP); 33 0 : int32_t idx = boost::any_cast<int32_t>(more_context_); 34 0 : req.set_nhr_marker(idx); 35 0 : EncodeAndSend(req); 36 0 : } 37 : 38 0 : void NHKState::Handler() { 39 0 : KNHResp *resp = static_cast<KNHResp *>(response_object_); 40 0 : if (resp) { 41 0 : if (MoreData()) { 42 : /* There are more nexthops in Kernel. We need to query them from 43 : * Kernel and send it to Sandesh. 44 : */ 45 0 : SendResponse(); 46 0 : SendNextRequest(); 47 : } else { 48 0 : resp->set_context(response_context_); 49 0 : resp->Response(); 50 0 : more_context_ = boost::any(); 51 : } 52 : } 53 0 : } 54 : 55 0 : void NHKState::SendResponse() { 56 : 57 0 : KNHResp *resp = static_cast<KNHResp *>(response_object_); 58 0 : resp->set_context(response_context_); 59 0 : resp->set_more(true); 60 0 : resp->Response(); 61 : 62 0 : response_object_ = new KNHResp(); 63 0 : } 64 : 65 : 66 0 : const string NHKState::TypeToString(int nh_type) const { 67 0 : unsigned short type = nh_type; 68 0 : switch(type) { 69 0 : case NH_ENCAP: 70 0 : return "ENCAP"; 71 0 : case NH_TUNNEL: 72 0 : return "TUNNEL"; 73 0 : case NH_DISCARD: 74 0 : return "DISCARD"; 75 0 : case NH_RCV: 76 0 : return "RECEIVE"; 77 0 : case NH_RESOLVE: 78 0 : return "RESOLVE"; 79 0 : case NH_COMPOSITE: 80 0 : return "COMPOSITE"; 81 0 : case NH_DEAD: 82 0 : return "DEAD"; 83 0 : default: 84 0 : return "INVALID"; 85 : } 86 : } 87 : 88 0 : const string NHKState::FamilyToString(int nh_family) const { 89 0 : unsigned family = nh_family; 90 0 : switch(family) { 91 0 : case AF_INET: 92 0 : return "AF_INET"; 93 0 : case AF_INET6: 94 0 : return "AF_INET6"; 95 0 : default: 96 0 : return "INVALID"; 97 : } 98 : } 99 : 100 0 : const string NHKState::EncapFamilyToString(int nh_family) const { 101 0 : unsigned family = nh_family; 102 0 : switch(family) { 103 0 : case ETHERTYPE_ARP: 104 0 : return "ETH_P_ARP"; 105 0 : case 0: 106 0 : return "NO_ENCAP"; 107 0 : default: 108 0 : return "INVALID"; 109 : } 110 : } 111 : 112 0 : const string NHKState::EncapToString(const vector<signed char> &encap) const { 113 0 : ostringstream strm; 114 : uint8_t ubyte; 115 0 : vector<signed char>::const_iterator it = encap.begin(); 116 0 : strm << hex << setfill('0'); 117 0 : while(it != encap.end()) { 118 0 : ubyte = (uint8_t) *it; 119 0 : strm << setw(2) << (int)ubyte; 120 0 : ++it; 121 : } 122 0 : return strm.str(); 123 0 : } 124 : 125 0 : const string NHKState::FlagsToString(uint32_t flags) const { 126 0 : string flag_str, policy_str("POLICY "), gre_str("TUNNEL_GRE "); 127 0 : string fabric_multicast("FABRIC_MULTICAST"); 128 0 : string l2_multicast("L2_MULTICAST"); 129 0 : string l3_multicast("L3_MULTICAST"); 130 0 : string multi_proto_multicast("MULTI_PROTO_MULTICAST"); 131 0 : string ecmp("ECMP"); 132 0 : string multicast_encap("MULTICAST_ENCAP"); 133 0 : string mpls_udp_str("TUNNEL_MPLS_UDP "); 134 0 : string udp_str("TUNNEL_UDP "), sip_copy("TUNNEL_SIP_COPY "); 135 0 : bool assigned = false; 136 : 137 0 : if (flags & NH_FLAG_VALID) { 138 0 : flag_str.assign("VALID "); 139 0 : assigned = true; 140 : } 141 0 : if (flags & NH_FLAG_POLICY_ENABLED) { 142 0 : if (assigned) { 143 0 : flag_str.append("| " + policy_str); 144 : } else { 145 0 : flag_str.assign(policy_str); 146 0 : assigned = true; 147 : } 148 : } 149 0 : if (flags & NH_FLAG_TUNNEL_GRE) { 150 0 : if (assigned) { 151 0 : flag_str.append("| " + gre_str); 152 : } else { 153 0 : flag_str.assign(gre_str); 154 0 : assigned = true; 155 : } 156 : } 157 0 : if (flags & NH_FLAG_TUNNEL_UDP) { 158 0 : if (assigned) { 159 0 : flag_str.append("| " + udp_str); 160 : } else { 161 0 : flag_str.assign(udp_str); 162 0 : assigned = true; 163 : } 164 : } 165 0 : if (flags & NH_FLAG_TUNNEL_UDP_MPLS) { 166 0 : if (assigned) { 167 0 : flag_str.append("| " + mpls_udp_str); 168 : } else { 169 0 : flag_str.assign(mpls_udp_str); 170 0 : assigned = true; 171 : } 172 : } 173 : 174 0 : if (flags & NH_FLAG_COMPOSITE_ECMP) { 175 0 : if (assigned) { 176 0 : flag_str.append("| " + ecmp); 177 : } else { 178 0 : flag_str.assign(ecmp); 179 0 : assigned = true; 180 : } 181 : } 182 : 183 0 : if (flags & NH_FLAG_COMPOSITE_FABRIC) { 184 0 : if (assigned) { 185 0 : flag_str.append("| " + fabric_multicast); 186 : } else { 187 0 : flag_str.assign(fabric_multicast); 188 0 : assigned = true; 189 : } 190 : } 191 : 192 0 : if (flags & NH_FLAG_TUNNEL_SIP_COPY) { 193 0 : if (assigned) { 194 0 : flag_str.append("| " + sip_copy); 195 : } else { 196 0 : flag_str.assign(sip_copy); 197 0 : assigned = true; 198 : } 199 : } 200 : 201 0 : if (!assigned) { 202 0 : return "NIL"; 203 : } 204 0 : return flag_str; 205 0 : } 206 : 207 0 : void NHKState::SetComponentNH(vr_nexthop_req *req, KNHInfo &info) { 208 0 : std::vector<KComponentNH> comp_nh_list; 209 0 : KComponentNH comp_nh; 210 : 211 0 : if (req->get_nhr_type() != NH_COMPOSITE) { 212 0 : return; 213 : } 214 : 215 0 : const std::vector<int32_t> nh_list = req->get_nhr_nh_list(); 216 0 : const std::vector<int32_t> label_list = req->get_nhr_label_list(); 217 : 218 0 : for (uint32_t i = 0; i < nh_list.size(); i++) { 219 0 : comp_nh.set_nh_id(nh_list[i]); 220 0 : comp_nh.set_label(label_list[i]); 221 0 : comp_nh_list.push_back(comp_nh); 222 : } 223 0 : info.set_component_nh(comp_nh_list); 224 0 : }