Line data Source code
1 : /*
2 : * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved.
3 : * Copyright Contributors to the OpenSDN project
4 : */
5 : #include <base/os.h>
6 : #include <iostream>
7 : #include <fstream>
8 : #include <pugixml/pugixml.hpp>
9 : #include <boost/uuid/uuid.hpp>
10 : #include <boost/uuid/string_generator.hpp>
11 :
12 : #include <test/test_cmn_util.h>
13 : #include <pkt/test/test_pkt_util.h>
14 : #include <oper/physical_device.h>
15 : #include <oper/physical_device_vn.h>
16 :
17 : #include <test-xml/test_xml.h>
18 : #include <test-xml/test_xml_oper.h>
19 : #include <test-xml/test_xml_validate.h>
20 : #include <test-xml/test_xml_packet.h>
21 :
22 : using namespace std;
23 : using namespace pugi;
24 : using namespace boost::uuids;
25 : using namespace AgentUtXmlUtils;
26 : int hash_id = 1;
27 :
28 27 : AgentUtXmlPacketUtils::AgentUtXmlPacketUtils() {
29 27 : name_ = "pkt";
30 27 : len_ = 64;
31 27 : vrf_id_ = -1;
32 27 : vrf_str_ = "";
33 27 : ingress_ = false;
34 27 : fwd_mode_ = "l3";
35 27 : pkt_module_ = "flow";
36 :
37 27 : intf_id_ = 0;
38 27 : intf_ = "";
39 :
40 27 : tunnel_type_ = "";
41 27 : tunnel_sip_ = "0.0.0.0";
42 27 : tunnel_dip_ = "0.0.0.0";
43 27 : label_ = -1;
44 27 : vxlan_id_ = 0;
45 :
46 27 : smac_ = "00:00:00:00:00:01";
47 27 : dmac_ = "00:00:00:00:00:02";
48 27 : sip_ = "1.1.1.1";
49 27 : dip_ = "1.1.1.2";
50 27 : proto_id_ = 1;
51 27 : proto_ = "icmp";
52 27 : sport_ = 1;
53 27 : dport_ = 2;
54 27 : tcp_ack_ = false;
55 :
56 27 : trap_code_ = "flow";
57 27 : hash_id_ = 0;
58 27 : }
59 :
60 27 : AgentUtXmlPacketUtils::~AgentUtXmlPacketUtils() {
61 27 : }
62 :
63 54 : TunnelType::Type AgentUtXmlPacketUtils::GetTunnelType()
64 : const {
65 54 : if (tunnel_type_ == "gre" || tunnel_type_ == "GRE")
66 18 : return TunnelType::MPLS_GRE;
67 36 : if (tunnel_type_ == "udp" || tunnel_type_ == "UDP")
68 0 : return TunnelType::MPLS_UDP;
69 36 : if (tunnel_type_ == "vxlan" || tunnel_type_ == "VXLAN")
70 8 : return TunnelType::VXLAN;
71 28 : return TunnelType::INVALID;
72 : }
73 :
74 27 : uint8_t AgentUtXmlPacketUtils::GetIpProto() const {
75 27 : if (proto_ == "tcp")
76 2 : return 6;
77 25 : if (proto_ == "udp")
78 25 : return 17;
79 0 : if (proto_ == "icmp")
80 0 : return 1;
81 :
82 0 : return atoi(proto_.c_str());
83 : }
84 :
85 27 : uint8_t AgentUtXmlPacketUtils::GetTrapCode() const {
86 27 : if (trap_code_ == "flow")
87 27 : return AgentHdr::TRAP_FLOW_MISS;
88 :
89 0 : assert(0);
90 : return AgentHdr::INVALID;
91 : }
92 :
93 3 : PktHandler::PktModuleName AgentUtXmlPacketUtils::GetPacketModule() const {
94 3 : if (pkt_module_ == "flow" || pkt_module_ == "FLOW")
95 3 : return PktHandler::FLOW;
96 0 : if (pkt_module_ == "invalid" || pkt_module_ == "INVALID")
97 0 : return PktHandler::INVALID;
98 :
99 0 : assert(0);
100 : return PktHandler::INVALID;
101 : }
102 :
103 9 : bool AgentUtXmlPacketUtils::IsL2Mode() const {
104 9 : if (fwd_mode_ == "l2" || fwd_mode_ == "L2")
105 7 : return true;
106 2 : return false;
107 : }
108 :
109 3 : bool AgentUtXmlPacketUtils::IsL3Mode() const {
110 3 : if (fwd_mode_ == "l3" || fwd_mode_ == "L3")
111 3 : return true;
112 0 : return false;
113 : }
114 :
115 27 : bool AgentUtXmlPacketUtils::ReadXml(const pugi::xml_node &node) {
116 27 : GetStringAttribute(node, "fwd_mode", &fwd_mode_);
117 27 : GetStringAttribute(node, "pkt-module", &pkt_module_);
118 :
119 27 : GetStringAttribute(node, "tunnel_type", &tunnel_type_);
120 27 : if (tunnel_type_ != "") {
121 13 : GetStringAttribute(node, "tunnel_sip", &tunnel_sip_);
122 13 : GetStringAttribute(node, "tunnel_dip", &tunnel_dip_);
123 13 : GetUintAttribute(node, "label", (uint16_t *)&label_);
124 13 : GetUintAttribute(node, "vxlan-id", (uint16_t *)&vxlan_id_);
125 : }
126 :
127 27 : GetStringAttribute(node, "smac", &smac_);
128 27 : GetStringAttribute(node, "dmac", &dmac_);
129 :
130 27 : GetUintAttribute(node, "intf-id", (uint16_t *)&intf_id_);
131 27 : GetStringAttribute(node, "intf", &intf_);
132 27 : GetStringAttribute(node, "interface", &intf_);
133 :
134 27 : GetStringAttribute(node, "sip", &sip_);
135 27 : GetStringAttribute(node, "dip", &dip_);
136 27 : GetStringAttribute(node, "proto", &proto_);
137 27 : GetUintAttribute(node, "proto", &proto_id_);
138 27 : GetUintAttribute(node, "sport", &sport_);
139 27 : GetUintAttribute(node, "dport", &dport_);
140 27 : GetUintAttribute(node, "hash_id", (uint16_t *)&hash_id_);
141 :
142 27 : if (hash_id_ == 0) {
143 25 : hash_id_ = hash_id++;
144 : }
145 27 : return true;
146 : }
147 :
148 30 : const string AgentUtXmlPacketUtils::ToString() {
149 30 : stringstream s;
150 30 : if (tunnel_type_ == "") {
151 17 : s << "Packet < " << name_ << "> Interface <" << intf_ << "> ";
152 : } else {
153 26 : s << "Packet < " << name_ << "> Tunnel <" << tunnel_type_ << " : "
154 13 : << intf_ << " : " << label_ << " : " << tunnel_sip_ << " : "
155 13 : << tunnel_dip_ << "> ";
156 : }
157 30 : s << "<" << sip_ << " : " << dip_ << " : " << proto_ << " : " << sport_
158 30 : << " : " << dport_ << ">" << endl;
159 60 : return s.str();
160 30 : }
161 :
162 9 : static int GetVxlan(Interface *intf) {
163 9 : int vxlan = 0;
164 9 : if (intf) {
165 9 : VmInterface *vmi = static_cast<VmInterface *>(intf);
166 9 : if (vmi->vn()) {
167 9 : vxlan = vmi->vn()->GetVxLanId();
168 : }
169 : }
170 9 : return vxlan;
171 : }
172 :
173 27 : bool AgentUtXmlPacketUtils::InetPacket(Interface *intf, Agent *agent,
174 : PktGen *pkt) {
175 27 : TunnelType::Type tun_type = GetTunnelType();
176 27 : if (tun_type != TunnelType::INVALID) {
177 13 : pkt->AddEthHdr("00:00:00:00:00:01", "00:00:00:00:00:02", 0x800);
178 : const VmInterface *vhost = static_cast<const VmInterface *>
179 13 : (agent->vhost_interface());
180 13 : string dip = tunnel_dip_;
181 13 : if (dip == "0.0.0.0") {
182 13 : dip = vhost->primary_ip_addr().to_string();
183 : }
184 :
185 13 : uint8_t proto = IPPROTO_UDP;
186 13 : if (tun_type == TunnelType::MPLS_GRE)
187 9 : proto = IPPROTO_GRE;
188 :
189 13 : pkt->AddIpHdr(tunnel_sip_.c_str(), dip.c_str(), proto);
190 13 : if (tun_type == TunnelType::MPLS_GRE) {
191 9 : pkt->AddGreHdr();
192 9 : pkt->AddMplsHdr(label_, true);
193 4 : } else if (tun_type == TunnelType::MPLS_UDP) {
194 0 : pkt->AddUdpHdr(VR_MPLS_OVER_UDP_SRC_PORT, VR_MPLS_OVER_UDP_DST_PORT,
195 0 : (len_ + 100));
196 0 : pkt->AddMplsHdr(label_, true);
197 4 : } else if (tun_type == TunnelType::VXLAN) {
198 4 : pkt->AddUdpHdr(VR_VXLAN_UDP_SRC_PORT, VR_VXLAN_UDP_DST_PORT, 0);
199 4 : int vxlan = GetVxlan(intf);
200 4 : pkt->AddVxlanHdr(vxlan);
201 : }
202 :
203 13 : if (fwd_mode_ == "l2") {
204 11 : pkt->AddEthHdr(dmac_.c_str(), smac_.c_str(), 0x800);
205 : }
206 13 : } else {
207 14 : pkt->AddEthHdr(dmac_.c_str(), smac_.c_str(), 0x800);
208 : }
209 :
210 27 : pkt->AddIpHdr(sip_.c_str(), dip_.c_str(), proto_id_);
211 27 : if (proto_id_ == 17) {
212 25 : pkt->AddUdpHdr(sport_, dport_, len_);
213 2 : } else if (proto_id_ == 6) {
214 2 : pkt->AddTcpHdr(sport_, dport_, false, false, tcp_ack_, len_);
215 0 : } else if (proto_id_ == 1) {
216 0 : pkt->AddIcmpHdr();
217 : } else {
218 0 : assert(0);
219 : }
220 27 : return true;
221 : }
222 :
223 0 : bool AgentUtXmlPacketUtils::Inet6Packet(Interface *intf, Agent *agent,
224 : PktGen *pkt) {
225 0 : return true;
226 : }
227 :
228 27 : bool AgentUtXmlPacketUtils::MakePacket(Agent *agent, PktGen *pkt) {
229 27 : bool ret = false;
230 :
231 27 : boost::system::error_code ec;
232 27 : IpAddress ip = IpAddress::from_string(sip_, ec);
233 :
234 27 : bool ingress_flow = true;
235 27 : TunnelType::Type tunnel_type = GetTunnelType();
236 27 : if (tunnel_type != TunnelType::INVALID) {
237 13 : ingress_flow = false;
238 : }
239 :
240 27 : VmInterface *intf = NULL;
241 27 : if (atoi(intf_.c_str())) {
242 27 : intf = static_cast<VmInterface *>(VmPortGet(atoi(intf_.c_str())));
243 27 : if (intf) {
244 27 : intf_id_ = intf->id();
245 : }
246 : }
247 :
248 27 : if (tunnel_type == TunnelType::MPLS_GRE) {
249 9 : if (IsL2Mode()) {
250 7 : label_ = intf->l2_label();
251 : } else {
252 2 : label_ = intf->label();
253 : }
254 : }
255 :
256 27 : if (fwd_mode_ != "l2") {
257 7 : if (ingress_flow)
258 5 : dmac_ = agent->vrrp_mac().ToString();
259 : else
260 2 : dmac_ = intf->mac().ToString();
261 : }
262 :
263 27 : if (proto_id_ == 0) {
264 27 : proto_id_ = GetIpProto();
265 : }
266 :
267 27 : uint16_t if_id = intf_id_;
268 27 : if (tunnel_type != TunnelType::INVALID) {
269 : const VmInterface *vhost = static_cast<const VmInterface *>
270 13 : (agent->vhost_interface());
271 13 : if_id = vhost->parent_list()[0]->id();
272 : }
273 :
274 27 : int vxlan_id = 0;
275 27 : if ((tunnel_type == TunnelType::VXLAN) && (ingress_flow == false)) {
276 4 : vxlan_id = GetVxlan(intf);
277 : }
278 :
279 27 : if (intf->vmi_type() == VmInterface::BAREMETAL) {
280 1 : vxlan_id = GetVxlan(intf);
281 : }
282 :
283 27 : pkt->AddEthHdr("00:00:00:00:00:01", "00:00:00:00:00:02", 0x800);
284 27 : pkt->AddAgentHdr(if_id, GetTrapCode(), hash_id_, vrf_id_, label_, vxlan_id);
285 27 : if (ip.is_v4()) {
286 27 : ret = InetPacket(intf, agent, pkt);
287 : } else {
288 0 : ret = Inet6Packet(intf, agent, pkt);
289 : }
290 :
291 27 : return ret;
292 : }
293 :
294 : /////////////////////////////////////////////////////////////////////////////
295 : // AgentUtXmlPacket routines
296 : /////////////////////////////////////////////////////////////////////////////
297 24 : AgentUtXmlPacket::AgentUtXmlPacket(const string &name, const xml_node &node,
298 24 : AgentUtXmlTestCase *test_case) :
299 24 : AgentUtXmlNode(name, node, false, test_case), pkt_() {
300 24 : }
301 :
302 48 : AgentUtXmlPacket::~AgentUtXmlPacket() {
303 48 : }
304 :
305 24 : bool AgentUtXmlPacket::ReadXml() {
306 24 : AgentUtXmlNode::ReadXml();
307 24 : return pkt_.ReadXml(node());
308 : }
309 :
310 0 : bool AgentUtXmlPacket::ToXml(xml_node *parent) {
311 0 : assert(0);
312 : return true;
313 : }
314 :
315 24 : void AgentUtXmlPacket::ToString(string *str) {
316 24 : *str = pkt_.ToString();
317 24 : return;
318 : }
319 :
320 0 : string AgentUtXmlPacket::NodeType() {
321 0 : return "packet";
322 : }
323 :
324 24 : bool AgentUtXmlPacket::Run() {
325 24 : cout << "Generate packet" << endl;
326 24 : Agent *agent = Agent::GetInstance();
327 24 : PktGen pkt;
328 24 : pkt_.MakePacket(agent, &pkt);
329 :
330 24 : uint8_t *ptr(new uint8_t[pkt.GetBuffLen()]);
331 24 : memcpy(ptr, pkt.GetBuff(), pkt.GetBuffLen());
332 :
333 : TestPkt0Interface *pkt0 = static_cast<TestPkt0Interface *>
334 24 : (agent->pkt()->control_interface());
335 24 : pkt0->ProcessFlowPacket(ptr, pkt.GetBuffLen(), pkt.GetBuffLen());
336 24 : return true;
337 24 : }
338 :
339 : /////////////////////////////////////////////////////////////////////////////
340 : // AgentUtXmlPktParseValidate routines
341 : /////////////////////////////////////////////////////////////////////////////
342 3 : AgentUtXmlPktParseValidate::AgentUtXmlPktParseValidate(const string &name,
343 3 : const xml_node &node) :
344 3 : AgentUtXmlValidationNode(name, node), pkt_() {
345 3 : }
346 :
347 6 : AgentUtXmlPktParseValidate::~AgentUtXmlPktParseValidate() {
348 6 : }
349 :
350 3 : bool AgentUtXmlPktParseValidate::ReadXml() {
351 3 : return pkt_.ReadXml(node());
352 : }
353 :
354 6 : const string AgentUtXmlPktParseValidate::ToString() {
355 6 : return pkt_.ToString();
356 : }
357 :
358 3 : bool AgentUtXmlPktParseValidate::Validate(PktHandler::PktModuleName type,
359 : PktInfo *info) {
360 3 : bool ret = true;
361 :
362 3 : if (type != pkt_.GetPacketModule())
363 0 : return false;
364 :
365 3 : if (type == PktHandler::INVALID)
366 0 : return true;
367 :
368 3 : if (info->ip_saddr != Ip4Address::from_string(pkt_.sip_) &&
369 3 : (info->ip_saddr != Ip6Address::from_string(pkt_.sip_)))
370 0 : return false;
371 :
372 3 : if (info->ip_daddr != Ip4Address::from_string(pkt_.dip_) &&
373 3 : (info->ip_daddr != Ip6Address::from_string(pkt_.dip_)))
374 0 : return false;
375 :
376 3 : if (pkt_.IsL3Mode() == false) {
377 0 : if (info->smac != MacAddress::FromString(pkt_.smac_))
378 0 : return false;
379 0 : if (info->dmac != MacAddress::FromString(pkt_.dmac_))
380 0 : return false;
381 : }
382 :
383 3 : if (pkt_.proto_id_ != info->ip_proto) {
384 0 : return false;
385 : }
386 :
387 3 : if (pkt_.proto_id_ == 6 || pkt_.proto_id_ == 17) {
388 3 : if (pkt_.sport_ != info->sport)
389 0 : return false;
390 3 : if (pkt_.dport_ != info->dport)
391 0 : return false;
392 : }
393 :
394 3 : return ret;
395 : }
396 :
397 3 : bool AgentUtXmlPktParseValidate::Validate() {
398 3 : Agent *agent = Agent::GetInstance();
399 3 : cout << "Generating packet" << endl;
400 :
401 3 : PktGen pkt;
402 3 : pkt_.MakePacket(agent, &pkt);
403 :
404 3 : uint32_t buff_len = pkt.GetBuffLen();
405 3 : uint32_t payload_len = pkt.GetBuffLen();
406 3 : uint8_t *ptr(new uint8_t[buff_len]);
407 3 : memcpy(ptr, pkt.GetBuff(), pkt.GetBuffLen());
408 :
409 : PacketBufferPtr buff(agent->pkt()->packet_buffer_manager()->Allocate
410 3 : (PktHandler::RX_PACKET, ptr, buff_len, buff_len - payload_len,
411 3 : payload_len, 0));
412 :
413 3 : PktInfo pkt_info(buff);
414 : VrouterControlInterface *pkt0 = static_cast<VrouterControlInterface *>
415 3 : (agent->pkt()->control_interface());
416 :
417 3 : AgentHdr agent_hdr;
418 3 : pkt0->DecodeAgentHdr(&agent_hdr, (uint8_t *)(ptr), payload_len);
419 :
420 : PktHandler::PktModuleName type;
421 3 : type = agent->pkt()->pkt_handler()->ParsePacket(agent_hdr, &pkt_info,
422 : (ptr + ETH_HLEN +
423 : sizeof(struct agent_hdr)));
424 6 : return Validate(type, &pkt_info);
425 3 : }
|