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