"tests/vscode:/vscode.git/clone" did not exist on "8d326e61cfbe5d76e25deca6093ecb22967d634e"
Commit 1eb0180c authored by Jialin Li's avatar Jialin Li
Browse files

add net switch

parent 02c660d6
...@@ -5,7 +5,8 @@ all: \ ...@@ -5,7 +5,8 @@ all: \
corundum_bm/corundum_bm \ corundum_bm/corundum_bm \
i40e_bm/i40e_bm \ i40e_bm/i40e_bm \
net_tap/net_tap \ net_tap/net_tap \
net_wire/net_wire net_wire/net_wire \
net_switch/net_switch
clean: clean:
$(MAKE) -C corundum/ clean $(MAKE) -C corundum/ clean
...@@ -14,6 +15,7 @@ clean: ...@@ -14,6 +15,7 @@ clean:
$(MAKE) -C dummy_nic/ clean $(MAKE) -C dummy_nic/ clean
$(MAKE) -C net_tap/ clean $(MAKE) -C net_tap/ clean
$(MAKE) -C net_wire/ clean $(MAKE) -C net_wire/ clean
$(MAKE) -C net_switch/ clean
$(MAKE) -C nicsim_common/ clean $(MAKE) -C nicsim_common/ clean
$(MAKE) -C netsim_common/ clean $(MAKE) -C netsim_common/ clean
$(MAKE) -C libnicbm/ clean $(MAKE) -C libnicbm/ clean
...@@ -49,6 +51,9 @@ net_tap/net_tap: netsim_common/libnetsim_common.a ...@@ -49,6 +51,9 @@ net_tap/net_tap: netsim_common/libnetsim_common.a
net_wire/net_wire: netsim_common/libnetsim_common.a net_wire/net_wire: netsim_common/libnetsim_common.a
$(MAKE) -C net_wire/ $(MAKE) -C net_wire/
net_switch/net_switch: netsim_common/libnetsim_common.a
$(MAKE) -C net_switch/
nicsim_common/libnicsim_common.a: nicsim_common/libnicsim_common.a:
$(MAKE) -C nicsim_common/ $(MAKE) -C nicsim_common/
......
...@@ -182,6 +182,27 @@ run_wire() { ...@@ -182,6 +182,27 @@ run_wire() {
return $pid return $pid
} }
# Args:
# - Instance name
# - sim instance 1
# - sim instance 2
# - [sim instance 3, ...]
run_switch() {
echo Starting switch $1
args=
for iface in ${@:2}
do
args="$args -s $WORKDIR/eth.$iface"
done
$EHSIM_BASE/net_switch/net_switch \
$args &>$OUTDIR/switch.$1.log &
pid=$!
ALL_PIDS="$ALL_PIDS $pid"
return $pid
}
# Args: # Args:
# - Instance name # - Instance name
# - Port names # - Port names
......
#!/bin/bash
source common-functions.sh
init_out qemu-corundum-bm-echo-switch $1
run_corundum_bm a
run_corundum_bm b
run_corundum_bm c
run_corundum_bm d
sleep 2
run_switch sw a b c d
run_qemu a a build/qemu-echo-server-0.tar
run_qemu b b build/qemu-echo-server-1.tar
run_qemu c c build/qemu-echo-server-2.tar
run_qemu d d build/qemu-echo-client.tar
client_pid=$!
wait $client_pid
cleanup
CPPFLAGS := -I../proto -I../netsim_common/include
CFLAGS := -Wall -Wextra -O3
LD := g++
all: net_switch
net_switch: net_switch.o ../netsim_common/libnetsim_common.a
$(LD) -o $@ $^
clean:
rm -f *.o net_switch
#include <cstdio>
#include <cstdlib>
#include <csignal>
#include <climits>
#include <cstring>
#include <unistd.h>
#include <vector>
#include <unordered_map>
extern "C" {
#include <netsim.h>
};
#define SYNC_PERIOD (500 * 1000ULL) // 500ns
#define ETH_LATENCY (500 * 1000ULL) // 500ns
/* MAC address type */
struct MAC {
const volatile uint8_t *data;
MAC(const volatile uint8_t *data)
: data(data) {}
bool operator==(const MAC &other) const {
for (int i = 0; i < 6; i++) {
if (data[i] != other.data[i]) {
return false;
}
}
return true;
}
};
namespace std {
template <>
struct hash<MAC>
{
size_t operator()(const MAC &m) const {
size_t res = 0;
for (int i = 0; i < 6; i++) {
res = (res << 4) | (res ^ m.data[i]);
}
return res;
}
};
} // namespace std
/* Global variables */
static uint64_t cur_ts = 0;
static int exiting = 0;
static const volatile uint8_t bcast[6] = {0xFF};
static const MAC bcast_addr(bcast);
static std::vector<struct netsim_interface> nsifs;
static std::unordered_map<MAC, int> mac_table;
static void sigint_handler(int dummy)
{
exiting = 1;
}
static void forward_pkt(volatile struct cosim_eth_proto_d2n_send *tx, int port)
{
volatile union cosim_eth_proto_n2d *msg_to;
msg_to = netsim_n2d_alloc(&nsifs[port], cur_ts, ETH_LATENCY);
if (msg_to != NULL) {
volatile struct cosim_eth_proto_n2d_recv *rx;
rx = &msg_to->recv;
rx->len = tx->len;
rx->port = 0;
memcpy((void *)rx->data, (void *)tx->data, tx->len);
// WMB();
rx->own_type = COSIM_ETH_PROTO_N2D_MSG_RECV |
COSIM_ETH_PROTO_N2D_OWN_DEV;
} else {
fprintf(stderr, "forward_pkt: dropping packet\n");
}
}
static void switch_pkt(struct netsim_interface *nsif, int iport)
{
volatile union cosim_eth_proto_d2n *msg_from = netsim_d2n_poll(nsif, cur_ts);
if (msg_from == NULL) {
return;
}
uint8_t type = msg_from->dummy.own_type & COSIM_ETH_PROTO_D2N_MSG_MASK;
if (type == COSIM_ETH_PROTO_D2N_MSG_SEND) {
volatile struct cosim_eth_proto_d2n_send *tx;
tx = &msg_from->send;
// Get MAC addresses
MAC dst(tx->data), src(tx->data+6);
// MAC learning
if (!(src == bcast_addr)) {
mac_table[src] = iport;
}
// L2 forwarding
if (mac_table.count(dst) > 0) {
int eport = mac_table.at(dst);
forward_pkt(tx, eport);
} else {
// Broadcast
for (int eport = 0; eport < nsifs.size(); eport++) {
if (eport != iport) {
// Do not forward to ingress port
forward_pkt(tx, eport);
}
}
}
} else if (type == COSIM_ETH_PROTO_D2N_MSG_SYNC) {
} else {
fprintf(stderr, "switch_pkt: unsupported type=%u\n", type);
abort();
}
netsim_d2n_done(nsif, msg_from);
}
int main(int argc, char *argv[])
{
int c;
// Parse command line argument
while ((c = getopt(argc, argv, "s:")) != -1) {
switch (c) {
case 's': {
struct netsim_interface nsif;
int sync = 1;
if (netsim_init(&nsif, optarg, &sync) != 0) {
return EXIT_FAILURE;
}
nsifs.push_back(nsif);
}
default:
fprintf(stderr, "unknown option %c\n", c);
}
}
if (nsifs.empty()) {
fprintf(stderr, "Usage: net_switch -s SOCKET-A [-s SOCKET-B ...]\n");
return EXIT_FAILURE;
}
signal(SIGINT, sigint_handler);
signal(SIGTERM, sigint_handler);
printf("start polling\n");
while (!exiting) {
// Sync all interfaces
for (auto &nsif : nsifs) {
if (netsim_n2d_sync(&nsif, cur_ts, ETH_LATENCY, SYNC_PERIOD) != 0) {
fprintf(stderr, "netsim_n2d_sync failed\n");
abort();
}
}
// Switch packets
uint64_t min_ts;
do {
min_ts = ULLONG_MAX;
for (int port = 0; port < nsifs.size(); port++) {
auto &nsif = nsifs.at(port);
switch_pkt(&nsif, port);
if (nsif.sync) {
uint64_t ts = netsim_d2n_timestamp(&nsif);
min_ts = ts < min_ts ? ts : min_ts;
}
}
} while (!exiting && (min_ts <= cur_ts));
// Update cur_ts
if (min_ts < ULLONG_MAX) {
cur_ts = min_ts;
}
}
return 0;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment