Merge "docs: Update install and release docs for DPDK migration support"
[samplevnf.git] / VNFs / DPPD-PROX / tools / flow_extract / stream.cpp
1 /*
2 // Copyright (c) 2010-2017 Intel Corporation
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 */
16
17 #include <iostream>
18 #include <iomanip>
19 #include <arpa/inet.h>
20
21 #include "pcapwriter.hpp"
22 #include "stream.hpp"
23
24 Stream::Stream(uint32_t id, uint32_t sizeHint)
25         : m_id(id), m_prevPktIsClient(false)
26 {
27         m_client.pkts.reserve(sizeHint / 2);
28         m_server.pkts.reserve(sizeHint / 2);
29         m_pkts.reserve(sizeHint);
30 }
31
32 bool Stream::isClient(const PcapPkt &pkt) const
33 {
34         return m_pt == pkt.parsePkt();
35 }
36
37 size_t Stream::pktCount() const
38 {
39         return m_client.pkts.size() + m_server.pkts.size();
40 }
41
42 void Stream::setTupleFromPkt(const PcapPkt &pkt)
43 {
44         m_pt = pkt.parsePkt();
45 }
46
47 void Stream::addPkt(const PcapPkt &pkt)
48 {
49         if (!pktCount())
50                 setTupleFromPkt(pkt);
51
52         bool isClientPkt = isClient(pkt);
53         HalfStream *half;
54
55         if (isClientPkt)
56                 half = &m_client;
57         else
58                 half = &m_server;
59
60         HalfStream::Action::Part p = half->addPkt(pkt);
61
62         if (p.len) {
63                 addAction(half, p, isClientPkt);
64         }
65
66         m_pkts.push_back(pkt);
67 }
68
69 void Stream::addAction(HalfStream *half, HalfStream::Action::Part p, bool isClientPkt)
70 {
71         if (m_actions.empty() || m_prevPktIsClient != isClientPkt || m_pt.proto_id == IPPROTO_UDP)
72                 m_actions.push_back(HalfStream::Action(half, p, isClientPkt));
73         else
74                 m_actions.back().addPart(p);
75         m_prevPktIsClient = isClientPkt;
76 }
77
78 Stream::Header Stream::getHeader() const
79 {
80         Header h;
81
82         h.streamId = m_id;
83         h.clientHdrLen = m_client.hdrLen;
84         h.clientContentLen = m_client.contentLen;
85         h.serverHdrLen = m_server.hdrLen;
86         h.serverContentLen = m_server.contentLen;
87         h.actionCount = m_actions.size();
88         h.clientIP = m_pt.src_addr;
89         h.clientPort = m_pt.src_port;
90         h.serverIP = m_pt.dst_addr;
91         h.serverPort = m_pt.dst_port;
92         h.upRate = m_client.getRate();
93         h.dnRate = m_server.getRate();
94         h.protocol = m_pt.proto_id;
95         h.completedTCP = (m_client.tcpOpen && m_client.tcpClose && m_server.tcpOpen && m_server.tcpClose) ||
96                 (!m_client.tcpOpen && !m_client.tcpClose && !m_server.tcpOpen && !m_server.tcpClose);
97
98         return h;
99 }
100
101 void Stream::Header::toFile(ofstream *f) const
102 {
103         f->write((const char *)this, sizeof(*this));
104 }
105
106 int Stream::Header::fromFile(ifstream *f)
107 {
108         const size_t readSize = sizeof(*this);
109
110         f->read((char *)this, readSize);
111         return  f->gcount() == readSize? 0 : -1;
112 }
113
114 size_t Stream::Header::getStreamLen() const
115 {
116         return  actionCount * sizeof(ActionEntry)
117                 + clientHdrLen + clientContentLen
118                 + serverHdrLen + serverContentLen;
119 }
120
121 void Stream::actionsToFile(ofstream *f) const
122 {
123         ActionEntry actionEntry;
124         uint32_t runningTotalLen[2] = {0};
125
126         for (size_t i = 0; i < m_actions.size(); ++i) {
127                 actionEntry.peer = m_actions[i].isClient()? 0 : 1;
128                 actionEntry.beg = runningTotalLen[actionEntry.peer];
129                 actionEntry.len = m_actions[i].totLen();
130
131                 runningTotalLen[actionEntry.peer] += actionEntry.len;
132                 f->write((const char *)&actionEntry, sizeof(actionEntry));
133         }
134 }
135
136 void Stream::clientHdrToFile(ofstream *f) const
137 {
138         f->write((const char *)m_client.hdr, m_client.hdrLen);
139 }
140
141 void Stream::serverHdrToFile(ofstream *f) const
142 {
143         f->write((const char *)m_server.hdr, m_server.hdrLen);
144 }
145
146 void Stream::contentsToFile(ofstream *f, bool isClient) const
147 {
148         for (size_t i = 0; i < m_actions.size(); ++i)
149                 if (m_actions[i].isClient() == isClient)
150                         m_actions[i].toFile(f);
151 }
152
153 void Stream::toFile(ofstream *f)
154 {
155         getHeader().toFile(f);
156         actionsToFile(f);
157         clientHdrToFile(f);
158         serverHdrToFile(f);
159         contentsToFile(f, true);
160         contentsToFile(f, false);
161 }
162
163 void Stream::toPcap(const string& outFile)
164 {
165         PcapWriter pw;
166
167         pw.open(outFile);
168         for (size_t i = 0; i < m_pkts.size(); ++i)
169                 pw.write(m_pkts[i]);
170         pw.close();
171 }