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