summaryrefslogtreecommitdiffstats
path: root/src/trex_client_config.cpp
diff options
context:
space:
mode:
authorIdo Barnea <ibarnea@cisco.com>2016-11-15 16:27:08 +0200
committerIdo Barnea <ibarnea@cisco.com>2016-11-21 12:56:28 +0200
commitbf83f301e4fdbf333240af7f316735e35634c5fd (patch)
tree667c001d36a1b1a95b0f6da82d9919977543746c /src/trex_client_config.cpp
parentc39cdf89bee7999ba714eb31e8ec4bc8b5d52a60 (diff)
client config ARP resolve working. Still missing IPv6 support.
Signed-off-by: Ido Barnea <ibarnea@cisco.com>
Diffstat (limited to 'src/trex_client_config.cpp')
-rw-r--r--src/trex_client_config.cpp243
1 files changed, 208 insertions, 35 deletions
diff --git a/src/trex_client_config.cpp b/src/trex_client_config.cpp
index ad71d38e..df5164d6 100644
--- a/src/trex_client_config.cpp
+++ b/src/trex_client_config.cpp
@@ -30,38 +30,184 @@ limitations under the License.
#include "common/basic_utils.h"
#include "bp_sim.h"
+bool ClientCfgDir::need_resolve() const {
+ if (has_next_hop() || has_ipv6_next_hop())
+ return true;
+ else
+ return false;
+}
+
+void ClientCfgDir::set_no_resolve_needed() {
+ m_bitfield &= ~(HAS_DST_MAC | HAS_IPV6_NEXT_HOP | HAS_NEXT_HOP);
+}
+
+void ClientCfgDir::dump(FILE *fd) const {
+ if (has_src_mac_addr()) {
+ fprintf(fd, " src MAC:%s\n", utl_macaddr_to_str(m_src_mac.GetConstBuffer()).c_str());
+ } else {
+ fprintf(fd, " No src MAC\n");
+ }
+ if (has_dst_mac_addr()) {
+ fprintf(fd, " dst MAC:%s\n", utl_macaddr_to_str(m_dst_mac.GetConstBuffer()).c_str());
+ } else {
+ fprintf(fd, " No dst MAC\n");
+ }
+ if (has_vlan()) {
+ fprintf(fd, " vlan:%d\n", m_vlan);
+ } else {
+ fprintf(fd, " No vlan\n");
+ }
+ if (has_next_hop()) {
+ fprintf(fd, " next hop:%s\n", ip_to_str(m_next_hop).c_str());
+ } else {
+ fprintf(fd, " No next hop\n");
+ }
+ if (has_ipv6_next_hop()) {
+ fprintf(fd, " next hop:%s\n", ip_to_str((unsigned char *)m_ipv6_next_hop).c_str());
+ } else {
+ fprintf(fd, " No IPv6 next hop\n");
+ }
+
+ if (m_resolved_macs.size() > 0) {
+ fprintf(fd, " Resolved MAC list:\n");
+ for (int i = 0; i < m_resolved_macs.size(); i++) {
+ fprintf(fd, " %s\n", utl_macaddr_to_str(m_resolved_macs[i].GetConstBuffer()).c_str());
+ }
+ }
+}
+
+void ClientCfgDir::set_resolved_macs(CManyIPInfo &pretest_result, uint16_t count) {
+ uint16_t vlan = has_vlan() ? m_vlan : 0;
+ MacAddress base_mac = m_dst_mac;
+ m_resolved_macs.resize(count);
+
+ for (int i = 0; i < count; i++) {
+ if (need_resolve()) {
+ if (has_next_hop()) {
+ if (!pretest_result.lookup(m_next_hop + i, vlan, m_resolved_macs[i])) {
+ fprintf(stderr, "Failed resolving ip:%x, vlan:%d - exiting\n", m_next_hop+i, vlan);
+ exit(1);
+ }
+ } else {
+ //??? handle ipv6
+ }
+ } else {
+ m_resolved_macs[i] = base_mac;
+ base_mac += 1;
+ }
+ }
+}
+
void
-ClientCfgEntry::dump() const {
+ClientCfgEntry::dump(FILE *fd) const {
std::cout << "IP start: " << ip_to_str(m_ip_start) << "\n";
std::cout << "IP end: " << ip_to_str(m_ip_end) << "\n";
+ fprintf(fd, "count %d\n", m_count);
- //m_cfg.dump();
+ m_cfg.dump(fd);
+}
+
+void ClientCfgEntry::set_resolved_macs(CManyIPInfo &pretest_result) {
+ m_cfg.m_initiator.set_resolved_macs(pretest_result, m_count);
+ m_cfg.m_responder.set_resolved_macs(pretest_result, m_count);
+}
- #if 0
- std::cout << "Init. MAC addr: ";
- for (int i = 0; i < 6; i++) {
- printf("%lx:", ( (m_initiator.m_dst_mac >> ( (6-i) * 8)) & 0xFF ) );
+void ClientCfgCompactEntry::fill_from_dir(ClientCfgDir cfg, uint8_t port_id) {
+ m_port = port_id;
+ if (cfg.has_next_hop()) {
+ m_next_hop_base.ip = cfg.m_next_hop;
+ if (cfg.has_src_ip()) {
+ m_src_ip.ip = cfg.m_src_ip;
+ } else {
+ m_src_ip.ip = 0;
+ }
+ m_is_ipv4 = true;
+ } else if (cfg.has_ipv6_next_hop()) {
+ memcpy(m_next_hop_base.ipv6, cfg.m_ipv6_next_hop, sizeof(m_next_hop_base.ipv6));
+ if (cfg.has_src_ipv6()) {
+ memcpy(m_src_ip.ipv6, cfg.m_src_ipv6, sizeof(m_src_ip.ipv6));
+ } else {
+ memset(m_src_ip.ipv6, 0, sizeof(m_src_ip.ipv6));
+ }
+ m_is_ipv4 = false;
}
- std::cout << "\n";
- std::cout << "Init. VLAN: " << m_initiator.m_vlan << "\n";
+ if (cfg.has_vlan()) {
+ m_vlan = cfg.m_vlan;
+ } else {
+ m_vlan = 0;
+ }
+}
- std::cout << "Res. MAC addr: ";
- for (int i = 0; i < 6; i++) {
- printf("%lx:", ( (m_responder.m_dst_mac >> ( (6-i) * 8)) & 0xFF ) );
+void
+ClientCfgDB::dump(FILE *fd) {
+ fprintf(fd, "**********Client config file start*********\n");
+ fprintf(fd, "vlan: %s is_empty: %s\n"
+ ,m_under_vlan ? "true" : "false"
+ , m_is_empty ? "true" : "false");
+
+ for (std::map<uint32_t, ClientCfgEntry>::iterator it = m_groups.begin(); it != m_groups.end(); ++it) {
+ fprintf(fd, "****%s:****\n", ip_to_str(it->first).c_str());
+ ((ClientCfgEntry)it->second).dump(fd);
}
- std::cout << "\n";
+ fprintf(fd, "**********Client config end*********\n");
+}
- std::cout << "Res. VLAN: " << m_responder.m_vlan << "\n";
- #endif
+void ClientCfgDB::set_resolved_macs(CManyIPInfo &pretest_result) {
+ std::map<uint32_t, ClientCfgEntry>::iterator it;
+ for (it = m_groups.begin(); it != m_groups.end(); it++) {
+ ClientCfgEntry &cfg = it->second;
+ cfg.set_resolved_macs(pretest_result);
+ }
}
+std::vector<ClientCfgCompactEntry *> ClientCfgDB::get_entry_list() {
+ std::vector<ClientCfgCompactEntry *> ret;
+ uint8_t port;
+ bool result;
+
+ assert(m_tg != NULL);
+ for (std::map<uint32_t, ClientCfgEntry>::iterator it = m_groups.begin(); it != m_groups.end(); ++it) {
+ ClientCfgEntry &cfg = it->second;
+ if (cfg.m_cfg.m_initiator.need_resolve() || cfg.m_cfg.m_initiator.need_resolve()) {
+ result = m_tg->find_port(cfg.m_ip_start, cfg.m_ip_end, port);
+ if (! result) {
+ fprintf(stderr, "Error in clinet config range %s - %s.\n"
+ , ip_to_str(cfg.m_ip_start).c_str(), ip_to_str(cfg.m_ip_end).c_str());
+ exit(-1);
+ }
+ if (port == UINT8_MAX) {
+ // if port not found, it means this adderss is not needed. Don't try to resolve.
+ cfg.m_cfg.m_initiator.set_no_resolve_needed();
+ cfg.m_cfg.m_responder.set_no_resolve_needed();
+ } else {
+ if (cfg.m_cfg.m_initiator.need_resolve()) {
+ ClientCfgCompactEntry *init_entry = new ClientCfgCompactEntry();
+ assert(init_entry);
+ init_entry->m_count = ((ClientCfgEntry)it->second).m_count;
+ init_entry->fill_from_dir(((ClientCfgEntry)it->second).m_cfg.m_initiator, port);
+ ret.push_back(init_entry);
+ }
+
+ if (cfg.m_cfg.m_responder.need_resolve()) {
+ ClientCfgCompactEntry *resp_entry = new ClientCfgCompactEntry();
+ assert(resp_entry);
+ resp_entry->m_count = cfg.m_count;
+ resp_entry->fill_from_dir(cfg.m_cfg.m_responder, port + 1);
+ ret.push_back(resp_entry);
+ }
+ }
+ }
+ }
+
+ return ret;
+}
/**
- * loads a YAML file containing
- * the client groups configuration
- *
+ * loads a YAML file containing
+ * the client groups configuration
+ *
*/
void
ClientCfgDB::load_yaml_file(const std::string &filename) {
@@ -93,7 +239,7 @@ ClientCfgDB::load_yaml_file(const std::string &filename) {
/**
* reads a single group of clients from YAML
- *
+ *
*/
void
ClientCfgDB::parse_single_group(YAMLParserWrapper &parser, const YAML::Node &node) {
@@ -116,7 +262,7 @@ ClientCfgDB::parse_single_group(YAMLParserWrapper &parser, const YAML::Node &nod
parse_dir(parser, init, group.m_cfg.m_initiator);
parse_dir(parser, resp, group.m_cfg.m_responder);
-
+
group.m_count = parser.parse_uint(node, "count", 0, UINT64_MAX, 1);
/* add to map with copying */
@@ -124,12 +270,32 @@ ClientCfgDB::parse_single_group(YAMLParserWrapper &parser, const YAML::Node &nod
}
-void
+void
ClientCfgDB::parse_dir(YAMLParserWrapper &parser, const YAML::Node &node, ClientCfgDir &dir) {
+ if (node.FindValue("src_ip")) {
+ dir.set_src_ip(parser.parse_ip(node, "src_ip"));
+ }
+
+ if (node.FindValue("src_ipv6")) {
+ uint16_t ip_num[8];
+ parser.parse_ipv6(node, "src_ipv6", (unsigned char *)&ip_num);
+ dir.set_src_ipv6(ip_num);
+ }
+
+ if (node.FindValue("next_hop")) {
+ dir.set_next_hop(parser.parse_ip(node, "next_hop"));
+ }
+
+ if (node.FindValue("ipv6_next_hop")) {
+ uint16_t ip_num[8];
+ parser.parse_ipv6(node, "ipv6_next_hop", (unsigned char *)&ip_num);
+ dir.set_ipv6_next_hop(ip_num);
+ }
+
if (node.FindValue("src_mac")) {
dir.set_src_mac_addr(parser.parse_mac_addr(node, "src_mac"));
}
-
+
if (node.FindValue("dst_mac")) {
dir.set_dst_mac_addr(parser.parse_mac_addr(node, "dst_mac"));
}
@@ -141,11 +307,20 @@ ClientCfgDB::parse_dir(YAMLParserWrapper &parser, const YAML::Node &node, Client
parser.parse_err("VLAN config was disabled", node["vlan"]);
}
}
+
+ if ((dir.has_next_hop() || dir.has_ipv6_next_hop()) && (dir.has_dst_mac_addr() || dir.has_src_mac_addr())) {
+ parser.parse_err("Should not configure both next_hop/ipv6_next_hop and dst_mac or src_mac", node);
+ }
+
+ if (dir.has_next_hop() && dir.has_ipv6_next_hop()) {
+ parser.parse_err("Should not configure both next_hop and ipv6_next_hop", node);
+ }
+
}
/**
* sanity checks
- *
+ *
* @author imarom (28-Jun-16)
*/
void
@@ -154,7 +329,7 @@ ClientCfgDB::verify(const YAMLParserWrapper &parser) const {
uint32_t monotonic = 0;
/* check that no interval overlaps */
-
+
/* all intervals do not overloap iff when sorted each start/end dots are strong monotonic */
for (const auto &p : m_groups) {
const ClientCfgEntry &group = p.second;
@@ -169,13 +344,13 @@ ClientCfgDB::verify(const YAMLParserWrapper &parser) const {
}
/**
- * lookup function
- * should be fast
- *
+ * lookup function
+ * should be fast
+ *
*/
ClientCfgEntry *
ClientCfgDB::lookup(uint32_t ip) {
-
+
/* a cache to avoid constant search (usually its a range of IPs) */
if ( (m_cache_group) && (m_cache_group->contains(ip)) ) {
return m_cache_group;
@@ -185,7 +360,7 @@ ClientCfgDB::lookup(uint32_t ip) {
m_cache_group = NULL;
std::map<uint32_t ,ClientCfgEntry>::iterator it;
-
+
/* upper bound fetchs the first greater element */
it = m_groups.upper_bound(ip);
@@ -217,12 +392,12 @@ ClientCfgDB::lookup(uint32_t ip) {
/**
* for convenience - search by IP as string
- *
+ *
* @author imarom (28-Jun-16)
- *
- * @param ip
- *
- * @return ClientCfgEntry*
+ *
+ * @param ip
+ *
+ * @return ClientCfgEntry*
*/
ClientCfgEntry *
ClientCfgDB::lookup(const std::string &ip) {
@@ -231,5 +406,3 @@ ClientCfgDB::lookup(const std::string &ip) {
return lookup(addr);
}
-
-