Line data Source code
1 : /*
2 : * Copyright (c) 2016 Juniper Networks, Inc. All rights reserved.
3 : */
4 :
5 : #include <stdint.h>
6 : #include <netinet/udp.h>
7 : #include "vr_defs.h"
8 : #include "cmn/agent_cmn.h"
9 : #include "oper/route_common.h"
10 : #include "pkt/proto.h"
11 : #include "pkt/proto_handler.h"
12 : #include "diag/diag_types.h"
13 : #include "diag/diag.h"
14 : #include "diag/overlay_traceroute.h"
15 : #include "diag/overlay_ping.h"
16 : #include "diag/traceroute.h"
17 : #include "diag/diag_pkt_handler.h"
18 :
19 : using namespace boost::posix_time;
20 0 : OverlayTraceRoute::OverlayTraceRoute(const OverlayTraceReq *traceroute_req,
21 0 : DiagTable *diag_table) :
22 : DiagEntry(traceroute_req->get_source_ip(), traceroute_req->get_dest_ip(),
23 0 : traceroute_req->get_protocol(), traceroute_req->get_source_port(),
24 0 : traceroute_req->get_dest_port(), Agent::GetInstance()->fabric_vrf_name(),
25 0 : traceroute_req->get_interval() * 100,traceroute_req->get_max_attempts(), diag_table),
26 0 : vn_uuid_(StringToUuid(traceroute_req->get_vn_uuid())),
27 0 : remote_vm_mac_(traceroute_req->get_vm_remote_mac()), ttl_(2),
28 0 : max_ttl_(traceroute_req->get_max_hops()),
29 0 : context_(traceroute_req->context()) {
30 0 : }
31 :
32 0 : OverlayTraceRoute::~OverlayTraceRoute() {
33 0 : }
34 :
35 :
36 0 : void OverlayTraceRoute::SendRequest()
37 : {
38 0 : Agent *agent = diag_table_->agent();
39 0 : Ip4Address tunneldst;
40 0 : Ip4Address tunnelsrc;
41 0 : seq_no_++;
42 0 : string vrf_name;
43 0 : boost::system::error_code ec;
44 0 : uint8_t data_len = 50;
45 0 : int vxlan_id = agent->vn_table()->Find(vn_uuid_)->GetVxLanId();
46 0 : VxLanId *vxlan = agent->vxlan_table()->Find(vxlan_id);
47 0 : if (!vxlan)
48 0 : return;
49 :
50 0 : BridgeRouteEntry *rt = OverlayPing::L2RouteGet(vxlan,
51 0 : remote_vm_mac_.ToString(), agent);
52 0 : if (!rt)
53 0 : return;
54 0 : const AgentPath *path = rt->GetActivePath();
55 0 : const TunnelNH *nh = static_cast<const TunnelNH *>(path->nexthop());
56 :
57 0 : tunneldst = *nh->GetDip();
58 0 : tunnelsrc = *nh->GetSip();
59 0 : len_ = OverlayPing::kOverlayUdpHdrLength + data_len;
60 : boost::shared_ptr<PktInfo> pkt_info(new PktInfo(agent, len_,
61 0 : PktHandler::DIAG, 0));
62 0 : uint8_t *buf = pkt_info->packet_buffer()->data();
63 0 : memset(buf, 0, len_);
64 0 : OverlayOamPktData *pktdata = NULL;
65 0 : pktdata = (OverlayOamPktData *)(buf + OverlayPing::kOverlayUdpHdrLength);
66 :
67 0 : boost::posix_time::ptime senttime = microsec_clock::universal_time();
68 0 : FillOamPktHeader(pktdata, vxlan_id, senttime);
69 0 : DiagPktHandler *pkt_handler = new DiagPktHandler(diag_table_->agent(), pkt_info,
70 0 : *(diag_table_->agent()->event_manager())->io_service());
71 : // FIll outer header
72 0 : pkt_info->eth = (struct ether_header *)(buf);
73 0 : pkt_handler->EthHdr(agent->vhost_interface()->mac(), *nh->GetDmac(),
74 : ETHERTYPE_IP);
75 0 : pkt_info->ip = (struct ip *)(pkt_info->eth +1);
76 0 : pkt_info->transp.udp = (struct udphdr *)(pkt_info->ip + 1);
77 : uint8_t len;
78 0 : len = data_len+2 * sizeof(udphdr)+sizeof(VxlanHdr)+
79 : sizeof(struct ip) + sizeof(struct ether_header);
80 0 : pkt_handler->UdpHdr(len, ntohl(tunnelsrc.to_ulong()), HashValUdpSourcePort(),
81 0 : ntohl(tunneldst.to_ulong()), VXLAN_UDP_DEST_PORT);
82 :
83 0 : pkt_handler->IpHdr(len + sizeof(struct ip), ntohl(tunnelsrc.to_ulong()),
84 0 : ntohl(tunneldst.to_ulong()), IPPROTO_UDP,
85 0 : DEFAULT_IP_ID, ttl_);
86 : // Fill VxLan Header
87 0 : VxlanHdr *vxlanhdr = (VxlanHdr *)(buf + sizeof(udphdr)+ sizeof(struct ip)
88 : + sizeof(struct ether_header));
89 0 : vxlanhdr->vxlan_id = ntohl(vxlan_id << 8);
90 0 : vxlanhdr->reserved = ntohl(OverlayPing::kVxlanRABit | OverlayPing::kVxlanIBit);
91 :
92 : //Fill inner packet details.
93 0 : pkt_info->eth = (struct ether_header *)(vxlanhdr + 1);
94 :
95 0 : pkt_handler->EthHdr(OverlayPing::in_source_mac_, OverlayPing::in_dst_mac_,
96 : ETHERTYPE_IP);
97 :
98 0 : pkt_info->ip = (struct ip *)(pkt_info->eth +1);
99 0 : Ip4Address dip = Ip4Address::from_string("127.0.0.1", ec);
100 0 : pkt_info->transp.udp = (struct udphdr *)(pkt_info->ip + 1);
101 0 : len = data_len+sizeof(struct udphdr);
102 0 : pkt_handler->UdpHdr(len, sip_.to_v4().to_ulong(), sport_,
103 0 : dip.to_ulong(), VXLAN_UDP_DEST_PORT);
104 0 : pkt_handler->IpHdr(len + sizeof(struct ip), ntohl(sip_.to_v4().to_ulong()),
105 0 : ntohl(dip.to_ulong()), proto_,
106 : DEFAULT_IP_ID, DEFAULT_IP_TTL);
107 : //pkt_handler->SetDiagChkSum();
108 0 : pkt_handler->pkt_info()->set_len(len_);
109 0 : PhysicalInterfaceKey key1(agent->fabric_interface_name());
110 0 : Interface *intf = static_cast<Interface *>
111 0 : (agent->interface_table()->Find(&key1, true));
112 0 : pkt_handler->Send(intf->id(), agent->fabric_vrf()->vrf_id(),
113 : AgentHdr::TX_SWITCH, CMD_PARAM_PACKET_CTRL,
114 : CMD_PARAM_1_DIAG, PktHandler::DIAG);
115 :
116 0 : delete pkt_handler;
117 0 : return;
118 0 : }
119 :
120 0 : void OverlayTraceReq::HandleRequest() const {
121 0 : std::string err_str;
122 0 : boost::system::error_code ec;
123 0 : OverlayTraceRoute *overlaytraceroute = NULL;
124 :
125 : {
126 0 : Agent *agent = Agent::GetInstance();
127 0 : boost::uuids::uuid vn_uuid = StringToUuid(get_vn_uuid());
128 0 : IpAddress sip(IpAddress::from_string(get_source_ip(), ec));
129 0 : if (ec.failed()) {
130 0 : err_str = "Invalid source IP";
131 0 : goto error;
132 : }
133 :
134 0 : if (!sip.is_v4()) {
135 0 : err_str = "V6 is not supported";
136 0 : goto error;
137 : }
138 :
139 0 : IpAddress dip(IpAddress::from_string(get_dest_ip(), ec));
140 0 : if (ec.failed()) {
141 0 : err_str = "Invalid destination IP";
142 0 : goto error;
143 : }
144 :
145 0 : if (!dip.is_v4()) {
146 0 : err_str = "V6 is not supported";
147 0 : goto error;
148 : }
149 :
150 0 : uint8_t proto = get_protocol();
151 0 : if (proto != IPPROTO_TCP && proto != IPPROTO_UDP) {
152 0 : err_str = "Invalid protocol - Supported protocols are TCP & UDP";
153 0 : goto error;
154 : }
155 0 : VnEntry *vn = agent->vn_table()->Find(vn_uuid);
156 :
157 0 : if (!vn) {
158 0 : err_str = "Invalid VN segment";
159 0 : goto error;
160 : }
161 :
162 0 : int vxlan_id = vn->GetVxLanId();
163 0 : VxLanId* vxlan = agent->vxlan_table()->Find(vxlan_id);
164 :
165 0 : if (!vxlan) {
166 0 : err_str = "Invalid vxlan segment";
167 0 : goto error;
168 : }
169 :
170 0 : BridgeRouteEntry *rt = OverlayPing::L2RouteGet(vxlan,
171 0 : get_vm_remote_mac(), agent);
172 0 : if (!rt) {
173 0 : err_str = "Invalid remote mac";
174 0 : goto error;
175 : }
176 : }
177 0 : overlaytraceroute = new OverlayTraceRoute(this,
178 0 : Agent::GetInstance()->diag_table());
179 0 : overlaytraceroute->Init();
180 0 : overlaytraceroute->ReplyLocalHop();
181 0 : return;
182 :
183 0 : error:
184 0 : TraceRouteErrResp *resp = new TraceRouteErrResp;
185 0 : resp->set_error_response(err_str);
186 0 : resp->set_context(context());
187 0 : resp->Response();
188 0 : return;
189 0 : }
190 : // if timed out max times for a TTL, reply and increment ttl
191 0 : void OverlayTraceRoute::RequestTimedOut(uint32_t seqno) {
192 0 : if (seq_no_ >= GetMaxAttempts()) {
193 0 : std::string address;
194 0 : for (uint32_t i = 0; i < GetMaxAttempts(); i++)
195 0 : address += "* ";
196 :
197 0 : done_ = ((ttl_ >= max_ttl_) ? true : false);
198 0 : TraceRoute::SendSandeshReply(address, context_, !done_);
199 0 : IncrementTtl();
200 0 : }
201 0 : }
202 :
203 : // Ready to send a response and increment ttl
204 0 : void OverlayTraceRoute::HandleReply(DiagPktHandler *handler) {
205 0 : if (ttl_ >= max_ttl_) {
206 0 : handler->set_done(true);
207 0 : done_ = true;
208 : }
209 0 : struct ip *ip = handler->pkt_info()->tunnel.ip;
210 0 : IpAddress saddr = IpAddress(Ip4Address(ntohl(ip->ip_src.s_addr)));
211 0 : TraceRoute::SendSandeshReply(saddr.to_v4().to_string(), context_,
212 0 : !handler->IsDone());
213 0 : IncrementTtl();
214 0 : }
215 :
216 : // Reply with local node as the first hop
217 0 : void OverlayTraceRoute::ReplyLocalHop() {
218 0 : TraceRoute::SendSandeshReply(diag_table_->agent()->router_id().to_string(),
219 0 : context_, true);
220 0 : }
221 :
222 0 : void OverlayTraceRoute::IncrementTtl() {
223 0 : ttl_++;
224 0 : seq_no_ = 0;
225 0 : }
|