net_wire.c 5.34 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>
Antoine Kaufmann's avatar
Antoine Kaufmann committed
36
37
38

#include <netsim.h>

39
40
static uint64_t sync_period = (500 * 1000ULL); // 500ns
static uint64_t eth_latency = (500 * 1000ULL); // 500ns
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
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
56
{
57
    volatile union cosim_eth_proto_d2n *msg_from = netsim_d2n_poll(from, cur_ts);
Antoine Kaufmann's avatar
Antoine Kaufmann committed
58
59
60
    volatile union cosim_eth_proto_n2d *msg_to;
    volatile struct cosim_eth_proto_d2n_send *tx;
    volatile struct cosim_eth_proto_n2d_recv *rx;
61
    struct pcap_pkthdr ph;
Antoine Kaufmann's avatar
Antoine Kaufmann committed
62
63
64
65
66
67
68
69
70
    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;

71
72
73
74
75
76
77
78
79
80
81
        // 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);
        }

82
        msg_to = netsim_n2d_alloc(to, cur_ts, eth_latency);
Antoine Kaufmann's avatar
Antoine Kaufmann committed
83
84
85
86
87
88
89
90
91
92
93
94
        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");
        }
95
    } else if (type == COSIM_ETH_PROTO_D2N_MSG_SYNC) {
Antoine Kaufmann's avatar
Antoine Kaufmann committed
96
97
98
99
100
101
102
103
104
105
106
    } 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;
107
    uint64_t ts_a, ts_b;
108
    int sync_a, sync_b;
109
    pcap_t *pc = NULL;
Antoine Kaufmann's avatar
Antoine Kaufmann committed
110

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

117
118
119
120
    signal(SIGINT, sigint_handler);
    signal(SIGTERM, sigint_handler);
    signal(SIGUSR1, sigusr1_handler);

121
122
123
124
125
126
127
    if (argc >= 4)
        sync_period = strtoull(argv[3], NULL, 0) * 1000ULL;

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

    if (argc >= 6) {
128
129
130
131
132
133
134
        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;
        }

135
        dumpfile = pcap_dump_open(pc, argv[5]);
136
137
    }

138
139
    sync_a = sync_b = 1;
    if (netsim_init(&nsif_a, argv[1], &sync_a) != 0) {
Antoine Kaufmann's avatar
Antoine Kaufmann committed
140
141
        return -1;
    }
142
    if (netsim_init(&nsif_b, argv[2], &sync_b) != 0) {
Antoine Kaufmann's avatar
Antoine Kaufmann committed
143
144
145
146
        return -1;
    }

    printf("start polling\n");
147
    while (!exiting) {
148
        if (netsim_n2d_sync(&nsif_a, cur_ts, eth_latency, sync_period) != 0) {
149
150
151
            fprintf(stderr, "netsim_n2d_sync(nsif_a) failed\n");
            abort();
        }
152
        if (netsim_n2d_sync(&nsif_b, cur_ts, eth_latency, sync_period) != 0) {
153
154
155
156
157
            fprintf(stderr, "netsim_n2d_sync(nsif_a) failed\n");
            abort();
        }

        do {
158
159
            move_pkt(&nsif_a, &nsif_b);
            move_pkt(&nsif_b, &nsif_a);
160
161
            ts_a = netsim_d2n_timestamp(&nsif_a);
            ts_b = netsim_d2n_timestamp(&nsif_b);
162
163
164
        } while (!exiting &&
            ((sync_a && ts_a <= cur_ts) ||
                (sync_b && ts_b <= cur_ts)));
165
166
167
168
169
170
171

        if (sync_a && sync_b)
            cur_ts = (ts_a <= ts_b ? ts_a : ts_b);
        else if (sync_a)
            cur_ts = ts_a;
        else if (sync_b)
            cur_ts = ts_b;
Antoine Kaufmann's avatar
Antoine Kaufmann committed
172
    }
173

174
175
    if (dumpfile)
        pcap_dump_close(dumpfile);
Antoine Kaufmann's avatar
Antoine Kaufmann committed
176
177
    return 0;
}