trex_client_config.h revision bf83f301
1/*
2 Itay Marom
3 Cisco Systems, Inc.
4*/
5
6/*
7Copyright (c) 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_CLIENT_CONFIG_H__
22#define __TREX_CLIENT_CONFIG_H__
23
24#include <stdint.h>
25#include <string>
26#include <map>
27#include "utl_ip.h"
28#include "common/Network/Packet/MacAddress.h"
29
30class YAMLParserWrapper;
31struct CTupleGenYamlInfo;
32
33/**
34 * client configuration per direction
35 *
36 * @author imarom (29-Jun-16)
37 */
38class ClientCfgDir {
39    friend class ClientCfgCompactEntry;
40
41private:
42    enum {
43        HAS_SRC_MAC       = 0x1,
44        HAS_DST_MAC       = 0x2,
45        HAS_VLAN          = 0x4,
46        HAS_NEXT_HOP      = 0x8,
47        HAS_IPV6_NEXT_HOP = 0x10,
48        HAS_SRC_IP        = 0x20,
49        HAS_SRC_IPV6      = 0x40,
50    };
51
52    //???? do we need to save memory? Maybe do another class that inherit from ClientCfgDir to be used here?
53    uint32_t    m_next_hop;
54    uint32_t    m_src_ip;
55    uint16_t    m_src_ipv6[8];
56    uint16_t    m_ipv6_next_hop[8];
57    MacAddress  m_src_mac;
58    MacAddress  m_dst_mac;
59    uint16_t    m_vlan;
60    uint8_t     m_bitfield;
61    std::vector <MacAddress> m_resolved_macs;
62
63public:
64    ClientCfgDir() {
65        m_bitfield = 0;
66    }
67
68    void dump(FILE *fd) const;
69    void set_resolved_macs(CManyIPInfo &pretest_result, uint16_t count);
70    bool need_resolve() const;
71    void set_no_resolve_needed();
72
73    bool has_src_mac_addr() const {
74        return (m_bitfield & HAS_SRC_MAC);
75    }
76
77    bool has_dst_mac_addr() const {
78        return (m_bitfield & HAS_DST_MAC);
79    }
80    bool has_vlan() const {
81        return (m_bitfield & HAS_VLAN);
82    }
83
84    bool has_next_hop() const {
85        return (m_bitfield & HAS_NEXT_HOP);
86    }
87
88    bool has_ipv6_next_hop() const {
89        return (m_bitfield & HAS_IPV6_NEXT_HOP);
90    }
91
92    bool has_src_ip() const {
93        return (m_bitfield & HAS_SRC_IP);
94    }
95
96    bool has_src_ipv6() const {
97        return (m_bitfield & HAS_SRC_IPV6);
98    }
99
100    void set_src_mac_addr(uint64_t mac_addr) {
101        m_src_mac.set(mac_addr);
102        m_bitfield |= HAS_SRC_MAC;
103    }
104
105    void set_dst_mac_addr(uint64_t mac_addr) {
106        m_dst_mac.set(mac_addr);
107        m_bitfield |= HAS_DST_MAC;
108    }
109
110    void set_vlan(uint16_t vlan_id) {
111        m_vlan      = vlan_id;
112        m_bitfield |= HAS_VLAN;
113    }
114
115    void set_src_ip(uint32_t src_ip) {
116        m_src_ip = src_ip;
117        m_bitfield |= HAS_SRC_IP;
118    }
119
120    void set_src_ipv6(const uint16_t src_ipv6[8]) {
121        for (int i = 0; i < 8; i++) {
122            m_src_ipv6[i] = src_ipv6[i];
123        }
124        m_bitfield |= HAS_SRC_IPV6;
125    }
126
127    void set_next_hop(uint32_t next_hop) {
128        m_next_hop  = next_hop;
129        m_bitfield |= HAS_NEXT_HOP;
130    }
131
132    void set_ipv6_next_hop(const uint16_t next_hop[8]) {
133        for (int i = 0; i < 8; i++) {
134            m_ipv6_next_hop[i] = next_hop[i];
135        }
136        m_bitfield |= HAS_IPV6_NEXT_HOP;
137    }
138
139    /* updates a configuration with a group index member */
140
141    void update(uint32_t index, const ClientCfgDir &cfg) {
142        if (has_src_mac_addr()) {
143            m_src_mac += index;
144        }
145
146        if (has_dst_mac_addr() || has_next_hop() || has_ipv6_next_hop()) {
147            m_dst_mac = cfg.m_resolved_macs[index];
148            m_bitfield |= HAS_DST_MAC;
149        }
150    }
151
152    const uint8_t *get_src_mac_addr() const {
153        assert(has_src_mac_addr());
154        return m_src_mac.GetConstBuffer();
155    }
156
157    const uint8_t *get_dst_mac_addr() const {
158        assert(has_dst_mac_addr());
159        return m_dst_mac.GetConstBuffer();
160    }
161
162    uint16_t get_vlan() const {
163        assert(has_vlan());
164        return m_vlan;
165    }
166};
167
168/**
169 * single client config
170 *
171 */
172class ClientCfg {
173
174public:
175
176    void dump (FILE *fd) const {
177        fprintf(fd, "initiator:\n");
178        m_initiator.dump(fd);
179        fprintf(fd, "responder:\n");
180        m_responder.dump(fd);
181    }
182    void update(uint32_t index, const ClientCfg &cfg) {
183        m_initiator.update(index, cfg.m_initiator);
184        m_responder.update(index, cfg.m_responder);
185    }
186
187    ClientCfgDir m_initiator;
188    ClientCfgDir m_responder;
189};
190
191class ClientCfgCompactEntry {
192    friend class ClientCfgDB;
193 public:
194    uint16_t get_count() {return m_count;}
195    uint16_t get_vlan() {return m_vlan;}
196    uint16_t get_port() {return m_port;}
197    bool is_ipv4() {return m_is_ipv4;}
198    uint32_t get_dst_ip() {return m_next_hop_base.ip;}
199    uint16_t *get_dst_ipv6() {return m_next_hop_base.ipv6;}
200    uint32_t get_src_ip() {return m_src_ip.ip;}
201    uint16_t *get_src_ipv6() {return m_src_ip.ipv6;}
202
203 public:
204    void fill_from_dir(ClientCfgDir cfg, uint8_t port_id);
205
206 private:
207    uint16_t m_count;
208    uint16_t m_vlan;
209    uint8_t m_port;
210    bool m_is_ipv4;
211    union {
212        uint32_t ip;
213        uint16_t ipv6[8];
214    } m_next_hop_base;
215    union {
216        uint32_t ip;
217        uint16_t ipv6[8];
218    } m_src_ip;
219
220};
221
222/******************************** internal section ********************************/
223
224/**
225 * describes a single client config
226 * entry loaded from the config file
227 *
228 */
229class ClientCfgEntry {
230
231public:
232
233    ClientCfgEntry() {
234        reset();
235    }
236
237    void dump(FILE *fd) const;
238    void set_resolved_macs(CManyIPInfo &pretest_result);
239    bool contains(uint32_t ip) const {
240        return ( (ip >= m_ip_start) && (ip <= m_ip_end) );
241    }
242
243    void reset() {
244        m_iterator = 0;
245    }
246
247
248    /**
249     * assings a client config from the group
250     * it will advance MAC addresses andf etc.
251     *
252     * @author imarom (27-Jun-16)
253     *
254     * @param info
255     */
256    void assign(ClientCfg &info) {
257        info = m_cfg;
258        info.update(m_iterator, m_cfg);
259
260        /* advance for the next assign */
261        m_iterator = (m_iterator + 1) % m_count;
262    }
263
264public:
265    uint32_t    m_ip_start;
266    uint32_t    m_ip_end;
267
268    ClientCfg   m_cfg;
269
270    uint32_t    m_count;
271
272private:
273    uint32_t    m_iterator;
274};
275
276/**
277 * holds all the configured clients groups
278 *
279 */
280class ClientCfgDB {
281public:
282
283    ClientCfgDB() {
284        m_is_empty    = true;
285        m_cache_group = NULL;
286        m_under_vlan  = false;
287        m_tg = NULL;
288    }
289
290    void dump(FILE *fd) ;
291
292    /**
293     * if no config file was loaded
294     * this should return true
295     *
296     */
297    bool is_empty() {
298        return m_is_empty;
299    }
300
301    void set_resolved_macs(CManyIPInfo &pretest_result);
302    std::vector<ClientCfgCompactEntry *> get_entry_list();
303
304    /**
305     * loads a YAML file
306     * configuration will be built
307     * according to the YAML config
308     *
309     */
310    void load_yaml_file(const std::string &filename);
311
312    /**
313     * lookup for a specific IP address for
314     * a group that contains this IP
315     *
316     */
317    ClientCfgEntry * lookup(uint32_t ip);
318    ClientCfgEntry * lookup(const std::string &ip);
319    void set_tuple_gen_info(CTupleGenYamlInfo *tg) {m_tg = tg;}
320
321private:
322    void parse_single_group(YAMLParserWrapper &parser, const YAML::Node &node);
323    void parse_dir(YAMLParserWrapper &parser, const YAML::Node &node, ClientCfgDir &dir);
324
325    /**
326     * verify the YAML file loaded in valid
327     *
328     */
329    void verify(const YAMLParserWrapper &parser) const;
330
331    /* maps the IP start value to client groups */
332    std::map<uint32_t, ClientCfgEntry>  m_groups;
333    bool m_under_vlan;
334    CTupleGenYamlInfo * m_tg;
335    ClientCfgEntry * m_cache_group;
336    bool m_is_empty;
337};
338
339#endif /* __TREX_CLIENT_CONFIG_H__ */
340