trex_stateless_capture.h revision d9e19ba4
1/*
2 Itay Marom
3 Cisco Systems, Inc.
4*/
5
6/*
7Copyright (c) 2015-2016 Cisco Systems, Inc.
8
9Licensed under the Apache License, Version 2.0 (the "License");
10you may not use this file except in compliance with the License.
11You may obtain a copy of the License at
12
13    http://www.apache.org/licenses/LICENSE-2.0
14
15Unless required by applicable law or agreed to in writing, software
16distributed under the License is distributed on an "AS IS" BASIS,
17WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18See the License for the specific language governing permissions and
19limitations under the License.
20*/
21#ifndef __TREX_STATELESS_CAPTURE_H__
22#define __TREX_STATELESS_CAPTURE_H__
23
24#include <stdint.h>
25#include <assert.h>
26#include <mutex>
27
28#include "trex_stateless_pkt.h"
29#include "trex_stateless_capture_rc.h"
30
31
32/**************************************
33 * Capture Filter
34 *
35 * specify which ports to capture and if TX/RX or both
36 *************************************/
37class CaptureFilter {
38public:
39    CaptureFilter() {
40        m_tx_active = 0;
41        m_rx_active = 0;
42    }
43
44    /**
45     * add a port to the active TX port list
46     */
47    void add_tx(uint8_t port_id) {
48        m_tx_active |= (1LL << port_id);
49    }
50
51    /**
52     * add a port to the active RX port list
53     */
54    void add_rx(uint8_t port_id) {
55        m_rx_active |= (1LL << port_id);
56    }
57
58    void add(uint8_t port_id) {
59        add_tx(port_id);
60        add_rx(port_id);
61    }
62
63    bool in_x(uint8_t port_id, TrexPkt::origin_e origin) {
64        return (
65                 ( (origin == TrexPkt::ORIGIN_RX) && (in_rx(port_id)) )
66                 ||
67                 ( (origin == TrexPkt::ORIGIN_TX) && (in_tx(port_id)) )
68               );
69    }
70
71    bool in_rx(uint8_t port_id) const {
72        uint64_t bit = (1LL << port_id);
73        return ((m_rx_active & bit) == bit);
74    }
75
76    bool in_tx(uint8_t port_id) const {
77        uint64_t bit = (1LL << port_id);
78        return ((m_tx_active & bit) == bit);
79    }
80
81    bool in_any(uint8_t port_id) const {
82        return ( in_tx(port_id) || in_rx(port_id) );
83    }
84
85    /**
86     * updates the current filter with another filter
87     * the result is the aggregation of TX /RX active lists
88     */
89    CaptureFilter& operator +=(const CaptureFilter &other) {
90        m_tx_active |= other.m_tx_active;
91        m_rx_active |= other.m_rx_active;
92
93        return *this;
94    }
95
96    Json::Value to_json() const {
97        Json::Value output = Json::objectValue;
98        output["tx"] = Json::UInt64(m_tx_active);
99        output["rx"] = Json::UInt64(m_rx_active);
100
101        return output;
102    }
103
104private:
105
106    uint64_t  m_tx_active;
107    uint64_t  m_rx_active;
108};
109
110
111/**************************************
112 * Capture
113 *
114 * A single instance of a capture
115 *************************************/
116class TrexStatelessCapture {
117public:
118
119    enum state_e {
120        STATE_ACTIVE,
121        STATE_STOPPED,
122    };
123
124    TrexStatelessCapture(capture_id_t id,
125                         uint64_t limit,
126                         const CaptureFilter &filter,
127                         TrexPktBuffer::mode_e mode);
128
129    ~TrexStatelessCapture();
130
131    /**
132     * handles a packet
133     */
134    void handle_pkt(const rte_mbuf_t *m, int port, TrexPkt::origin_e origin);
135
136
137    uint64_t get_id() const {
138        return m_id;
139    }
140
141    const CaptureFilter & get_filter() const {
142        return m_filter;
143    }
144
145
146    /**
147     * stop the capture - from now on all packets will be ignored
148     *
149     * @author imarom (1/24/2017)
150     */
151    void stop() {
152        m_state = STATE_STOPPED;
153    }
154
155    TrexPktBuffer * fetch(uint32_t pkt_limit, uint32_t &pending);
156
157    bool is_active() const {
158        return m_state == STATE_ACTIVE;
159    }
160
161    uint32_t get_pkt_count() const {
162        return m_pkt_buffer->get_element_count();
163    }
164
165    dsec_t get_start_ts() const {
166        return m_start_ts;
167    }
168
169
170    Json::Value to_json() const;
171
172private:
173    state_e          m_state;
174    TrexPktBuffer   *m_pkt_buffer;
175    dsec_t           m_start_ts;
176    CaptureFilter    m_filter;
177    uint64_t         m_id;
178    uint64_t         m_pkt_index;
179};
180
181
182/**************************************
183 * Capture Manager
184 * Handles all the captures in
185 * the system
186 *
187 * the design is a singleton
188 *************************************/
189class TrexStatelessCaptureMngr {
190
191public:
192
193    static TrexStatelessCaptureMngr g_instance;
194    static TrexStatelessCaptureMngr& getInstance() {
195        return g_instance;
196    }
197
198
199    ~TrexStatelessCaptureMngr() {
200        reset();
201    }
202
203    /**
204     * starts a new capture
205     */
206    void start(const CaptureFilter &filter,
207               uint64_t limit,
208               TrexPktBuffer::mode_e mode,
209               TrexCaptureRCStart &rc);
210
211    /**
212     * stops an existing capture
213     *
214     */
215    void stop(capture_id_t capture_id, TrexCaptureRCStop &rc);
216
217    /**
218     * fetch packets from an existing capture
219     *
220     */
221    void fetch(capture_id_t capture_id, uint32_t pkt_limit, TrexCaptureRCFetch &rc);
222
223    /**
224     * removes an existing capture
225     * all packets captured will be detroyed
226     */
227    void remove(capture_id_t capture_id, TrexCaptureRCRemove &rc);
228
229
230    /**
231     * removes all captures
232     *
233     */
234    void reset();
235
236
237    /**
238     * return true if any filter is active
239     * on a specific port
240     *
241     * @author imarom (1/3/2017)
242     *
243     * @return bool
244     */
245    bool is_active(uint8_t port) const {
246        return m_global_filter.in_any(port);
247    }
248
249    /**
250     * handle packet on TX side
251     */
252    inline void handle_pkt_tx(const rte_mbuf_t *m, int port) {
253
254        /* fast bail out IF */
255        if (unlikely(m_global_filter.in_tx(port))) {
256            handle_pkt_slow_path(m, port, TrexPkt::ORIGIN_TX);
257        }
258
259    }
260
261    /**
262     * handle packet on RX side
263     */
264    inline void handle_pkt_rx(const rte_mbuf_t *m, int port) {
265
266        /* fast bail out IF */
267        if (unlikely(m_global_filter.in_rx(port))) {
268            handle_pkt_slow_path(m, port, TrexPkt::ORIGIN_RX);
269        }
270
271    }
272
273    Json::Value to_json() const;
274
275private:
276
277    TrexStatelessCaptureMngr() {
278        /* init this to 1 */
279        m_id_counter = 1;
280    }
281
282
283    TrexStatelessCapture * lookup(capture_id_t capture_id);
284    int lookup_index(capture_id_t capture_id);
285
286    void handle_pkt_slow_path(const rte_mbuf_t *m, int port, TrexPkt::origin_e origin) __attribute__ ((noinline));
287
288    void update_global_filter();
289
290    std::vector<TrexStatelessCapture *> m_captures;
291
292    capture_id_t m_id_counter;
293
294    /* a union of all the filters curently active */
295    CaptureFilter m_global_filter;
296
297    /* slow path lock*/
298    std::mutex    m_lock;
299
300    static const int MAX_CAPTURE_SIZE = 10;
301
302};
303
304#endif /* __TREX_STATELESS_CAPTURE_H__ */
305
306