net_wire.c 5.77 KB
Newer Older
Antoine Kaufmann's avatar
Antoine Kaufmann committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/*
 * Copyright 2020 Max Planck Institute for Software Systems
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#include <fcntl.h>
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
29
#include <signal.h>
Antoine Kaufmann's avatar
Antoine Kaufmann committed
30
31
32
33
34
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <linux/if.h>
#include <linux/if_tun.h>
35
#include <pcap/pcap.h>
36
#include <assert.h>
Antoine Kaufmann's avatar
Antoine Kaufmann committed
37
38
39

#include <netsim.h>

40
41
static uint64_t sync_period = (500 * 1000ULL); // 500ns
static uint64_t eth_latency = (500 * 1000ULL); // 500ns
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
static uint64_t cur_ts;
static int exiting = 0;
static pcap_dumper_t *dumpfile = NULL;

static void sigint_handler(int dummy)
{
    exiting = 1;
}

static void sigusr1_handler(int dummy)
{
    fprintf(stderr, "main_time = %lu\n", cur_ts);
}

static void move_pkt(struct netsim_interface *from, struct netsim_interface *to)
Antoine Kaufmann's avatar
Antoine Kaufmann committed
57
{
58
    volatile union cosim_eth_proto_d2n *msg_from = netsim_d2n_poll(from, cur_ts);
Antoine Kaufmann's avatar
Antoine Kaufmann committed
59
60
61
    volatile union cosim_eth_proto_n2d *msg_to;
    volatile struct cosim_eth_proto_d2n_send *tx;
    volatile struct cosim_eth_proto_n2d_recv *rx;
62
    struct pcap_pkthdr ph;
Antoine Kaufmann's avatar
Antoine Kaufmann committed
63
64
65
66
67
68
69
70
71
    uint8_t type;

    if (msg_from == NULL)
        return;

    type = msg_from->dummy.own_type & COSIM_ETH_PROTO_D2N_MSG_MASK;
    if (type == COSIM_ETH_PROTO_D2N_MSG_SEND) {
        tx = &msg_from->send;

72
73
74
75
76
77
78
79
80
81
82
        // log to pcap file if initialized
        if (dumpfile) {
            memset(&ph, 0, sizeof(ph));
            ph.ts.tv_sec = cur_ts / 1000000000000ULL;
            ph.ts.tv_usec = (cur_ts % 1000000000000ULL) / 1000ULL;
            ph.caplen = tx->len;
            ph.len = tx->len;
            pcap_dump((unsigned char *) dumpfile, &ph,
                    (unsigned char *) tx->data);
        }

83
        msg_to = netsim_n2d_alloc(to, cur_ts, eth_latency);
Antoine Kaufmann's avatar
Antoine Kaufmann committed
84
85
86
87
88
89
90
91
92
93
94
95
        if (msg_to != NULL) {
            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, "move_pkt: dropping packet\n");
        }
96
    } else if (type == COSIM_ETH_PROTO_D2N_MSG_SYNC) {
Antoine Kaufmann's avatar
Antoine Kaufmann committed
97
98
99
100
101
102
103
104
105
106
107
    } else {
        fprintf(stderr, "move_pkt: unsupported type=%u\n", type);
        abort();
    }

    netsim_d2n_done(from, msg_from);
}

int main(int argc, char *argv[])
{
    struct netsim_interface nsif_a, nsif_b;
108
    uint64_t ts_a, ts_b;
109
    int sync_a, sync_b;
110
    pcap_t *pc = NULL;
111
    int sync_mode = SYNC_MODES;
Antoine Kaufmann's avatar
Antoine Kaufmann committed
112

113
114
    if (argc < 3 && argc > 7) {
        fprintf(stderr, "Usage: net_wire SOCKET-A SOCKET-B [SYNC-MODE] [SYNC-PERIOD] "
115
                "[ETH-LATENCY] [PCAP-FILE]\n");
Antoine Kaufmann's avatar
Antoine Kaufmann committed
116
117
118
        return EXIT_FAILURE;
    }

119
120
121
122
    signal(SIGINT, sigint_handler);
    signal(SIGTERM, sigint_handler);
    signal(SIGUSR1, sigusr1_handler);

123
    if (argc >= 4)
124
        sync_mode = strtol(argv[3], NULL, 0);
125
126

    if (argc >= 5)
127
        sync_period = strtoull(argv[4], NULL, 0) * 1000ULL;
128

129
130
131
132
    if (argc >= 6)
        eth_latency = strtoull(argv[5], NULL, 0) * 1000ULL;

    if (argc >= 7) {
133
134
135
136
137
138
139
        pc = pcap_open_dead_with_tstamp_precision(DLT_EN10MB, 65535,
                PCAP_TSTAMP_PRECISION_NANO);
        if (pc == NULL) {
            perror("pcap_open_dead failed");
            return EXIT_FAILURE;
        }

140
        dumpfile = pcap_dump_open(pc, argv[6]);
141
142
    }

143
144
    assert(sync_mode == SYNC_MODES || sync_mode == SYNC_BARRIER);

145
146
    sync_a = sync_b = 1;
    if (netsim_init(&nsif_a, argv[1], &sync_a) != 0) {
Antoine Kaufmann's avatar
Antoine Kaufmann committed
147
148
        return -1;
    }
149
    if (netsim_init(&nsif_b, argv[2], &sync_b) != 0) {
Antoine Kaufmann's avatar
Antoine Kaufmann committed
150
151
152
153
        return -1;
    }

    printf("start polling\n");
154
    while (!exiting) {
155
        if (netsim_n2d_sync(&nsif_a, cur_ts, eth_latency, sync_period, sync_mode) != 0) {
156
157
158
            fprintf(stderr, "netsim_n2d_sync(nsif_a) failed\n");
            abort();
        }
159
        if (netsim_n2d_sync(&nsif_b, cur_ts, eth_latency, sync_period, sync_mode) != 0) {
160
161
162
            fprintf(stderr, "netsim_n2d_sync(nsif_a) failed\n");
            abort();
        }
163
        netsim_advance_epoch(cur_ts, sync_period, sync_mode);
164
165

        do {
166
167
            move_pkt(&nsif_a, &nsif_b);
            move_pkt(&nsif_b, &nsif_a);
168
169
            ts_a = netsim_d2n_timestamp(&nsif_a);
            ts_b = netsim_d2n_timestamp(&nsif_b);
170
171
172
        } while (!exiting &&
            ((sync_a && ts_a <= cur_ts) ||
                (sync_b && ts_b <= cur_ts)));
173
174

        if (sync_a && sync_b)
175
176
            cur_ts = netsim_advance_time(ts_a <= ts_b ? ts_a : ts_b,
                    sync_period, sync_mode);
177
        else if (sync_a)
178
            cur_ts = netsim_advance_time(ts_a, sync_period, sync_mode);
179
        else if (sync_b)
180
            cur_ts = netsim_advance_time(ts_b, sync_period, sync_mode);
Antoine Kaufmann's avatar
Antoine Kaufmann committed
181
    }
182

183
184
    if (dumpfile)
        pcap_dump_close(dumpfile);
Antoine Kaufmann's avatar
Antoine Kaufmann committed
185
186
    return 0;
}