From b227bab13baddd67c4407ddd82e265207c159c16 Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Thu, 1 Mar 2018 11:23:18 +0100 Subject: [PATCH 01/28] fix makefile --- codelab/Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/codelab/Makefile b/codelab/Makefile index cb9a82b..2818168 100644 --- a/codelab/Makefile +++ b/codelab/Makefile @@ -1,4 +1,3 @@ -CC=gcc CFLAGS=-Wall -g -Werror -DSOLUTION PROGS=sink forward swap fe @@ -10,4 +9,4 @@ swap: swap.o fe: fe.o clean: - -rm *.o $(PROGS) + -rm -f *.o $(PROGS) From 48b5c654f5b6a65283eb373ffb9feafb5add366d Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Thu, 1 Mar 2018 11:28:57 +0100 Subject: [PATCH 02/28] codelab: sink: fix include directive --- codelab/sink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codelab/sink.c b/codelab/sink.c index 222e7d9..9d6ab3a 100644 --- a/codelab/sink.c +++ b/codelab/sink.c @@ -14,7 +14,7 @@ #include #define NETMAP_WITH_LIBS #include -#include +#include #include #include #include From f05502c8dcc0d82c45b08ce7abdf6a681e7c7292 Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Thu, 1 Mar 2018 11:32:34 +0100 Subject: [PATCH 03/28] sink: add missing sys/socket.h include --- codelab/sink.c | 1 + 1 file changed, 1 insertion(+) diff --git a/codelab/sink.c b/codelab/sink.c index 9d6ab3a..6c4b0e7 100644 --- a/codelab/sink.c +++ b/codelab/sink.c @@ -14,6 +14,7 @@ #include #define NETMAP_WITH_LIBS #include +#include #include #include #include From b16940b0e7a693a3e7d98d07c4e40a2647f9bc09 Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Thu, 1 Mar 2018 11:34:41 +0100 Subject: [PATCH 04/28] sink: add missing include for netinet/in.h --- codelab/sink.c | 1 + 1 file changed, 1 insertion(+) diff --git a/codelab/sink.c b/codelab/sink.c index 6c4b0e7..9e8bfe5 100644 --- a/codelab/sink.c +++ b/codelab/sink.c @@ -15,6 +15,7 @@ #define NETMAP_WITH_LIBS #include #include +#include #include #include #include From 0f2526aeac9dc6b11b968b6d77e44ca3c9a39183 Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Thu, 1 Mar 2018 11:36:32 +0100 Subject: [PATCH 05/28] sink: use struct ip in place of struct iphdr --- codelab/sink.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/codelab/sink.c b/codelab/sink.c index 9e8bfe5..7774d3c 100644 --- a/codelab/sink.c +++ b/codelab/sink.c @@ -33,7 +33,7 @@ static inline int udp_port_match(const char *buf, unsigned len, int udp_port) { struct ether_header *ethh; - struct iphdr *iph; + struct ip *iph; struct udphdr *udph; ethh = (struct ether_header *)buf; @@ -41,8 +41,8 @@ udp_port_match(const char *buf, unsigned len, int udp_port) /* Filter out non-IP traffic. */ return 0; } - iph = (struct iphdr *)(ethh + 1); - if (iph->protocol != IPPROTO_UDP) { + iph = (struct ip *)(ethh + 1); + if (iph->ip_p != IPPROTO_UDP) { /* Filter out non-UDP traffic. */ return 0; } From 08c2b552368668f300a2e6ac1a0d7bab10e03fa8 Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Thu, 1 Mar 2018 11:37:41 +0100 Subject: [PATCH 06/28] codelab: reformat --- .clang-format | 112 +++++++++++++++++++++++++++++++++++++ codelab/fe.c | 137 +++++++++++++++++++++++----------------------- codelab/forward.c | 87 ++++++++++++++--------------- codelab/sink.c | 42 +++++++------- codelab/swap.c | 60 ++++++++++---------- 5 files changed, 275 insertions(+), 163 deletions(-) create mode 100644 .clang-format diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..85ce4c3 --- /dev/null +++ b/.clang-format @@ -0,0 +1,112 @@ +--- +Language: Cpp +# BasedOnStyle: Google +AccessModifierOffset: -4 +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: true +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: Right +AlignOperands: true +AlignTrailingComments: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: All +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: TopLevelDefinitions +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: true +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterClass: false + AfterControlStatement: false + AfterEnum: false + AfterFunction: true + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + BeforeCatch: false + BeforeElse: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Custom +BreakBeforeInheritanceComma: false +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeColon +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 80 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: true +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH + - list_for_each_entry + - list_for_each_entry_safe + - hlist_for_each_entry + - rb_list_foreach + - rb_list_foreach_safe +IncludeCategories: + - Regex: '^<.*\.h>' + Priority: 1 + - Regex: '^<.*' + Priority: 2 + - Regex: '.*' + Priority: 3 +IncludeIsMainRegex: '([-_](test|unittest))?$' +IndentCaseLabels: false +IndentWidth: 4 +IndentWrappedFunctionNames: false +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: false +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBlockIndentWidth: 4 +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: false +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 1 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 200 +PointerAlignment: Right +ReflowComments: true +SortIncludes: false +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeParens: ControlStatements +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInContainerLiterals: false +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Auto +TabWidth: 4 +UseTab: Never +... diff --git a/codelab/fe.c b/codelab/fe.c index 66a9625..8a033db 100644 --- a/codelab/fe.c +++ b/codelab/fe.c @@ -23,11 +23,11 @@ #include #include -static int stop = 0; +static int stop = 0; static unsigned long long fwdback = 0; -static unsigned long long fwda = 0; -static unsigned long long fwdb = 0; -static unsigned long long tot = 0; +static unsigned long long fwda = 0; +static unsigned long long fwdb = 0; +static unsigned long long tot = 0; static void sigint_handler(int signum) @@ -40,13 +40,13 @@ rx_ready(struct nm_desc *nmd) { unsigned int ri; - for (ri = nmd->first_rx_ring; ri <= nmd->last_rx_ring; ri ++) { - struct netmap_ring *ring; + for (ri = nmd->first_rx_ring; ri <= nmd->last_rx_ring; ri++) { + struct netmap_ring *ring; - ring = NETMAP_RXRING(nmd->nifp, ri); - if (nm_ring_space(ring)) { - return 1; /* there is something to read */ - } + ring = NETMAP_RXRING(nmd->nifp, ri); + if (nm_ring_space(ring)) { + return 1; /* there is something to read */ + } } return 0; @@ -75,7 +75,6 @@ pkt_get_udp_port(const char *buf) return ntohs(udph->dest); } - static void forward_pkts(struct nm_desc *src, struct nm_desc *dst) { @@ -90,8 +89,8 @@ forward_pkts(struct nm_desc *src, struct nm_desc *dst) rxring = NETMAP_RXRING(src->nifp, si); txring = NETMAP_TXRING(dst->nifp, di); - nrx = nm_ring_space(rxring); - ntx = nm_ring_space(txring); + nrx = nm_ring_space(rxring); + ntx = nm_ring_space(txring); if (nrx == 0) { si++; continue; @@ -101,25 +100,25 @@ forward_pkts(struct nm_desc *src, struct nm_desc *dst) continue; } - rxhead = rxring->head; - txhead = txring->head; - for (; nrx > 0 && ntx > 0; - nrx --, rxhead = nm_ring_next(rxring, rxhead), tot ++) { + rxhead = rxring->head; + txhead = txring->head; + for (; nrx > 0 && ntx > 0; + nrx--, rxhead = nm_ring_next(rxring, rxhead), tot++) { struct netmap_slot *rs = &rxring->slot[rxhead]; struct netmap_slot *ts = &txring->slot[txhead]; - char *rxbuf = NETMAP_BUF(rxring, rs->buf_idx); - char *txbuf = NETMAP_BUF(txring, ts->buf_idx); + char *rxbuf = NETMAP_BUF(rxring, rs->buf_idx); + char *txbuf = NETMAP_BUF(txring, ts->buf_idx); ts->len = rs->len; memcpy(txbuf, rxbuf, ts->len); txhead = nm_ring_next(txring, txhead); - ntx --; - fwdback ++; - tot ++; + ntx--; + fwdback++; + tot++; } /* Update state of netmap ring. */ - rxring->head = rxring->cur = rxhead; - txring->head = txring->cur = txhead; + rxring->head = rxring->cur = rxhead; + txring->head = txring->cur = txhead; } } @@ -134,11 +133,11 @@ main_loop(const char *netmap_port_one, const char *netmap_port_two, nmd_one = nm_open(netmap_port_one, NULL, 0, NULL); if (nmd_one == NULL) { if (!errno) { - printf("Failed to nm_open(%s): not a netmap port\n", - netmap_port_one); + printf("Failed to nm_open(%s): not a netmap port\n", + netmap_port_one); } else { - printf("Failed to nm_open(%s): %s\n", netmap_port_one, - strerror(errno)); + printf("Failed to nm_open(%s): %s\n", netmap_port_one, + strerror(errno)); } return -1; } @@ -159,7 +158,7 @@ main_loop(const char *netmap_port_one, const char *netmap_port_two, if (nmd_three == NULL) { if (!errno) { printf("Failed to nm_open(%s): not a netmap port\n", - netmap_port_three); + netmap_port_three); } else { printf("Failed to nm_open(%s): %s\n", netmap_port_three, strerror(errno)); @@ -168,7 +167,6 @@ main_loop(const char *netmap_port_one, const char *netmap_port_two, } while (!stop) { - /* Forward traffic from ports two and three back to port one. */ forward_pkts(nmd_two, nmd_one); forward_pkts(nmd_three, nmd_one); @@ -191,19 +189,20 @@ usage(char **argv) { printf("usage: %s [-h] [-i NETMAP_PORT_ONE] " "[-i NETMAP_PORT_TWO] [-i NETMAP_PORT_THREE] " - "[-p UDP_PORT_A] [-p UDP_PORT_B]\n", argv[0]); + "[-p UDP_PORT_A] [-p UDP_PORT_B]\n", + argv[0]); exit(EXIT_SUCCESS); } int main(int argc, char **argv) { - const char *netmap_port_one = NULL; - const char *netmap_port_two = NULL; + const char *netmap_port_one = NULL; + const char *netmap_port_two = NULL; const char *netmap_port_three = NULL; int udp_port; - int udp_port_a = 8000; - int udp_port_b = 8001; + int udp_port_a = 8000; + int udp_port_b = 8001; int udp_port_args = 0; struct sigaction sa; int opt; @@ -211,41 +210,41 @@ main(int argc, char **argv) while ((opt = getopt(argc, argv, "hi:p:")) != -1) { switch (opt) { - case 'h': + case 'h': + usage(argv); + return 0; + + case 'i': + if (netmap_port_one == NULL) { + netmap_port_one = optarg; + } else if (netmap_port_two == NULL) { + netmap_port_two = optarg; + } else if (netmap_port_three == NULL) { + netmap_port_three = optarg; + } + break; + + case 'p': + udp_port = atoi(optarg); + if (udp_port <= 0 || udp_port >= 65535) { + printf(" invalid UDP port %s\n", optarg); usage(argv); - return 0; - - case 'i': - if (netmap_port_one == NULL) { - netmap_port_one = optarg; - } else if (netmap_port_two == NULL) { - netmap_port_two = optarg; - } else if (netmap_port_three == NULL) { - netmap_port_three = optarg; - } + } + switch (udp_port_args) { + case 0: + udp_port_a = udp_port; break; - - case 'p': - udp_port = atoi(optarg); - if (udp_port <= 0 || udp_port >= 65535) { - printf(" invalid UDP port %s\n", optarg); - usage(argv); - } - switch (udp_port_args) { - case 0: - udp_port_a = udp_port; - break; - case 1: - udp_port_b = udp_port; - break; - } - udp_port_args ++; + case 1: + udp_port_b = udp_port; break; + } + udp_port_args++; + break; - default: - printf(" unrecognized option '-%c'\n", opt); - usage(argv); - return -1; + default: + printf(" unrecognized option '-%c'\n", opt); + usage(argv); + return -1; } } @@ -263,7 +262,7 @@ main(int argc, char **argv) sa.sa_handler = sigint_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; - ret = sigaction(SIGINT, &sa, NULL); + ret = sigaction(SIGINT, &sa, NULL); if (ret) { perror("sigaction(SIGINT)"); exit(EXIT_FAILURE); @@ -276,8 +275,8 @@ main(int argc, char **argv) printf("UDP port A: %d\n", udp_port_a); printf("UDP port B: %d\n", udp_port_b); - main_loop(netmap_port_one, netmap_port_two, netmap_port_three, - udp_port_a, udp_port_b); + main_loop(netmap_port_one, netmap_port_two, netmap_port_three, udp_port_a, + udp_port_b); return 0; } diff --git a/codelab/forward.c b/codelab/forward.c index 2e9c35b..d40ecc7 100644 --- a/codelab/forward.c +++ b/codelab/forward.c @@ -20,7 +20,7 @@ #include #include -static int stop = 0; +static int stop = 0; static unsigned long long fwd = 0; static unsigned long long tot = 0; @@ -35,13 +35,13 @@ rx_ready(struct nm_desc *nmd) { unsigned int ri; - for (ri = nmd->first_rx_ring; ri <= nmd->last_rx_ring; ri ++) { - struct netmap_ring *ring; + for (ri = nmd->first_rx_ring; ri <= nmd->last_rx_ring; ri++) { + struct netmap_ring *ring; - ring = NETMAP_RXRING(nmd->nifp, ri); - if (nm_ring_space(ring)) { - return 1; /* there is something to read */ - } + ring = NETMAP_RXRING(nmd->nifp, ri); + if (nm_ring_space(ring)) { + return 1; /* there is something to read */ + } } return 0; @@ -78,9 +78,9 @@ pkt_select(const char *buf, int udp_port) return 1; } - static int -main_loop(const char *netmap_port_one, const char *netmap_port_two, int udp_port) +main_loop(const char *netmap_port_one, const char *netmap_port_two, + int udp_port) { struct nm_desc *nmd_one; struct nm_desc *nmd_two; @@ -115,18 +115,18 @@ main_loop(const char *netmap_port_one, const char *netmap_port_two, int udp_port printf("zerocopy %sabled\n", zerocopy ? "en" : "dis"); while (!stop) { - struct pollfd pfd[2]; - pfd[0].fd = nmd_one->fd; - pfd[0].events = 0; - pfd[1].fd = nmd_two->fd; - pfd[1].events = 0; - /* if port one has RX packets then - * POLLOUT on port two else POLLIN on + struct pollfd pfd[2]; + pfd[0].fd = nmd_one->fd; + pfd[0].events = 0; + pfd[1].fd = nmd_two->fd; + pfd[1].events = 0; + /* if port one has RX packets then + * POLLOUT on port two else POLLIN on * port one */ poll(pfd, 2, 1000); - /* try to copy as many packets as possible + /* try to copy as many packets as possible * from port 1 to port 2 */ } @@ -144,7 +144,8 @@ static void usage(char **argv) { printf("usage: %s [-h] [-p UDP_PORT] [-i NETMAP_PORT_ONE] " - "[-i NETMAP_PORT_TWO]\n", argv[0]); + "[-i NETMAP_PORT_TWO]\n", + argv[0]); exit(EXIT_SUCCESS); } @@ -153,37 +154,37 @@ main(int argc, char **argv) { const char *netmap_port_one = NULL; const char *netmap_port_two = NULL; - int udp_port = 0; /* zero means select everything */ + int udp_port = 0; /* zero means select everything */ struct sigaction sa; int opt; int ret; while ((opt = getopt(argc, argv, "hi:p:")) != -1) { switch (opt) { - case 'h': - usage(argv); - return 0; - - case 'i': - if (netmap_port_one == NULL) { - netmap_port_one = optarg; - } else if (netmap_port_two == NULL) { - netmap_port_two = optarg; - } - break; - - case 'p': - udp_port = atoi(optarg); - if (udp_port < 0 || udp_port >= 65535) { - printf(" invalid UDP port %s\n", optarg); - usage(argv); - } - break; - - default: - printf(" unrecognized option '-%c'\n", opt); + case 'h': + usage(argv); + return 0; + + case 'i': + if (netmap_port_one == NULL) { + netmap_port_one = optarg; + } else if (netmap_port_two == NULL) { + netmap_port_two = optarg; + } + break; + + case 'p': + udp_port = atoi(optarg); + if (udp_port < 0 || udp_port >= 65535) { + printf(" invalid UDP port %s\n", optarg); usage(argv); - return -1; + } + break; + + default: + printf(" unrecognized option '-%c'\n", opt); + usage(argv); + return -1; } } @@ -201,7 +202,7 @@ main(int argc, char **argv) sa.sa_handler = sigint_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; - ret = sigaction(SIGINT, &sa, NULL); + ret = sigaction(SIGINT, &sa, NULL); if (ret) { perror("sigaction(SIGINT)"); exit(EXIT_FAILURE); diff --git a/codelab/sink.c b/codelab/sink.c index 7774d3c..4c6500e 100644 --- a/codelab/sink.c +++ b/codelab/sink.c @@ -76,33 +76,33 @@ int main(int argc, char **argv) { const char *netmap_port = NULL; - int udp_port = 8000; + int udp_port = 8000; struct sigaction sa; int opt; int ret; while ((opt = getopt(argc, argv, "hi:p:")) != -1) { switch (opt) { - case 'h': + case 'h': + usage(argv); + return 0; + + case 'i': + netmap_port = optarg; + break; + + case 'p': + udp_port = atoi(optarg); + if (udp_port <= 0 || udp_port >= 65535) { + printf(" invalid UDP port %s\n", optarg); usage(argv); - return 0; - - case 'i': - netmap_port = optarg; - break; - - case 'p': - udp_port = atoi(optarg); - if (udp_port <= 0 || udp_port >= 65535) { - printf(" invalid UDP port %s\n", optarg); - usage(argv); - } - break; - - default: - printf(" unrecognized option '-%c'\n", opt); - usage(argv); - return -1; + } + break; + + default: + printf(" unrecognized option '-%c'\n", opt); + usage(argv); + return -1; } } @@ -115,7 +115,7 @@ main(int argc, char **argv) sa.sa_handler = sigint_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; - ret = sigaction(SIGINT, &sa, NULL); + ret = sigaction(SIGINT, &sa, NULL); if (ret) { perror("sigaction(SIGINT)"); exit(EXIT_FAILURE); diff --git a/codelab/swap.c b/codelab/swap.c index 8cb5c02..bde4368 100644 --- a/codelab/swap.c +++ b/codelab/swap.c @@ -20,9 +20,9 @@ #include #include -static int stop = 0; +static int stop = 0; static unsigned long long swapped = 0; -static unsigned long long tot = 0; +static unsigned long long tot = 0; static void sigint_handler(int signum) @@ -35,13 +35,13 @@ rx_ready(struct nm_desc *nmd) { unsigned int ri; - for (ri = nmd->first_rx_ring; ri <= nmd->last_rx_ring; ri ++) { - struct netmap_ring *ring; + for (ri = nmd->first_rx_ring; ri <= nmd->last_rx_ring; ri++) { + struct netmap_ring *ring; - ring = NETMAP_RXRING(nmd->nifp, ri); - if (nm_ring_space(ring)) { - return 1; /* there is something to read */ - } + ring = NETMAP_RXRING(nmd->nifp, ri); + if (nm_ring_space(ring)) { + return 1; /* there is something to read */ + } } return 0; @@ -67,15 +67,14 @@ pkt_udp_port_swap(char *buf) /* Filter out non-UDP traffic. */ return 0; } - udph = (struct udphdr *)(iph + 1); - tmp = udph->source; + udph = (struct udphdr *)(iph + 1); + tmp = udph->source; udph->source = udph->dest; - udph->dest = tmp; + udph->dest = tmp; return 1; } - static int main_loop(const char *netmap_port_one, const char *netmap_port_two) { @@ -127,7 +126,8 @@ static void usage(char **argv) { printf("usage: %s [-h] [-i NETMAP_PORT_ONE] " - "[-i NETMAP_PORT_TWO]\n", argv[0]); + "[-i NETMAP_PORT_TWO]\n", + argv[0]); exit(EXIT_SUCCESS); } @@ -142,22 +142,22 @@ main(int argc, char **argv) while ((opt = getopt(argc, argv, "hi:p:")) != -1) { switch (opt) { - case 'h': - usage(argv); - return 0; - - case 'i': - if (netmap_port_one == NULL) { - netmap_port_one = optarg; - } else if (netmap_port_two == NULL) { - netmap_port_two = optarg; - } - break; - - default: - printf(" unrecognized option '-%c'\n", opt); - usage(argv); - return -1; + case 'h': + usage(argv); + return 0; + + case 'i': + if (netmap_port_one == NULL) { + netmap_port_one = optarg; + } else if (netmap_port_two == NULL) { + netmap_port_two = optarg; + } + break; + + default: + printf(" unrecognized option '-%c'\n", opt); + usage(argv); + return -1; } } @@ -175,7 +175,7 @@ main(int argc, char **argv) sa.sa_handler = sigint_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; - ret = sigaction(SIGINT, &sa, NULL); + ret = sigaction(SIGINT, &sa, NULL); if (ret) { perror("sigaction(SIGINT)"); exit(EXIT_FAILURE); From 3a5c2ee929dbe74a36e7a3efbbef2db37bb7637a Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Thu, 1 Mar 2018 11:42:17 +0100 Subject: [PATCH 07/28] codelab: struct udphdr: use BSD flavor --- codelab/sink.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/codelab/sink.c b/codelab/sink.c index 4c6500e..81fba00 100644 --- a/codelab/sink.c +++ b/codelab/sink.c @@ -21,6 +21,7 @@ #include #include + static int stop = 0; static void @@ -49,7 +50,7 @@ udp_port_match(const char *buf, unsigned len, int udp_port) udph = (struct udphdr *)(iph + 1); /* Match the destination port. */ - if (udph->dest == htons(udp_port)) { + if (udph->uh_dport == htons(udp_port)) { return 1; } From cd84c62db61d0e4221c1d25634e8e9efa3f65a8d Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Thu, 1 Mar 2018 11:43:51 +0100 Subject: [PATCH 08/28] sink: silence the compiler --- codelab/sink.c | 1 + 1 file changed, 1 insertion(+) diff --git a/codelab/sink.c b/codelab/sink.c index 81fba00..832ecef 100644 --- a/codelab/sink.c +++ b/codelab/sink.c @@ -61,6 +61,7 @@ static int main_loop(const char *netmap_port, int udp_port) { while (!stop) { + (void)udp_port_match; /* silence the compiler */ } return 0; From 9e721c65cf23b2c5bfdf66addf1d6694b43641f9 Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Thu, 1 Mar 2018 11:47:56 +0100 Subject: [PATCH 09/28] codelab: fix forward and swap --- codelab/forward.c | 12 +++++++----- codelab/swap.c | 16 +++++++++------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/codelab/forward.c b/codelab/forward.c index d40ecc7..447640a 100644 --- a/codelab/forward.c +++ b/codelab/forward.c @@ -15,7 +15,9 @@ #include #define NETMAP_WITH_LIBS #include -#include +#include +#include +#include #include #include #include @@ -51,7 +53,7 @@ static inline int pkt_select(const char *buf, int udp_port) { struct ether_header *ethh; - struct iphdr *iph; + struct ip *iph; struct udphdr *udph; if (udp_port == 0) { @@ -63,15 +65,15 @@ pkt_select(const char *buf, int udp_port) /* Filter out non-IP traffic. */ return 0; } - iph = (struct iphdr *)(ethh + 1); - if (iph->protocol != IPPROTO_UDP) { + iph = (struct ip *)(ethh + 1); + if (iph->ip_p != IPPROTO_UDP) { /* Filter out non-UDP traffic. */ return 0; } udph = (struct udphdr *)(iph + 1); /* Match the destination port. */ - if (udph->dest != htons(udp_port)) { + if (udph->uh_dport != htons(udp_port)) { return 0; } diff --git a/codelab/swap.c b/codelab/swap.c index bde4368..bae72dd 100644 --- a/codelab/swap.c +++ b/codelab/swap.c @@ -15,7 +15,9 @@ #include #define NETMAP_WITH_LIBS #include -#include +#include +#include +#include #include #include #include @@ -53,7 +55,7 @@ static inline int pkt_udp_port_swap(char *buf) { struct ether_header *ethh; - struct iphdr *iph; + struct ip *iph; struct udphdr *udph; uint16_t tmp; @@ -62,15 +64,15 @@ pkt_udp_port_swap(char *buf) /* Filter out non-IP traffic. */ return 0; } - iph = (struct iphdr *)(ethh + 1); - if (iph->protocol != IPPROTO_UDP) { + iph = (struct ip *)(ethh + 1); + if (iph->ip_p != IPPROTO_UDP) { /* Filter out non-UDP traffic. */ return 0; } udph = (struct udphdr *)(iph + 1); - tmp = udph->source; - udph->source = udph->dest; - udph->dest = tmp; + tmp = udph->uh_sport; + udph->uh_sport = udph->uh_dport; + udph->uh_dport = tmp; return 1; } From faf7c498834b96b680119a4b53b01fff982e04c0 Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Thu, 1 Mar 2018 11:56:21 +0100 Subject: [PATCH 10/28] codelab: fe: apply compatibility fixes --- codelab/fe.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/codelab/fe.c b/codelab/fe.c index 8a033db..c02fcfa 100644 --- a/codelab/fe.c +++ b/codelab/fe.c @@ -18,7 +18,9 @@ #include #define NETMAP_WITH_LIBS #include -#include +#include +#include +#include #include #include #include @@ -56,7 +58,7 @@ static inline int pkt_get_udp_port(const char *buf) { struct ether_header *ethh; - struct iphdr *iph; + struct ip *iph; struct udphdr *udph; ethh = (struct ether_header *)buf; @@ -64,15 +66,15 @@ pkt_get_udp_port(const char *buf) /* Filter out non-IP traffic. */ return 0; } - iph = (struct iphdr *)(ethh + 1); - if (iph->protocol != IPPROTO_UDP) { + iph = (struct ip *)(ethh + 1); + if (iph->ip_p != IPPROTO_UDP) { /* Filter out non-UDP traffic. */ return 0; } udph = (struct udphdr *)(iph + 1); /* Return destination port. */ - return ntohs(udph->dest); + return ntohs(udph->uh_dport); } static void From 04ae782d02e99d94c214da88a60e84adf03cca9e Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Thu, 1 Mar 2018 11:58:42 +0100 Subject: [PATCH 11/28] codelab: forward: fix compiler warning --- codelab/forward.c | 2 ++ codelab/sink.c | 4 ++-- codelab/swap.c | 6 +++--- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/codelab/forward.c b/codelab/forward.c index 447640a..0cfead9 100644 --- a/codelab/forward.c +++ b/codelab/forward.c @@ -217,5 +217,7 @@ main(int argc, char **argv) main_loop(netmap_port_one, netmap_port_two, udp_port); + (void)pkt_select; /* silence the compiler */ + return 0; } diff --git a/codelab/sink.c b/codelab/sink.c index 832ecef..fbfb618 100644 --- a/codelab/sink.c +++ b/codelab/sink.c @@ -21,7 +21,6 @@ #include #include - static int stop = 0; static void @@ -61,7 +60,6 @@ static int main_loop(const char *netmap_port, int udp_port) { while (!stop) { - (void)udp_port_match; /* silence the compiler */ } return 0; @@ -128,5 +126,7 @@ main(int argc, char **argv) main_loop(netmap_port, udp_port); + (void)udp_port_match; /* silence the compiler */ + return 0; } diff --git a/codelab/swap.c b/codelab/swap.c index bae72dd..40c118c 100644 --- a/codelab/swap.c +++ b/codelab/swap.c @@ -69,10 +69,10 @@ pkt_udp_port_swap(char *buf) /* Filter out non-UDP traffic. */ return 0; } - udph = (struct udphdr *)(iph + 1); - tmp = udph->uh_sport; + udph = (struct udphdr *)(iph + 1); + tmp = udph->uh_sport; udph->uh_sport = udph->uh_dport; - udph->uh_dport = tmp; + udph->uh_dport = tmp; return 1; } From 1d6fe09e53f586b370cd70b11d11722e1e58285b Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Thu, 1 Mar 2018 12:00:49 +0100 Subject: [PATCH 12/28] codelab: swap: fix compiler warning --- codelab/swap.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/codelab/swap.c b/codelab/swap.c index 40c118c..ddfe325 100644 --- a/codelab/swap.c +++ b/codelab/swap.c @@ -189,5 +189,7 @@ main(int argc, char **argv) main_loop(netmap_port_one, netmap_port_two); + (void) pkt_udp_port_swap; + return 0; } From a0b90f4b897869526778f65817e4521a456acaca Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Thu, 1 Mar 2018 12:01:46 +0100 Subject: [PATCH 13/28] codelab: fe: fix warning --- codelab/fe.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/codelab/fe.c b/codelab/fe.c index c02fcfa..63b299a 100644 --- a/codelab/fe.c +++ b/codelab/fe.c @@ -280,5 +280,7 @@ main(int argc, char **argv) main_loop(netmap_port_one, netmap_port_two, netmap_port_three, udp_port_a, udp_port_b); + (void) pkt_get_udp_port; + return 0; } From 670dc10802e9650c8211657c221931cd0e32071b Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Thu, 1 Mar 2018 12:15:11 +0100 Subject: [PATCH 14/28] solutions: apply codelab fixes --- solutions/Makefile | 3 +- solutions/fe.c | 149 +++++++++++++++++++++++--------------------- solutions/forward.c | 84 +++++++++++++------------ solutions/sink.c | 54 ++++++++-------- solutions/swap.c | 73 ++++++++++++---------- 5 files changed, 191 insertions(+), 172 deletions(-) diff --git a/solutions/Makefile b/solutions/Makefile index cb9a82b..2818168 100644 --- a/solutions/Makefile +++ b/solutions/Makefile @@ -1,4 +1,3 @@ -CC=gcc CFLAGS=-Wall -g -Werror -DSOLUTION PROGS=sink forward swap fe @@ -10,4 +9,4 @@ swap: swap.o fe: fe.o clean: - -rm *.o $(PROGS) + -rm -f *.o $(PROGS) diff --git a/solutions/fe.c b/solutions/fe.c index 36b7936..d373237 100644 --- a/solutions/fe.c +++ b/solutions/fe.c @@ -18,16 +18,18 @@ #include #define NETMAP_WITH_LIBS #include -#include +#include +#include +#include #include #include #include -static int stop = 0; +static int stop = 0; static unsigned long long fwdback = 0; -static unsigned long long fwda = 0; -static unsigned long long fwdb = 0; -static unsigned long long tot = 0; +static unsigned long long fwda = 0; +static unsigned long long fwdb = 0; +static unsigned long long tot = 0; static void sigint_handler(int signum) @@ -40,13 +42,13 @@ rx_ready(struct nm_desc *nmd) { unsigned int ri; - for (ri = nmd->first_rx_ring; ri <= nmd->last_rx_ring; ri ++) { - struct netmap_ring *ring; + for (ri = nmd->first_rx_ring; ri <= nmd->last_rx_ring; ri++) { + struct netmap_ring *ring; - ring = NETMAP_RXRING(nmd->nifp, ri); - if (nm_ring_space(ring)) { - return 1; /* there is something to read */ - } + ring = NETMAP_RXRING(nmd->nifp, ri); + if (nm_ring_space(ring)) { + return 1; /* there is something to read */ + } } return 0; @@ -56,7 +58,7 @@ static inline int pkt_get_udp_port(const char *buf) { struct ether_header *ethh; - struct iphdr *iph; + struct ip *iph; struct udphdr *udph; ethh = (struct ether_header *)buf; @@ -64,15 +66,15 @@ pkt_get_udp_port(const char *buf) /* Filter out non-IP traffic. */ return 0; } - iph = (struct iphdr *)(ethh + 1); - if (iph->protocol != IPPROTO_UDP) { + iph = (struct ip *)(ethh + 1); + if (iph->ip_p != IPPROTO_UDP) { /* Filter out non-UDP traffic. */ return 0; } udph = (struct udphdr *)(iph + 1); /* Return destination port. */ - return ntohs(udph->dest); + return ntohs(udph->uh_dport); } #ifdef SOLUTION @@ -148,8 +150,8 @@ forward_pkts(struct nm_desc *src, struct nm_desc *dst) rxring = NETMAP_RXRING(src->nifp, si); txring = NETMAP_TXRING(dst->nifp, di); - nrx = nm_ring_space(rxring); - ntx = nm_ring_space(txring); + nrx = nm_ring_space(rxring); + ntx = nm_ring_space(txring); if (nrx == 0) { si++; continue; @@ -159,25 +161,25 @@ forward_pkts(struct nm_desc *src, struct nm_desc *dst) continue; } - rxhead = rxring->head; - txhead = txring->head; - for (; nrx > 0 && ntx > 0; - nrx --, rxhead = nm_ring_next(rxring, rxhead), tot ++) { + rxhead = rxring->head; + txhead = txring->head; + for (; nrx > 0 && ntx > 0; + nrx--, rxhead = nm_ring_next(rxring, rxhead), tot++) { struct netmap_slot *rs = &rxring->slot[rxhead]; struct netmap_slot *ts = &txring->slot[txhead]; - char *rxbuf = NETMAP_BUF(rxring, rs->buf_idx); - char *txbuf = NETMAP_BUF(txring, ts->buf_idx); + char *rxbuf = NETMAP_BUF(rxring, rs->buf_idx); + char *txbuf = NETMAP_BUF(txring, ts->buf_idx); ts->len = rs->len; memcpy(txbuf, rxbuf, ts->len); txhead = nm_ring_next(txring, txhead); - ntx --; - fwdback ++; - tot ++; + ntx--; + fwdback++; + tot++; } /* Update state of netmap ring. */ - rxring->head = rxring->cur = rxhead; - txring->head = txring->cur = txhead; + rxring->head = rxring->cur = rxhead; + txring->head = txring->cur = txhead; } } @@ -192,11 +194,11 @@ main_loop(const char *netmap_port_one, const char *netmap_port_two, nmd_one = nm_open(netmap_port_one, NULL, 0, NULL); if (nmd_one == NULL) { if (!errno) { - printf("Failed to nm_open(%s): not a netmap port\n", - netmap_port_one); + printf("Failed to nm_open(%s): not a netmap port\n", + netmap_port_one); } else { - printf("Failed to nm_open(%s): %s\n", netmap_port_one, - strerror(errno)); + printf("Failed to nm_open(%s): %s\n", netmap_port_one, + strerror(errno)); } return -1; } @@ -217,7 +219,7 @@ main_loop(const char *netmap_port_one, const char *netmap_port_two, if (nmd_three == NULL) { if (!errno) { printf("Failed to nm_open(%s): not a netmap port\n", - netmap_port_three); + netmap_port_three); } else { printf("Failed to nm_open(%s): %s\n", netmap_port_three, strerror(errno)); @@ -294,19 +296,20 @@ usage(char **argv) { printf("usage: %s [-h] [-i NETMAP_PORT_ONE] " "[-i NETMAP_PORT_TWO] [-i NETMAP_PORT_THREE] " - "[-p UDP_PORT_A] [-p UDP_PORT_B]\n", argv[0]); + "[-p UDP_PORT_A] [-p UDP_PORT_B]\n", + argv[0]); exit(EXIT_SUCCESS); } int main(int argc, char **argv) { - const char *netmap_port_one = NULL; - const char *netmap_port_two = NULL; + const char *netmap_port_one = NULL; + const char *netmap_port_two = NULL; const char *netmap_port_three = NULL; int udp_port; - int udp_port_a = 8000; - int udp_port_b = 8001; + int udp_port_a = 8000; + int udp_port_b = 8001; int udp_port_args = 0; struct sigaction sa; int opt; @@ -314,41 +317,41 @@ main(int argc, char **argv) while ((opt = getopt(argc, argv, "hi:p:")) != -1) { switch (opt) { - case 'h': + case 'h': + usage(argv); + return 0; + + case 'i': + if (netmap_port_one == NULL) { + netmap_port_one = optarg; + } else if (netmap_port_two == NULL) { + netmap_port_two = optarg; + } else if (netmap_port_three == NULL) { + netmap_port_three = optarg; + } + break; + + case 'p': + udp_port = atoi(optarg); + if (udp_port <= 0 || udp_port >= 65535) { + printf(" invalid UDP port %s\n", optarg); usage(argv); - return 0; - - case 'i': - if (netmap_port_one == NULL) { - netmap_port_one = optarg; - } else if (netmap_port_two == NULL) { - netmap_port_two = optarg; - } else if (netmap_port_three == NULL) { - netmap_port_three = optarg; - } + } + switch (udp_port_args) { + case 0: + udp_port_a = udp_port; break; - - case 'p': - udp_port = atoi(optarg); - if (udp_port <= 0 || udp_port >= 65535) { - printf(" invalid UDP port %s\n", optarg); - usage(argv); - } - switch (udp_port_args) { - case 0: - udp_port_a = udp_port; - break; - case 1: - udp_port_b = udp_port; - break; - } - udp_port_args ++; + case 1: + udp_port_b = udp_port; break; + } + udp_port_args++; + break; - default: - printf(" unrecognized option '-%c'\n", opt); - usage(argv); - return -1; + default: + printf(" unrecognized option '-%c'\n", opt); + usage(argv); + return -1; } } @@ -366,7 +369,7 @@ main(int argc, char **argv) sa.sa_handler = sigint_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; - ret = sigaction(SIGINT, &sa, NULL); + ret = sigaction(SIGINT, &sa, NULL); if (ret) { perror("sigaction(SIGINT)"); exit(EXIT_FAILURE); @@ -379,8 +382,10 @@ main(int argc, char **argv) printf("UDP port A: %d\n", udp_port_a); printf("UDP port B: %d\n", udp_port_b); - main_loop(netmap_port_one, netmap_port_two, netmap_port_three, - udp_port_a, udp_port_b); + main_loop(netmap_port_one, netmap_port_two, netmap_port_three, udp_port_a, + udp_port_b); + + (void) pkt_get_udp_port; return 0; } diff --git a/solutions/forward.c b/solutions/forward.c index ad0fc5d..355d5ab 100644 --- a/solutions/forward.c +++ b/solutions/forward.c @@ -15,12 +15,14 @@ #include #define NETMAP_WITH_LIBS #include -#include +#include +#include +#include #include #include #include -static int stop = 0; +static int stop = 0; static unsigned long long fwd = 0; static unsigned long long tot = 0; @@ -35,13 +37,13 @@ rx_ready(struct nm_desc *nmd) { unsigned int ri; - for (ri = nmd->first_rx_ring; ri <= nmd->last_rx_ring; ri ++) { - struct netmap_ring *ring; + for (ri = nmd->first_rx_ring; ri <= nmd->last_rx_ring; ri++) { + struct netmap_ring *ring; - ring = NETMAP_RXRING(nmd->nifp, ri); - if (nm_ring_space(ring)) { - return 1; /* there is something to read */ - } + ring = NETMAP_RXRING(nmd->nifp, ri); + if (nm_ring_space(ring)) { + return 1; /* there is something to read */ + } } return 0; @@ -51,7 +53,7 @@ static inline int pkt_select(const char *buf, int udp_port) { struct ether_header *ethh; - struct iphdr *iph; + struct ip *iph; struct udphdr *udph; if (udp_port == 0) { @@ -63,15 +65,15 @@ pkt_select(const char *buf, int udp_port) /* Filter out non-IP traffic. */ return 0; } - iph = (struct iphdr *)(ethh + 1); - if (iph->protocol != IPPROTO_UDP) { + iph = (struct ip *)(ethh + 1); + if (iph->ip_p != IPPROTO_UDP) { /* Filter out non-UDP traffic. */ return 0; } udph = (struct udphdr *)(iph + 1); /* Match the destination port. */ - if (udph->dest != htons(udp_port)) { + if (udph->uh_dport != htons(udp_port)) { return 0; } @@ -140,7 +142,8 @@ forward_pkts(struct nm_desc *src, struct nm_desc *dst, int udp_port, int zerocop #endif /* SOLUTION */ static int -main_loop(const char *netmap_port_one, const char *netmap_port_two, int udp_port) +main_loop(const char *netmap_port_one, const char *netmap_port_two, + int udp_port) { struct nm_desc *nmd_one; struct nm_desc *nmd_two; @@ -231,7 +234,8 @@ static void usage(char **argv) { printf("usage: %s [-h] [-p UDP_PORT] [-i NETMAP_PORT_ONE] " - "[-i NETMAP_PORT_TWO]\n", argv[0]); + "[-i NETMAP_PORT_TWO]\n", + argv[0]); exit(EXIT_SUCCESS); } @@ -240,37 +244,37 @@ main(int argc, char **argv) { const char *netmap_port_one = NULL; const char *netmap_port_two = NULL; - int udp_port = 0; /* zero means select everything */ + int udp_port = 0; /* zero means select everything */ struct sigaction sa; int opt; int ret; while ((opt = getopt(argc, argv, "hi:p:")) != -1) { switch (opt) { - case 'h': - usage(argv); - return 0; - - case 'i': - if (netmap_port_one == NULL) { - netmap_port_one = optarg; - } else if (netmap_port_two == NULL) { - netmap_port_two = optarg; - } - break; - - case 'p': - udp_port = atoi(optarg); - if (udp_port < 0 || udp_port >= 65535) { - printf(" invalid UDP port %s\n", optarg); - usage(argv); - } - break; - - default: - printf(" unrecognized option '-%c'\n", opt); + case 'h': + usage(argv); + return 0; + + case 'i': + if (netmap_port_one == NULL) { + netmap_port_one = optarg; + } else if (netmap_port_two == NULL) { + netmap_port_two = optarg; + } + break; + + case 'p': + udp_port = atoi(optarg); + if (udp_port < 0 || udp_port >= 65535) { + printf(" invalid UDP port %s\n", optarg); usage(argv); - return -1; + } + break; + + default: + printf(" unrecognized option '-%c'\n", opt); + usage(argv); + return -1; } } @@ -288,7 +292,7 @@ main(int argc, char **argv) sa.sa_handler = sigint_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; - ret = sigaction(SIGINT, &sa, NULL); + ret = sigaction(SIGINT, &sa, NULL); if (ret) { perror("sigaction(SIGINT)"); exit(EXIT_FAILURE); @@ -301,5 +305,7 @@ main(int argc, char **argv) main_loop(netmap_port_one, netmap_port_two, udp_port); + (void)pkt_select; /* silence the compiler */ + return 0; } diff --git a/solutions/sink.c b/solutions/sink.c index fbf0db4..3f71247 100644 --- a/solutions/sink.c +++ b/solutions/sink.c @@ -14,7 +14,9 @@ #include #define NETMAP_WITH_LIBS #include -#include +#include +#include +#include #include #include #include @@ -31,7 +33,7 @@ static inline int udp_port_match(const char *buf, unsigned len, int udp_port) { struct ether_header *ethh; - struct iphdr *iph; + struct ip *iph; struct udphdr *udph; ethh = (struct ether_header *)buf; @@ -39,15 +41,15 @@ udp_port_match(const char *buf, unsigned len, int udp_port) /* Filter out non-IP traffic. */ return 0; } - iph = (struct iphdr *)(ethh + 1); - if (iph->protocol != IPPROTO_UDP) { + iph = (struct ip *)(ethh + 1); + if (iph->ip_p != IPPROTO_UDP) { /* Filter out non-UDP traffic. */ return 0; } udph = (struct udphdr *)(iph + 1); /* Match the destination port. */ - if (udph->dest == htons(udp_port)) { + if (udph->uh_dport == htons(udp_port)) { return 1; } @@ -140,33 +142,33 @@ int main(int argc, char **argv) { const char *netmap_port = NULL; - int udp_port = 8000; + int udp_port = 8000; struct sigaction sa; int opt; int ret; while ((opt = getopt(argc, argv, "hi:p:")) != -1) { switch (opt) { - case 'h': + case 'h': + usage(argv); + return 0; + + case 'i': + netmap_port = optarg; + break; + + case 'p': + udp_port = atoi(optarg); + if (udp_port <= 0 || udp_port >= 65535) { + printf(" invalid UDP port %s\n", optarg); usage(argv); - return 0; - - case 'i': - netmap_port = optarg; - break; - - case 'p': - udp_port = atoi(optarg); - if (udp_port <= 0 || udp_port >= 65535) { - printf(" invalid UDP port %s\n", optarg); - usage(argv); - } - break; + } + break; - default: - printf(" unrecognized option '-%c'\n", opt); - usage(argv); - return -1; + default: + printf(" unrecognized option '-%c'\n", opt); + usage(argv); + return -1; } } @@ -179,7 +181,7 @@ main(int argc, char **argv) sa.sa_handler = sigint_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; - ret = sigaction(SIGINT, &sa, NULL); + ret = sigaction(SIGINT, &sa, NULL); if (ret) { perror("sigaction(SIGINT)"); exit(EXIT_FAILURE); @@ -190,5 +192,7 @@ main(int argc, char **argv) main_loop(netmap_port, udp_port); + (void)udp_port_match; /* silence the compiler */ + return 0; } diff --git a/solutions/swap.c b/solutions/swap.c index 5769734..b7ff555 100644 --- a/solutions/swap.c +++ b/solutions/swap.c @@ -15,14 +15,16 @@ #include #define NETMAP_WITH_LIBS #include -#include +#include +#include +#include #include #include #include -static int stop = 0; +static int stop = 0; static unsigned long long swapped = 0; -static unsigned long long tot = 0; +static unsigned long long tot = 0; static void sigint_handler(int signum) @@ -35,13 +37,13 @@ rx_ready(struct nm_desc *nmd) { unsigned int ri; - for (ri = nmd->first_rx_ring; ri <= nmd->last_rx_ring; ri ++) { - struct netmap_ring *ring; + for (ri = nmd->first_rx_ring; ri <= nmd->last_rx_ring; ri++) { + struct netmap_ring *ring; - ring = NETMAP_RXRING(nmd->nifp, ri); - if (nm_ring_space(ring)) { - return 1; /* there is something to read */ - } + ring = NETMAP_RXRING(nmd->nifp, ri); + if (nm_ring_space(ring)) { + return 1; /* there is something to read */ + } } return 0; @@ -53,7 +55,7 @@ static inline int pkt_udp_port_swap(char *buf) { struct ether_header *ethh; - struct iphdr *iph; + struct ip *iph; struct udphdr *udph; uint16_t tmp; @@ -62,15 +64,15 @@ pkt_udp_port_swap(char *buf) /* Filter out non-IP traffic. */ return 0; } - iph = (struct iphdr *)(ethh + 1); - if (iph->protocol != IPPROTO_UDP) { + iph = (struct ip *)(ethh + 1); + if (iph->ip_p != IPPROTO_UDP) { /* Filter out non-UDP traffic. */ return 0; } - udph = (struct udphdr *)(iph + 1); - tmp = udph->source; - udph->source = udph->dest; - udph->dest = tmp; + udph = (struct udphdr *)(iph + 1); + tmp = udph->uh_sport; + udph->uh_sport = udph->uh_dport; + udph->uh_dport = tmp; return 1; } @@ -226,7 +228,8 @@ static void usage(char **argv) { printf("usage: %s [-h] [-i NETMAP_PORT_ONE] " - "[-i NETMAP_PORT_TWO]\n", argv[0]); + "[-i NETMAP_PORT_TWO]\n", + argv[0]); exit(EXIT_SUCCESS); } @@ -241,22 +244,22 @@ main(int argc, char **argv) while ((opt = getopt(argc, argv, "hi:p:")) != -1) { switch (opt) { - case 'h': - usage(argv); - return 0; - - case 'i': - if (netmap_port_one == NULL) { - netmap_port_one = optarg; - } else if (netmap_port_two == NULL) { - netmap_port_two = optarg; - } - break; - - default: - printf(" unrecognized option '-%c'\n", opt); - usage(argv); - return -1; + case 'h': + usage(argv); + return 0; + + case 'i': + if (netmap_port_one == NULL) { + netmap_port_one = optarg; + } else if (netmap_port_two == NULL) { + netmap_port_two = optarg; + } + break; + + default: + printf(" unrecognized option '-%c'\n", opt); + usage(argv); + return -1; } } @@ -274,7 +277,7 @@ main(int argc, char **argv) sa.sa_handler = sigint_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; - ret = sigaction(SIGINT, &sa, NULL); + ret = sigaction(SIGINT, &sa, NULL); if (ret) { perror("sigaction(SIGINT)"); exit(EXIT_FAILURE); @@ -286,5 +289,7 @@ main(int argc, char **argv) main_loop(netmap_port_one, netmap_port_two); + (void) pkt_udp_port_swap; + return 0; } From 95e1b63afe2a00388aaf2c7a6ee898adc2f99c48 Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Thu, 1 Mar 2018 12:15:53 +0100 Subject: [PATCH 15/28] style improvements --- codelab/fe.c | 2 +- codelab/swap.c | 2 +- solutions/fe.c | 27 +++++++++++++-------------- solutions/forward.c | 33 +++++++++++++++++---------------- solutions/sink.c | 17 ++++++++--------- solutions/swap.c | 26 +++++++++++++------------- 6 files changed, 53 insertions(+), 54 deletions(-) diff --git a/codelab/fe.c b/codelab/fe.c index 63b299a..a806dcd 100644 --- a/codelab/fe.c +++ b/codelab/fe.c @@ -280,7 +280,7 @@ main(int argc, char **argv) main_loop(netmap_port_one, netmap_port_two, netmap_port_three, udp_port_a, udp_port_b); - (void) pkt_get_udp_port; + (void)pkt_get_udp_port; return 0; } diff --git a/codelab/swap.c b/codelab/swap.c index ddfe325..2220dbd 100644 --- a/codelab/swap.c +++ b/codelab/swap.c @@ -189,7 +189,7 @@ main(int argc, char **argv) main_loop(netmap_port_one, netmap_port_two); - (void) pkt_udp_port_swap; + (void)pkt_udp_port_swap; return 0; } diff --git a/solutions/fe.c b/solutions/fe.c index d373237..fb6abf5 100644 --- a/solutions/fe.c +++ b/solutions/fe.c @@ -88,7 +88,7 @@ pkt_copy_or_drop(struct nm_desc *dst, const char *buf, unsigned len) if (nm_ring_space(txring)) { struct netmap_slot *ts = &txring->slot[txring->head]; - char *txbuf = NETMAP_BUF(txring, ts->buf_idx); + char *txbuf = NETMAP_BUF(txring, ts->buf_idx); ts->len = len; memcpy(txbuf, buf, len); @@ -112,26 +112,26 @@ route_forward(struct nm_desc *one, struct nm_desc *two, struct nm_desc *three, int nrx; rxring = NETMAP_RXRING(one->nifp, si); - nrx = nm_ring_space(rxring); + nrx = nm_ring_space(rxring); if (nrx == 0) { si++; continue; } - rxhead = rxring->head; + rxhead = rxring->head; for (; nrx > 0; nrx--, rxhead = nm_ring_next(rxring, rxhead)) { struct netmap_slot *rs = &rxring->slot[rxhead]; - char *rxbuf = NETMAP_BUF(rxring, rs->buf_idx); - int udp_port = pkt_get_udp_port(rxbuf); + char *rxbuf = NETMAP_BUF(rxring, rs->buf_idx); + int udp_port = pkt_get_udp_port(rxbuf); if (udp_port == udp_port_a) { fwda += pkt_copy_or_drop(two, rxbuf, rs->len); } else if (udp_port == udp_port_b) { fwdb += pkt_copy_or_drop(three, rxbuf, rs->len); } - tot ++; + tot++; } - rxring->head = rxring->cur = rxhead; + rxring->head = rxring->cur = rxhead; } } #endif /* SOLUTION */ @@ -233,9 +233,9 @@ main_loop(const char *netmap_port_one, const char *netmap_port_two, int ret; int two_ready, three_ready; - pfd[0].fd = nmd_one->fd; - pfd[1].fd = nmd_two->fd; - pfd[2].fd = nmd_three->fd; + pfd[0].fd = nmd_one->fd; + pfd[1].fd = nmd_two->fd; + pfd[2].fd = nmd_three->fd; pfd[0].events = POLLIN; pfd[1].events = 0; pfd[2].events = 0; @@ -244,7 +244,7 @@ main_loop(const char *netmap_port_one, const char *netmap_port_two, * line blocking (we don't know in advance which packets are going to * be forwarded where). As a result, unfortunately, we may end dropping * packets. */ - two_ready = rx_ready(nmd_two); + two_ready = rx_ready(nmd_two); three_ready = rx_ready(nmd_three); if (!two_ready) { pfd[1].events |= POLLIN; @@ -270,8 +270,7 @@ main_loop(const char *netmap_port_one, const char *netmap_port_two, } /* Route and forward from port one to ports two and three. */ - route_forward(nmd_one, nmd_two, nmd_three, udp_port_a, - udp_port_b); + route_forward(nmd_one, nmd_two, nmd_three, udp_port_a, udp_port_b); #endif /* SOLUTION */ /* Forward traffic from ports two and three back to port one. */ @@ -385,7 +384,7 @@ main(int argc, char **argv) main_loop(netmap_port_one, netmap_port_two, netmap_port_three, udp_port_a, udp_port_b); - (void) pkt_get_udp_port; + (void)pkt_get_udp_port; return 0; } diff --git a/solutions/forward.c b/solutions/forward.c index 355d5ab..136d4bf 100644 --- a/solutions/forward.c +++ b/solutions/forward.c @@ -82,7 +82,8 @@ pkt_select(const char *buf, int udp_port) #ifdef SOLUTION static void -forward_pkts(struct nm_desc *src, struct nm_desc *dst, int udp_port, int zerocopy) +forward_pkts(struct nm_desc *src, struct nm_desc *dst, int udp_port, + int zerocopy) { unsigned int si = src->first_rx_ring; unsigned int di = dst->first_tx_ring; @@ -95,8 +96,8 @@ forward_pkts(struct nm_desc *src, struct nm_desc *dst, int udp_port, int zerocop rxring = NETMAP_RXRING(src->nifp, si); txring = NETMAP_TXRING(dst->nifp, di); - nrx = nm_ring_space(rxring); - ntx = nm_ring_space(txring); + nrx = nm_ring_space(rxring); + ntx = nm_ring_space(txring); if (nrx == 0) { si++; continue; @@ -106,13 +107,13 @@ forward_pkts(struct nm_desc *src, struct nm_desc *dst, int udp_port, int zerocop continue; } - rxhead = rxring->head; - txhead = txring->head; - for (; nrx > 0 && ntx > 0; - nrx --, rxhead = nm_ring_next(rxring, rxhead), tot ++) { + rxhead = rxring->head; + txhead = txring->head; + for (; nrx > 0 && ntx > 0; + nrx--, rxhead = nm_ring_next(rxring, rxhead), tot++) { struct netmap_slot *rs = &rxring->slot[rxhead]; struct netmap_slot *ts = &txring->slot[txhead]; - char *rxbuf = NETMAP_BUF(rxring, rs->buf_idx); + char *rxbuf = NETMAP_BUF(rxring, rs->buf_idx); if (!pkt_select(rxbuf, udp_port)) { continue; /* discard */ @@ -121,8 +122,8 @@ forward_pkts(struct nm_desc *src, struct nm_desc *dst, int udp_port, int zerocop ts->len = rs->len; if (zerocopy) { uint32_t idx = ts->buf_idx; - ts->buf_idx = rs->buf_idx; - rs->buf_idx = idx; + ts->buf_idx = rs->buf_idx; + rs->buf_idx = idx; /* report the buffer change. */ ts->flags |= NS_BUF_CHANGED; rs->flags |= NS_BUF_CHANGED; @@ -131,12 +132,12 @@ forward_pkts(struct nm_desc *src, struct nm_desc *dst, int udp_port, int zerocop memcpy(txbuf, rxbuf, ts->len); } txhead = nm_ring_next(txring, txhead); - ntx --; - fwd ++; + ntx--; + fwd++; } /* Update state of netmap ring. */ - rxring->head = rxring->cur = rxhead; - txring->head = txring->cur = txhead; + rxring->head = rxring->cur = rxhead; + txring->head = txring->cur = txhead; } } #endif /* SOLUTION */ @@ -182,8 +183,8 @@ main_loop(const char *netmap_port_one, const char *netmap_port_two, struct pollfd pfd[2]; int ret; - pfd[0].fd = nmd_one->fd; - pfd[1].fd = nmd_two->fd; + pfd[0].fd = nmd_one->fd; + pfd[1].fd = nmd_two->fd; pfd[0].events = 0; pfd[1].events = 0; if (!rx_ready(nmd_one)) { diff --git a/solutions/sink.c b/solutions/sink.c index 3f71247..fddd852 100644 --- a/solutions/sink.c +++ b/solutions/sink.c @@ -69,8 +69,7 @@ main_loop(const char *netmap_port, int udp_port) if (!errno) { printf("Failed to nm_open(%s): not a netmap port\n", netmap_port); } else { - printf("Failed to nm_open(%s): %s\n", netmap_port, - strerror(errno)); + printf("Failed to nm_open(%s): %s\n", netmap_port, strerror(errno)); } return -1; } @@ -82,7 +81,7 @@ main_loop(const char *netmap_port, int udp_port) unsigned int ri; int ret; - pfd[0].fd = nmd->fd; + pfd[0].fd = nmd->fd; pfd[0].events = POLLIN; /* We poll with a timeout to have a chance to break the main loop if @@ -96,25 +95,25 @@ main_loop(const char *netmap_port, int udp_port) } /* Scan all the receive rings. */ - for (ri = nmd->first_rx_ring; ri <= nmd->last_rx_ring; ri ++) { + for (ri = nmd->first_rx_ring; ri <= nmd->last_rx_ring; ri++) { struct netmap_ring *rxring; unsigned head, tail; int batch; rxring = NETMAP_RXRING(nmd->nifp, ri); - head = rxring->head; - tail = rxring->tail; - batch = tail - head; + head = rxring->head; + tail = rxring->tail; + batch = tail - head; if (batch < 0) { batch += rxring->num_slots; } tot += batch; for (; head != tail; head = nm_ring_next(rxring, head)) { struct netmap_slot *slot = rxring->slot + head; - char *buf = NETMAP_BUF(rxring, slot->buf_idx); + char *buf = NETMAP_BUF(rxring, slot->buf_idx); if (udp_port_match(buf, slot->len, udp_port)) { - cnt ++; + cnt++; } } rxring->cur = rxring->head = head; diff --git a/solutions/swap.c b/solutions/swap.c index b7ff555..6cbcc1a 100644 --- a/solutions/swap.c +++ b/solutions/swap.c @@ -92,8 +92,8 @@ swap_and_forward(struct nm_desc *src, struct nm_desc *dst, int zerocopy) rxring = NETMAP_RXRING(src->nifp, si); txring = NETMAP_TXRING(dst->nifp, di); - nrx = nm_ring_space(rxring); - ntx = nm_ring_space(txring); + nrx = nm_ring_space(rxring); + ntx = nm_ring_space(txring); if (nrx == 0) { si++; continue; @@ -103,9 +103,9 @@ swap_and_forward(struct nm_desc *src, struct nm_desc *dst, int zerocopy) continue; } - rxhead = rxring->head; - txhead = txring->head; - for (; nrx > 0 && ntx > 0; nrx--, ntx--, tot++) { + rxhead = rxring->head; + txhead = txring->head; + for (; nrx > 0 && ntx > 0; nrx--, ntx--, tot++) { struct netmap_slot *rs = &rxring->slot[rxhead]; struct netmap_slot *ts = &txring->slot[txhead]; char *txbuf; @@ -113,15 +113,15 @@ swap_and_forward(struct nm_desc *src, struct nm_desc *dst, int zerocopy) ts->len = rs->len; if (zerocopy) { uint32_t idx = ts->buf_idx; - ts->buf_idx = rs->buf_idx; - rs->buf_idx = idx; + ts->buf_idx = rs->buf_idx; + rs->buf_idx = idx; /* report the buffer change. */ ts->flags |= NS_BUF_CHANGED; rs->flags |= NS_BUF_CHANGED; txbuf = NETMAP_BUF(txring, ts->buf_idx); } else { char *rxbuf = NETMAP_BUF(rxring, rs->buf_idx); - txbuf = NETMAP_BUF(txring, ts->buf_idx); + txbuf = NETMAP_BUF(txring, ts->buf_idx); memcpy(txbuf, rxbuf, ts->len); } @@ -130,8 +130,8 @@ swap_and_forward(struct nm_desc *src, struct nm_desc *dst, int zerocopy) rxhead = nm_ring_next(rxring, rxhead); } /* Update state of netmap ring. */ - rxring->head = rxring->cur = rxhead; - txring->head = txring->cur = txhead; + rxring->head = rxring->cur = rxhead; + txring->head = txring->cur = txhead; } } #endif /* SOLUTION */ @@ -176,8 +176,8 @@ main_loop(const char *netmap_port_one, const char *netmap_port_two) struct pollfd pfd[2]; int ret; - pfd[0].fd = nmd_one->fd; - pfd[1].fd = nmd_two->fd; + pfd[0].fd = nmd_one->fd; + pfd[1].fd = nmd_two->fd; pfd[0].events = 0; pfd[1].events = 0; if (!rx_ready(nmd_one)) { @@ -289,7 +289,7 @@ main(int argc, char **argv) main_loop(netmap_port_one, netmap_port_two); - (void) pkt_udp_port_swap; + (void)pkt_udp_port_swap; return 0; } From 64cf903216e143a782afaaa208923cb7b7df9c6f Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Thu, 1 Mar 2018 12:21:07 +0100 Subject: [PATCH 16/28] codelab: forward: small style improvements --- codelab/forward.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/codelab/forward.c b/codelab/forward.c index 0cfead9..5605072 100644 --- a/codelab/forward.c +++ b/codelab/forward.c @@ -118,17 +118,18 @@ main_loop(const char *netmap_port_one, const char *netmap_port_two, while (!stop) { struct pollfd pfd[2]; + pfd[0].fd = nmd_one->fd; - pfd[0].events = 0; pfd[1].fd = nmd_two->fd; + pfd[0].events = 0; pfd[1].events = 0; - /* if port one has RX packets then + /* TODO: if port one has RX packets then * POLLOUT on port two else POLLIN on * port one */ poll(pfd, 2, 1000); - /* try to copy as many packets as possible + /* TODO: try to copy as many packets as possible * from port 1 to port 2 */ } From aa1810f351a7f1f4ae4cc37a910776595ae3d8bc Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Thu, 1 Mar 2018 16:26:47 +0100 Subject: [PATCH 17/28] solutions: fix scripts to use /bin/sh --- solutions/flowgraph-down.sh | 2 +- solutions/flowgraph-up.sh | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/solutions/flowgraph-down.sh b/solutions/flowgraph-down.sh index 23a3416..6c83d03 100755 --- a/solutions/flowgraph-down.sh +++ b/solutions/flowgraph-down.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/sh set -x diff --git a/solutions/flowgraph-up.sh b/solutions/flowgraph-up.sh index 76239b4..376d8ff 100755 --- a/solutions/flowgraph-up.sh +++ b/solutions/flowgraph-up.sh @@ -1,10 +1,10 @@ -#!/bin/bash +#!/bin/sh set -x PIDS="" -sudo pkt-gen -i netmap:pipe{1 -f tx -s 10.0.0.1:7000-10.0.0.1:7010 -d 10.0.0.1:8000-10.0.0.1:8004 &> /dev/null & +sudo pkt-gen -i netmap:pipe{1 -f tx -s 10.0.0.1:7000-10.0.0.1:7010 -d 10.0.0.1:8000-10.0.0.1:8004 2>&1 > /dev/null & PIDS="$PIDS $!" sleep 0.5 sudo ./fe -i netmap:pipe}1 -i netmap:pipe{2 -i netmap:pipe{3 -p 8000 -p 8001 & From ceaf90f307ea6942a964e8e4742d9127d5f3f1da Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Fri, 14 Sep 2018 12:08:57 +0200 Subject: [PATCH 18/28] add travis support --- .travis.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..7f06565 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,10 @@ +dist: trusty +sudo: required +language: c +script: + - "sudo apt-get -qq update" + - "sudo apt-get install -y libelf-dev linux-headers-$(uname -r)" + - "git clone https://github.com/netmap-unipi/netmap" + - "cd netmap && ./configure --no-drivers && make && sudo make install" + - "cd codelab && make" + - "cd solutions && make" From cdacd31617079a1a270a9d4362b55f76ea02ea0d Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Fri, 14 Sep 2018 12:17:21 +0200 Subject: [PATCH 19/28] .travis: add missing pushd and popd instructions --- .travis.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.travis.yml b/.travis.yml index 7f06565..9c52e53 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,9 +2,15 @@ dist: trusty sudo: required language: c script: + - "pushd ." - "sudo apt-get -qq update" - "sudo apt-get install -y libelf-dev linux-headers-$(uname -r)" - "git clone https://github.com/netmap-unipi/netmap" - "cd netmap && ./configure --no-drivers && make && sudo make install" + - "popd" + - "pushd ." - "cd codelab && make" + - "popd" + - "pushd ." - "cd solutions && make" + - "popd" From 4d6a6f8e8c2ddc49a9ac1855844d8025d977696f Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Sun, 27 Jan 2019 15:09:43 +0100 Subject: [PATCH 20/28] add stateless-filter example for FOSDEM 2019 --- fosdem2019/Makefile | 9 + fosdem2019/stateless-filter.c | 403 ++++++++++++++++++++++++++++++++++ 2 files changed, 412 insertions(+) create mode 100644 fosdem2019/Makefile create mode 100644 fosdem2019/stateless-filter.c diff --git a/fosdem2019/Makefile b/fosdem2019/Makefile new file mode 100644 index 0000000..4c97e0e --- /dev/null +++ b/fosdem2019/Makefile @@ -0,0 +1,9 @@ +CFLAGS=-Wall -g -Werror -O2 +PROGS=stateless-filter + +all: $(PROGS) + +stateless-filter: stateless-filter.o + +clean: + -rm -f *.o $(PROGS) diff --git a/fosdem2019/stateless-filter.c b/fosdem2019/stateless-filter.c new file mode 100644 index 0000000..d628975 --- /dev/null +++ b/fosdem2019/stateless-filter.c @@ -0,0 +1,403 @@ +/* + * This program forwards packets between two netmap ports, an external + * port (ext) and an internal port (int). Packets flowing from ext to + * int are filtered according to the rules provided through command + * line. Packets flowing from int to ext bypass the filter, and they + * are always forwarded. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define NETMAP_WITH_LIBS +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int stop = 0; +static unsigned long long fwd = 0; +static unsigned long long tot = 0; + +static void +sigint_handler(int signum) +{ + stop = 1; +} + +struct filtrule { + /* All fields are in network order. */ + uint32_t ip_daddr; + uint32_t ip_mask; + uint16_t dport; + uint8_t ip_proto; + uint8_t pad; +}; + +static inline int +rx_ready(struct nm_desc *nmd) +{ + unsigned int ri; + + for (ri = nmd->first_rx_ring; ri <= nmd->last_rx_ring; ri++) { + struct netmap_ring *ring; + + ring = NETMAP_RXRING(nmd->nifp, ri); + if (nm_ring_space(ring)) { + return 1; /* there is something to read */ + } + } + + return 0; +} + +static inline int +pkt_select(const char *buf, struct filtrule *rules, + int num_rules) +{ + struct ether_header *ethh; + struct udphdr *udph; + struct ip *iph; + int i; + + ethh = (struct ether_header *)buf; + if (ethh->ether_type != htons(ETHERTYPE_IP)) { + /* Filter out non-IP traffic. */ + return 0; + } + iph = (struct ip *)(ethh + 1); + udph = (struct udphdr *)(iph + 1); + + for (i = 0; i < num_rules; i++) { + struct filtrule *rule = rules + i; + + if ((iph->ip_dst.s_addr & rule->ip_mask) + == rule->ip_daddr && + (!rules->ip_proto || rule->ip_proto == iph->ip_p) && + (!rule->dport || rule->dport == udph->uh_dport)) { + return 1; + } + } + + return 0; /* discard */ +} + +static void +forward_pkts(struct nm_desc *src, struct nm_desc *dst, struct filtrule *rules, + int num_rules, int zerocopy) +{ + unsigned int si = src->first_rx_ring; + unsigned int di = dst->first_tx_ring; + + while (si <= src->last_rx_ring && di <= dst->last_tx_ring) { + struct netmap_ring *txring; + struct netmap_ring *rxring; + unsigned int rxhead, txhead; + int nrx, ntx; + + rxring = NETMAP_RXRING(src->nifp, si); + txring = NETMAP_TXRING(dst->nifp, di); + nrx = nm_ring_space(rxring); + ntx = nm_ring_space(txring); + if (nrx == 0) { + si++; + continue; + } + if (ntx == 0) { + di++; + continue; + } + + rxhead = rxring->head; + txhead = txring->head; + for (; nrx > 0 && ntx > 0; + nrx--, rxhead = nm_ring_next(rxring, rxhead), tot++) { + struct netmap_slot *rs = &rxring->slot[rxhead]; + struct netmap_slot *ts = &txring->slot[txhead]; + char *rxbuf = NETMAP_BUF(rxring, rs->buf_idx); + + if (rules && !pkt_select(rxbuf, rules, num_rules)) { + continue; /* discard */ + } + + ts->len = rs->len; + if (zerocopy) { + uint32_t idx = ts->buf_idx; + ts->buf_idx = rs->buf_idx; + rs->buf_idx = idx; + /* report the buffer change. */ + ts->flags |= NS_BUF_CHANGED; + rs->flags |= NS_BUF_CHANGED; + } else { + char *txbuf = NETMAP_BUF(txring, ts->buf_idx); + memcpy(txbuf, rxbuf, ts->len); + } + txhead = nm_ring_next(txring, txhead); + ntx--; + fwd++; + } + /* Update state of netmap ring. */ + rxring->head = rxring->cur = rxhead; + txring->head = txring->cur = txhead; + } +} + +static int +main_loop(const char *ext_port_name, const char *int_port_name, + struct filtrule *rules, int num_rules) +{ + struct nm_desc *ext_port; + struct nm_desc *int_port; + int zerocopy; + + ext_port = nm_open(ext_port_name, NULL, 0, NULL); + if (ext_port == NULL) { + if (!errno) { + printf("Failed to nm_open(%s): not a netmap port\n", + ext_port_name); + } else { + printf("Failed to nm_open(%s): %s\n", ext_port_name, + strerror(errno)); + } + return -1; + } + + int_port = nm_open(int_port_name, NULL, NM_OPEN_NO_MMAP, ext_port); + if (int_port == NULL) { + if (!errno) { + printf("Failed to nm_open(%s): not a netmap port\n", + int_port_name); + } else { + printf("Failed to nm_open(%s): %s\n", int_port_name, + strerror(errno)); + } + return -1; + } + + /* Check if we can do zerocopy. */ + zerocopy = (ext_port->mem == int_port->mem); + printf("zerocopy %sabled\n", zerocopy ? "en" : "dis"); + + while (!stop) { + struct pollfd pfd[2]; + int ret; + + pfd[0].fd = ext_port->fd; + pfd[1].fd = int_port->fd; + pfd[0].events = 0; + pfd[1].events = 0; + if (!rx_ready(ext_port)) { + /* Ran out of input packets on the first port, we need to + * wait for them. */ + pfd[0].events |= POLLIN; + } else { + /* We have input packets on the first port, let's wait for + * TX ring space in the other port. */ + pfd[1].events |= POLLOUT; + } + if (!rx_ready(int_port)) { + /* Ran out of input packets on the second port, we need to + * wait for them. */ + pfd[1].events |= POLLIN; + } else { + /* We have input packets on the second port, let's wait for + * TX ring space in the other port. */ + pfd[0].events |= POLLOUT; + } + + /* We poll with a timeout to have a chance to break the main loop if + * no packets are coming. */ + ret = poll(pfd, 2, 1000); + if (ret < 0) { + perror("poll()"); + } else if (ret == 0) { + /* Timeout */ + continue; + } + + /* Forward in the two directions. */ + forward_pkts(ext_port, int_port, rules, num_rules, zerocopy); + forward_pkts(int_port, ext_port, NULL, 0, zerocopy); + } + + nm_close(ext_port); + nm_close(int_port); + + printf("Total processed packets: %llu\n", tot); + printf("Forwarded packets : %llu\n", fwd); + + return 0; +} + +static void +usage(char **argv) +{ + printf("usage: %s [-h]\n" + " [-p x.y.z.w/mask:proto:dport (pass rule)] [-p ... ]\n" + " [-i INTERNAL_PORT]\n" + " [-e EXTERNAL_PORT]\n\n" + " Zero or more pass rules can be specified. A zero value for" + " mask, proto or dport means 'any'.\n", + argv[0]); + exit(EXIT_SUCCESS); +} + +int +main(int argc, char **argv) +{ +#define MAXRULES 16 + struct filtrule rules[MAXRULES]; + const char *ext_port_name = NULL; + const char *int_port_name = NULL; + struct sigaction sa; + int num_rules = 0; + int opt, ret, i; + + while ((opt = getopt(argc, argv, "hi:e:p:")) != -1) { + switch (opt) { + case 'h': + usage(argv); + return 0; + + case 'i': + int_port_name = optarg; + break; + + case 'e': + ext_port_name = optarg; + break; + + case 'p': { + char *copy = strdup(optarg); + char *ipstr, *maskstr, *protostr, *portstr, *null; + int port, proto, mask; + struct in_addr ip; + int ret; + + assert(copy != NULL); + ipstr = strtok(copy, "/"); + if (!ipstr) { + printf(" invalid -p '%s': no IPv4 found\n", + optarg); + usage(argv); + } + ret = inet_pton(AF_INET, ipstr, &ip); + if (ret <= 0) { + printf(" invalid IPv4 '%s'\n", + ipstr); + usage(argv); + } + + maskstr = strtok(NULL, ":"); + if (!maskstr) { + printf(" invalid -p '%s': no mask found\n", + optarg); + usage(argv); + } + mask = atoi(maskstr); + if (mask < 0 || mask > 31) { + printf(" invalid mask '%s'\n", + maskstr); + usage(argv); + } + + protostr = strtok(NULL, ":"); + if (!protostr) { + printf(" invalid -p '%s': no proto found\n", + optarg); + usage(argv); + } + proto = atoi(protostr); + if (proto < 0 || proto > 255) { + printf(" invalid proto '%s'\n", + protostr); + usage(argv); + } + + portstr = strtok(NULL, ":"); + if (!portstr) { + printf(" invalid -p '%s': no port found\n", + optarg); + usage(argv); + } + port = atoi(portstr); + if (port < 0 || port > (1<<16)-1) { + printf(" invalid port '%s'\n", + portstr); + usage(argv); + } + + null = strtok(NULL, ":"); + if (null) { + printf(" invalid -p '%s': trailing chars\n", + optarg); + usage(argv); + } + free(copy); + printf("<%08x/%d> <%d> <%d>\n", ip.s_addr, mask, proto, port); + + if (num_rules >= MAXRULES) { + printf(" too many rules, bailing out\n"); + exit(EXIT_FAILURE); + } + + rules[num_rules].ip_mask = + (((uint64_t)1ULL << mask) - 1ULL) << (32 - mask); + rules[num_rules].ip_mask = htonl(rules[num_rules].ip_mask); + rules[num_rules].ip_daddr = ip.s_addr & rules[num_rules].ip_mask; + rules[num_rules].ip_proto = proto; + rules[num_rules].dport = htons(port); + num_rules++; + break; + } + + default: + printf(" unrecognized option '-%c'\n", opt); + usage(argv); + return -1; + } + } + + if (ext_port_name == NULL) { + printf(" missing external port\n"); + usage(argv); + } + + if (int_port_name == NULL) { + printf(" missing internal port\n"); + usage(argv); + } + + /* Register Ctrl-C handler. */ + sa.sa_handler = sigint_handler; + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_RESTART; + ret = sigaction(SIGINT, &sa, NULL); + if (ret) { + perror("sigaction(SIGINT)"); + exit(EXIT_FAILURE); + } + + printf("External port: %s\n", ext_port_name); + printf("Internal port: %s\n", int_port_name); + for (i = 0; i < num_rules; i++) { + printf(" rule: ip_daddr 0x%08x/0x%08x ip_proto %u " + "dport %u\n", + ntohl(rules[i].ip_daddr), ntohl(rules[i].ip_mask), + rules[i].ip_proto, ntohs(rules[i].dport)); + } + + main_loop(ext_port_name, int_port_name, rules, num_rules); + + return 0; +} From e194c7d22522c2a296336f52432b5bd47cf4c26f Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Sun, 27 Jan 2019 17:53:31 +0100 Subject: [PATCH 21/28] stateless-filter: add single-ring simplified implementation --- fosdem2019/stateless-filter.c | 83 +++++++++++++++++++++++++++-------- 1 file changed, 65 insertions(+), 18 deletions(-) diff --git a/fosdem2019/stateless-filter.c b/fosdem2019/stateless-filter.c index d628975..121000f 100644 --- a/fosdem2019/stateless-filter.c +++ b/fosdem2019/stateless-filter.c @@ -25,6 +25,10 @@ #include #include +/* You can undef MULTIRING to get the simpler code, which assumes + * that each netmap port has a single RX ring and a single TX ring. */ +#define MULTIRING + static int stop = 0; static unsigned long long fwd = 0; static unsigned long long tot = 0; @@ -44,23 +48,6 @@ struct filtrule { uint8_t pad; }; -static inline int -rx_ready(struct nm_desc *nmd) -{ - unsigned int ri; - - for (ri = nmd->first_rx_ring; ri <= nmd->last_rx_ring; ri++) { - struct netmap_ring *ring; - - ring = NETMAP_RXRING(nmd->nifp, ri); - if (nm_ring_space(ring)) { - return 1; /* there is something to read */ - } - } - - return 0; -} - static inline int pkt_select(const char *buf, struct filtrule *rules, int num_rules) @@ -96,6 +83,7 @@ static void forward_pkts(struct nm_desc *src, struct nm_desc *dst, struct filtrule *rules, int num_rules, int zerocopy) { +#ifdef MULTIRING unsigned int si = src->first_rx_ring; unsigned int di = dst->first_tx_ring; @@ -146,10 +134,69 @@ forward_pkts(struct nm_desc *src, struct nm_desc *dst, struct filtrule *rules, ntx--; fwd++; } - /* Update state of netmap ring. */ + /* Update the pointers in the netmap rings. */ rxring->head = rxring->cur = rxhead; txring->head = txring->cur = txhead; } +#else /* !MULTIRING */ + struct netmap_ring *txring; + struct netmap_ring *rxring; + unsigned int rxhead, txhead; + + rxring = NETMAP_RXRING(src->nifp, 0); + txring = NETMAP_TXRING(dst->nifp, 0); + + for (rxhead = rxring->head, txhead = txring->head; + rxhead != rxring->tail; tot++, + rxhead = nm_ring_next(rxring, rxhead)) { + struct netmap_slot *rs = &rxring->slot[rxhead]; + struct netmap_slot *ts = &txring->slot[txhead]; + char *rxbuf = NETMAP_BUF(rxring, rs->buf_idx); + + if (rules && !pkt_select(rxbuf, rules, num_rules)) { + continue; /* discard */ + } + + ts->len = rs->len; + if (zerocopy) { + uint32_t idx = ts->buf_idx; + ts->buf_idx = rs->buf_idx; + rs->buf_idx = idx; + /* report the buffer change. */ + ts->flags |= NS_BUF_CHANGED; + rs->flags |= NS_BUF_CHANGED; + } else { + char *txbuf = NETMAP_BUF(txring, ts->buf_idx); + memcpy(txbuf, rxbuf, ts->len); + } + txhead = nm_ring_next(txring, txhead); + fwd++; + } + /* Update the pointers in the netmap rings. */ + rxring->head = rxring->cur = rxhead; + txring->head = txring->cur = txhead; +#endif /* !MULTIRING */ +} + +static inline int +rx_ready(struct nm_desc *nmd) +{ +#ifdef MULTIRING + unsigned int ri; + + for (ri = nmd->first_rx_ring; ri <= nmd->last_rx_ring; ri++) { + struct netmap_ring *ring; + + ring = NETMAP_RXRING(nmd->nifp, ri); + if (nm_ring_space(ring)) { + return 1; /* there is something to read */ + } + } + + return 0; +#else /* !MULTIRING */ + return nm_ring_space(NETMAP_RXRING(nmd->nifp, 0)); +#endif /* !MULTIRING */ } static int From a6972e341022b11abccc69634e669f351c6c6950 Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Mon, 28 Jan 2019 12:08:30 +0100 Subject: [PATCH 22/28] statless-filter: improve output --- fosdem2019/README | 24 ++++++++++++++++++++++++ fosdem2019/stateless-filter.c | 4 ++-- 2 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 fosdem2019/README diff --git a/fosdem2019/README b/fosdem2019/README new file mode 100644 index 0000000..8ac86c4 --- /dev/null +++ b/fosdem2019/README @@ -0,0 +1,24 @@ +#### Netmap talk at FOSDEM 2019 #### + +URL: https://fosdem.org/2019/schedule/event/netmap_vnf_development/ + +This file contains instructions on how to run the example, step by step. + +Requirements: + - Linux (host) machine with KVM enabled + - Linux VM, or FreeBSD VM (with FreeBSD >= 12.x) + +### Step 1: Build and install netmap and qemu on the host machine + +$ mkdir fosdem2019-netmap +$ cd fosdem2019-netmap +$ git clone https://github.com/luigirizzo/netmap +$ cd netmap +$ ./configure --no-drivers # patched drivers not necessary for this example +$ make && sudo make install +$ sudo insmod netmap.ko +$ cd .. +$ git clone https://github.com/netmap-unipi/qemu +$ cd qemu +$ + diff --git a/fosdem2019/stateless-filter.c b/fosdem2019/stateless-filter.c index 121000f..ab64a22 100644 --- a/fosdem2019/stateless-filter.c +++ b/fosdem2019/stateless-filter.c @@ -391,7 +391,6 @@ main(int argc, char **argv) usage(argv); } free(copy); - printf("<%08x/%d> <%d> <%d>\n", ip.s_addr, mask, proto, port); if (num_rules >= MAXRULES) { printf(" too many rules, bailing out\n"); @@ -437,8 +436,9 @@ main(int argc, char **argv) printf("External port: %s\n", ext_port_name); printf("Internal port: %s\n", int_port_name); + printf("Rules:\n"); for (i = 0; i < num_rules; i++) { - printf(" rule: ip_daddr 0x%08x/0x%08x ip_proto %u " + printf(" pass ip_daddr 0x%08x/0x%08x ip_proto %u " "dport %u\n", ntohl(rules[i].ip_daddr), ntohl(rules[i].ip_mask), rules[i].ip_proto, ntohs(rules[i].dport)); From 6bccaa84a5b608162779233ae204fa9ecf3bc09a Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Mon, 28 Jan 2019 12:42:20 +0100 Subject: [PATCH 23/28] fosdem 2019: add README --- fosdem2019/README | 99 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 84 insertions(+), 15 deletions(-) diff --git a/fosdem2019/README b/fosdem2019/README index 8ac86c4..b05d4fa 100644 --- a/fosdem2019/README +++ b/fosdem2019/README @@ -6,19 +6,88 @@ This file contains instructions on how to run the example, step by step. Requirements: - Linux (host) machine with KVM enabled - - Linux VM, or FreeBSD VM (with FreeBSD >= 12.x) - -### Step 1: Build and install netmap and qemu on the host machine - -$ mkdir fosdem2019-netmap -$ cd fosdem2019-netmap -$ git clone https://github.com/luigirizzo/netmap -$ cd netmap -$ ./configure --no-drivers # patched drivers not necessary for this example -$ make && sudo make install -$ sudo insmod netmap.ko -$ cd .. -$ git clone https://github.com/netmap-unipi/qemu -$ cd qemu -$ + - QEMU Virtual Machine, running Linux or FreeBSD >= 12.x +### Step 1: Build, install and load netmap on the host machine + +(host) $ mkdir fosdem2019-netmap +(host) $ cd fosdem2019-netmap +(host) $ git clone https://github.com/luigirizzo/netmap +(host) $ cd netmap +(host) $ ./configure --no-drivers # patched drivers not necessary for this example +(host) $ make && sudo make install +(host) $ sudo insmod netmap.ko +(host) $ cd .. + + +### Step 2: Build and install qemu on the host machine + +(host) $ git clone https://github.com/netmap-unipi/qemu +(host) $ cd qemu +(host) $ ./configure --target-list=x86_64-softmmu --enable-kvm --disable-werror --enable-netmap +(host) $ make && sudo make install +(host) $ cd .. + + +### Step 3: Prepare the VM + +Install netmap in the VM (same as step 1, but inside the VM). +Then, build the example: + +(vm) $ git clone https://github.com/netmap-unipi/netmap-tutorial +(vm) $ cd netmap-tutorial/fosdem2019 +(vm) $ make + + +### Step 4: Close the VM and re-launch it with two netmap pipe ports + +sudo qemu-system-x86_64 /path/to/qemu/vm/image.qcow2 -enable-kvm -smp 2 -m 2G -vga std -device e1000,netdev=mgmt,mac=00:AA:BB:CC:0a:99 -netdev user,id=mgmt,hostfwd=tcp::20010-:22 -device ptnet-pci,netdev=data10,mac=00:AA:BB:CC:0a:0a -netdev netmap,ifname=vale1:10}1,id=data10,passthrough=on -device ptnet-pci,netdev=data11,mac=00:AA:BB:CC:0a:0b -netdev netmap,ifname=vale1:10{2,id=data11,passthrough=on + + + +### Step 5: Access the VM and find the two passed-through interfaces + +First, load the netmap module: +(vm) $ sudo insmod netmap + +On Linux, a list of passed-through netmap ports can be obtained in this way: +(vm) for if in $(ls /sys/class/net); do ethtool -i $if | grep -qq ptnetmap && echo "ptnetmap if: $if"; done + +On FreeBSD, just run "ifconfig" and look for "ptnetX" interfaces. + + +### Step 6: Run the example application + +Run the filter with a rule to pass TCP/UDP traffic towards +10.10.10.0/24, port 7777: + +(vm) $ cd netmap/tutorial/fosdem2019 +(vm) $ sudo ./stateless-filter -e eth1 -i eth2 -p 10.10.10.0/24:0:7777 + + +### Step 7: Inject traffic into the VM + +Send UDP traffic (with matching destination IP and port) into the other +end of the pipe corresponding to the EXT port: + +(host) pkt-gen -i vale1:10{1 -f tx -d 10.10.10.23:7777 + + +### Step 8: Capture traffic forwarded from the VM + +Receive traffic from the other end of the pipe corresponding the INT +port: +(host) pkt-gen -i vale1:10}2 -f rx + + + +### More experiments: + +1. Restart the filter, changing the rule to pass only port 80, and check + that no traffic is forwarded: +(vm) $ sudo ./stateless-filter -e eth1 -i eth2 -p 10.10.10.0/24:0:80 + +2. Try with bidirectional traffic, replacing "-f tx" with "-f ping", + and "-f rx" with "-f pong". + +3. Add more pass rule or use a pass-any rule ("0.0.0.0/0:0:0"). From a96aa0a926cd0ceefd2fdf6e759aeee88580443e Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Mon, 28 Jan 2019 15:11:47 +0100 Subject: [PATCH 24/28] stateless-filter: add missing check on txring --- fosdem2019/stateless-filter.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fosdem2019/stateless-filter.c b/fosdem2019/stateless-filter.c index ab64a22..63308b3 100644 --- a/fosdem2019/stateless-filter.c +++ b/fosdem2019/stateless-filter.c @@ -147,8 +147,8 @@ forward_pkts(struct nm_desc *src, struct nm_desc *dst, struct filtrule *rules, txring = NETMAP_TXRING(dst->nifp, 0); for (rxhead = rxring->head, txhead = txring->head; - rxhead != rxring->tail; tot++, - rxhead = nm_ring_next(rxring, rxhead)) { + rxhead != rxring->tail && txhead != txring->tail; + tot++, rxhead = nm_ring_next(rxring, rxhead)) { struct netmap_slot *rs = &rxring->slot[rxhead]; struct netmap_slot *ts = &txring->slot[txhead]; char *rxbuf = NETMAP_BUF(rxring, rs->buf_idx); From faea10a174242f5c193dcc64d9829cdfddbec80a Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Mon, 28 Jan 2019 16:00:06 +0100 Subject: [PATCH 25/28] stateless-filter: add -c option to turn down zerocopy --- fosdem2019/README | 32 ++++++++++++++++++-------------- fosdem2019/stateless-filter.c | 18 +++++++++++++----- 2 files changed, 31 insertions(+), 19 deletions(-) diff --git a/fosdem2019/README b/fosdem2019/README index b05d4fa..dcc8e1b 100644 --- a/fosdem2019/README +++ b/fosdem2019/README @@ -41,7 +41,7 @@ Then, build the example: ### Step 4: Close the VM and re-launch it with two netmap pipe ports -sudo qemu-system-x86_64 /path/to/qemu/vm/image.qcow2 -enable-kvm -smp 2 -m 2G -vga std -device e1000,netdev=mgmt,mac=00:AA:BB:CC:0a:99 -netdev user,id=mgmt,hostfwd=tcp::20010-:22 -device ptnet-pci,netdev=data10,mac=00:AA:BB:CC:0a:0a -netdev netmap,ifname=vale1:10}1,id=data10,passthrough=on -device ptnet-pci,netdev=data11,mac=00:AA:BB:CC:0a:0b -netdev netmap,ifname=vale1:10{2,id=data11,passthrough=on +(host) $ sudo qemu-system-x86_64 /path/to/qemu/vm/image.qcow2 -enable-kvm -smp 2 -m 2G -vga std -device e1000,netdev=mgmt,mac=00:AA:BB:CC:0a:99 -netdev user,id=mgmt,hostfwd=tcp::20010-:22 -device ptnet-pci,netdev=data10,mac=00:AA:BB:CC:0a:0a -netdev netmap,ifname=vale1:10}1,id=data10,passthrough=on -device ptnet-pci,netdev=data11,mac=00:AA:BB:CC:0a:0b -netdev netmap,ifname=vale1:10{2,id=data11,passthrough=on @@ -51,9 +51,14 @@ First, load the netmap module: (vm) $ sudo insmod netmap On Linux, a list of passed-through netmap ports can be obtained in this way: -(vm) for if in $(ls /sys/class/net); do ethtool -i $if | grep -qq ptnetmap && echo "ptnetmap if: $if"; done +(vm) $ for if in $(ls /sys/class/net); do ethtool -i $if | grep -qq ptnetmap && echo "ptnetmap if: $if"; done -On FreeBSD, just run "ifconfig" and look for "ptnetX" interfaces. +Bring the interfaces up, e.g.: +(vm) $ sudo ip link set $if up + +On FreeBSD, just run "ifconfig" and look for "ptnet*" interfaces, e.g.: +(vm) $ sudo ifconfig ptnet0 up +(vm) $ sudo ifconfig ptnet1 up ### Step 6: Run the example application @@ -62,30 +67,29 @@ Run the filter with a rule to pass TCP/UDP traffic towards 10.10.10.0/24, port 7777: (vm) $ cd netmap/tutorial/fosdem2019 -(vm) $ sudo ./stateless-filter -e eth1 -i eth2 -p 10.10.10.0/24:0:7777 +(vm) $ sudo ./stateless-filter netmap:eth1 -i netmap:eth2 -p 10.10.10.0/24:0:7777 -### Step 7: Inject traffic into the VM +### Step 7: Capture traffic forwarded from the VM -Send UDP traffic (with matching destination IP and port) into the other -end of the pipe corresponding to the EXT port: - -(host) pkt-gen -i vale1:10{1 -f tx -d 10.10.10.23:7777 +Receive traffic from the other end of the pipe corresponding the INT +port: +(host) # pkt-gen -i vale1:10}2 -f rx -### Step 8: Capture traffic forwarded from the VM +### Step 8: Inject traffic into the VM -Receive traffic from the other end of the pipe corresponding the INT -port: -(host) pkt-gen -i vale1:10}2 -f rx +Send UDP traffic (with matching destination IP and port) into the other +end of the pipe corresponding to the EXT port: +(host) # pkt-gen -i vale1:10{1 -f tx -d 10.10.10.23:7777 ### More experiments: 1. Restart the filter, changing the rule to pass only port 80, and check that no traffic is forwarded: -(vm) $ sudo ./stateless-filter -e eth1 -i eth2 -p 10.10.10.0/24:0:80 +(vm) $ sudo ./stateless-filter -e netmap:eth1 -i netmap:eth2 -p 10.10.10.0/24:0:80 2. Try with bidirectional traffic, replacing "-f tx" with "-f ping", and "-f rx" with "-f pong". diff --git a/fosdem2019/stateless-filter.c b/fosdem2019/stateless-filter.c index 63308b3..e93ce89 100644 --- a/fosdem2019/stateless-filter.c +++ b/fosdem2019/stateless-filter.c @@ -201,7 +201,7 @@ rx_ready(struct nm_desc *nmd) static int main_loop(const char *ext_port_name, const char *int_port_name, - struct filtrule *rules, int num_rules) + struct filtrule *rules, int num_rules, int force_copy) { struct nm_desc *ext_port; struct nm_desc *int_port; @@ -232,7 +232,7 @@ main_loop(const char *ext_port_name, const char *int_port_name, } /* Check if we can do zerocopy. */ - zerocopy = (ext_port->mem == int_port->mem); + zerocopy = !force_copy && (ext_port->mem == int_port->mem); printf("zerocopy %sabled\n", zerocopy ? "en" : "dis"); while (!stop) { @@ -282,6 +282,7 @@ main_loop(const char *ext_port_name, const char *int_port_name, printf("Total processed packets: %llu\n", tot); printf("Forwarded packets : %llu\n", fwd); + printf("Dropped packets : %llu\n", tot - fwd); return 0; } @@ -292,7 +293,9 @@ usage(char **argv) printf("usage: %s [-h]\n" " [-p x.y.z.w/mask:proto:dport (pass rule)] [-p ... ]\n" " [-i INTERNAL_PORT]\n" - " [-e EXTERNAL_PORT]\n\n" + " [-e EXTERNAL_PORT]\n" + " [-c (disable zerocopy if supported)]\n" + "\n" " Zero or more pass rules can be specified. A zero value for" " mask, proto or dport means 'any'.\n", argv[0]); @@ -307,10 +310,11 @@ main(int argc, char **argv) const char *ext_port_name = NULL; const char *int_port_name = NULL; struct sigaction sa; + int force_copy = 0; int num_rules = 0; int opt, ret, i; - while ((opt = getopt(argc, argv, "hi:e:p:")) != -1) { + while ((opt = getopt(argc, argv, "hi:e:p:c")) != -1) { switch (opt) { case 'h': usage(argv); @@ -407,6 +411,10 @@ main(int argc, char **argv) break; } + case 'c': + force_copy = 1; + break; + default: printf(" unrecognized option '-%c'\n", opt); usage(argv); @@ -444,7 +452,7 @@ main(int argc, char **argv) rules[i].ip_proto, ntohs(rules[i].dport)); } - main_loop(ext_port_name, int_port_name, rules, num_rules); + main_loop(ext_port_name, int_port_name, rules, num_rules, force_copy); return 0; } From 993fa6e90f079b1b64be1f7359eaf6c9d3f22279 Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Mon, 28 Jan 2019 16:10:43 +0100 Subject: [PATCH 26/28] stateless-filter: minor fix --- fosdem2019/stateless-filter.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/fosdem2019/stateless-filter.c b/fosdem2019/stateless-filter.c index e93ce89..6a17c76 100644 --- a/fosdem2019/stateless-filter.c +++ b/fosdem2019/stateless-filter.c @@ -49,8 +49,7 @@ struct filtrule { }; static inline int -pkt_select(const char *buf, struct filtrule *rules, - int num_rules) +pkt_select(const char *buf, struct filtrule *rules, int num_rules) { struct ether_header *ethh; struct udphdr *udph; @@ -72,7 +71,7 @@ pkt_select(const char *buf, struct filtrule *rules, == rule->ip_daddr && (!rules->ip_proto || rule->ip_proto == iph->ip_p) && (!rule->dport || rule->dport == udph->uh_dport)) { - return 1; + return 1; /* select */ } } From e7ad953d753870187aa05507c55905e7428bbf21 Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Wed, 30 Jan 2019 12:06:57 +0100 Subject: [PATCH 27/28] fosdem2019: improve instructions --- fosdem2019/README | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fosdem2019/README b/fosdem2019/README index dcc8e1b..159f1ad 100644 --- a/fosdem2019/README +++ b/fosdem2019/README @@ -2,7 +2,7 @@ URL: https://fosdem.org/2019/schedule/event/netmap_vnf_development/ -This file contains instructions on how to run the example, step by step. +This file contains step-by-step instructions to run the example. Requirements: - Linux (host) machine with KVM enabled @@ -67,14 +67,14 @@ Run the filter with a rule to pass TCP/UDP traffic towards 10.10.10.0/24, port 7777: (vm) $ cd netmap/tutorial/fosdem2019 -(vm) $ sudo ./stateless-filter netmap:eth1 -i netmap:eth2 -p 10.10.10.0/24:0:7777 +(vm) $ sudo ./stateless-filter -e netmap:eth1 -i netmap:eth2 -p 10.10.10.0/24:0:7777 ### Step 7: Capture traffic forwarded from the VM Receive traffic from the other end of the pipe corresponding the INT port: -(host) # pkt-gen -i vale1:10}2 -f rx +(host) $ sudo pkt-gen -i vale1:10}2 -f rx ### Step 8: Inject traffic into the VM @@ -82,7 +82,7 @@ port: Send UDP traffic (with matching destination IP and port) into the other end of the pipe corresponding to the EXT port: -(host) # pkt-gen -i vale1:10{1 -f tx -d 10.10.10.23:7777 +(host) $ sudo pkt-gen -i vale1:10{1 -f tx -d 10.10.10.23:7777-10.10.10.129:7777 ### More experiments: From 86fb59e8c953838e2a5e6962e63116069897c4db Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Wed, 30 Jan 2019 12:12:16 +0100 Subject: [PATCH 28/28] README: add more command line for pkt-gen transmitter --- fosdem2019/README | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/fosdem2019/README b/fosdem2019/README index 159f1ad..2a3e153 100644 --- a/fosdem2019/README +++ b/fosdem2019/README @@ -82,7 +82,7 @@ port: Send UDP traffic (with matching destination IP and port) into the other end of the pipe corresponding to the EXT port: -(host) $ sudo pkt-gen -i vale1:10{1 -f tx -d 10.10.10.23:7777-10.10.10.129:7777 +(host) $ sudo pkt-gen -i vale1:10{1 -f tx -d 10.10.10.23:7777 ### More experiments: @@ -95,3 +95,6 @@ end of the pipe corresponding to the EXT port: and "-f rx" with "-f pong". 3. Add more pass rule or use a pass-any rule ("0.0.0.0/0:0:0"). + +4. Try with destination address and ports in a range +(host) $ sudo pkt-gen -i vale1:10{1 -f tx -d 10.10.10.23:7777-10.10.10.129:7780