From: Adam E. <ada...@ns...> - 2013-04-23 16:49:59
|
Hi again, First of all, thank you for your replies to my past questions. Now I'm trying to build a simulated network with Linux containers to make it easier to test my program. However, I have mixed and (in the case of SCTP) disappointing results. I've written a program and attached it to this mail, which brings up the veth interfaces, creates the separate network namespace, and tries to communicate over the tunnel. In summary, pinging and TCP work well with any combination of -6, -N and -i flags of the program. SCTP also works if I don't put the remote end to a separate namespace with -N. If I do (no -N) then either: -- for IPv4 connections socket(PF_INET, SOCK_STREAM, IPPROTO_SCTP) says "Address family not supported by protocol" -- for IPv6 connections bind() complains "Cannot assign requested address" (even though the socket is bound to the respective interface) Can you explain what could possibly go wrong? My kernel is 2.6.32-5-amd64 from Debian and libsctp is version 1.0.11+dfsg-1. (There's a bonus question: at the beginning of prepare() you'll find a sleep() which I don't understand why is needed. Let it be enough to say that without it IPv6 under TCP and ping behaves the same manner as for SCTP.) Thanks, adam |
From: Vlad Y. <vya...@gm...> - 2013-04-23 17:15:11
|
Hi Adam On 04/23/2013 12:45 PM, Adam Endrodi wrote: > > Hi again, > > > First of all, thank you for your replies to my past questions. > Now I'm trying to build a simulated network with Linux containers > to make it easier to test my program. However, I have mixed and > (in the case of SCTP) disappointing results. > > I've written a program and attached it to this mail, which brings up > the veth interfaces, creates the separate network namespace, and tries > to communicate over the tunnel. This list strips off all attachments except text, so your program didn't come through. Best to post a link to it. > > In summary, pinging and TCP work well with any combination of -6, -N > and -i flags of the program. SCTP also works if I don't put the remote > end to a separate namespace with -N. If I do (no -N) then either: > -- for IPv4 connections socket(PF_INET, SOCK_STREAM, IPPROTO_SCTP) > says "Address family not supported by protocol" > -- for IPv6 connections bind() complains "Cannot assign requested address" > (even though the socket is bound to the respective interface) > > Can you explain what could possibly go wrong? My kernel is 2.6.32-5-amd64 > from Debian and libsctp is version 1.0.11+dfsg-1. SCTP is not namespace aware in 2.6.32. That would explain your SCTP results. > > (There's a bonus question: at the beginning of prepare() you'll find a > sleep() which I don't understand why is needed. Let it be enough to say > that without it IPv6 under TCP and ping behaves the same manner as for > SCTP.) Don't know since the list stripped off your program. Since you seem to need it for TCP as well, ask on netdev. -vlad > > Thanks, > adam > > > > ------------------------------------------------------------------------------ > Try New Relic Now & We'll Send You this Cool Shirt > New Relic is the only SaaS-based application performance monitoring service > that delivers powerful full stack analytics. Optimize and monitor your > browser, app, & servers with just a few lines of code. Try New Relic > and get this awesome Nerd Life shirt! http://p.sf.net/sfu/newrelic_d2d_apr > > > > _______________________________________________ > Lksctp-developers mailing list > Lks...@li... > https://lists.sourceforge.net/lists/listinfo/lksctp-developers > |
From: Adam E. <ada...@ns...> - 2013-04-24 08:04:08
|
Hi vlad, On Tue, Apr 23, 2013 at 01:15:01PM -0400, ext Vlad Yasevich wrote: > > This list strips off all attachments except text, so your program > didn't come through. Best to post a link to it. OK, I'll quote it at the end of this mail, maybe somebody will find it useful. > SCTP is not namespace aware in 2.6.32. That would explain your > SCTP results. Yeah, it really does. Can you tell from which version is it ns-aware? I still have a problem with SCTP over IPv6 even if I leave namespaces out of scope. If i run `threesome -p sctp -6' it still complains that "Cannot assign requested address", while `threesome -p tcp -6' works perfectly. > >(There's a bonus question: at the beginning of prepare() you'll find a > > sleep() which I don't understand why is needed. Let it be enough to say > > that without it IPv6 under TCP and ping behaves the same manner as for > > SCTP.) Thanks, adam ====================================================================== /* * threesome.c -- test how different protocols manage with veth * * This program creates a pair of veth network devices, configures them, * and optionally puts one of the pair into an isolated network space. * Then it either pings one side from the other or sends messages over * TCP or SCTP likewise. Both IPv4 and IPv6 are supported. You need * to run this program with superuser privileges. * * Compile as: cc -Wall threesome.c -lsctp -o threesome * * Usage: * threesome [-N46i] [-p {ping|tcp|sctp}] * [-m <master-address>] [-s <slave-address>] * [-P <port>] * * Options: * -N Do not put one of the veth devices * to another network space. * -4 Use IPv4 (default). * -6 Use IPv6. * -m <master-address> IP address of veth0. You can only specify * IPv4 address, because the IPv6 address is * generated by veth at the time both devices * are pulled up. The default is 1.2.3.4. * -s <slave-address> IP address of the device which is put into * a separate namespace. Default is 1.2.3.5. * -P <port> The port of the server side. * -i By default, we communicate from the master * side (eg. we ping the slave from the master). * With this flag you can switch the roles. */ /* Include files */ #include <stdlib.h> #include <stdarg.h> #include <unistd.h> #include <assert.h> #include <stdio.h> #include <string.h> #include <sched.h> #include <arpa/inet.h> #include <netinet/in.h> #include <sys/time.h> #include <sys/wait.h> // Maximum size of an IPv6 address in hexadecimal representation. #define IPV6_ADDRLEN (4*8 + 7 + 4 + 1) // Either "main", "master" or "slave". static const char *Whoami = "main"; /* Program code */ // Like popen(3), except that it has an execlp(3)-like interface. // NOTE the child is not reaped when @st is closed. static FILE *__attribute__((sentinel)) cmd_pipe(char *prg, ...) { int childs_stdout[2]; unsigned n, i; va_list args; char **argv; FILE *st; // Make new file descriptor. assert(!pipe(childs_stdout)); assert((st = fdopen(childs_stdout[0], "r")) != NULL); if (fork()) { close(childs_stdout[1]); return st; } else { fclose(st); assert(dup2(childs_stdout[1], STDOUT_FILENO) == STDOUT_FILENO); } // Count the number of parameters. va_start(args, prg); for (n = 0; va_arg(args, char *); n++) ; va_end(args); // Copy the arguments to argv. assert((argv = malloc(sizeof(*argv) * (1+n+1))) != NULL); va_start(args, prg); argv[0] = prg; printf("%6s: %s", Whoami, argv[0]); for (i = 1; n > 0; n--, i++) { // Print the command line. argv[i] = va_arg(args, char *); printf(" %s", argv[i]); } puts(" |"); argv[i] = NULL; va_end(args); assert(!execvp(argv[0], argv)); abort(); } // Just like system(3) but with execlp(3) syntax. static void __attribute__((sentinel)) cmd(char *prg, ...) { pid_t child; if (!(child = fork())) { unsigned n, i; va_list args; char **argv; // Count the number of parameters. va_start(args, prg); for (n = 0; va_arg(args, char *); n++) ; va_end(args); // Copy the arguments to argv. assert((argv = malloc(sizeof(*argv) * (1+n+1))) != NULL); va_start(args, prg); argv[0] = prg; printf("%6s: %s", Whoami, argv[0]); for (i = 1; n > 0; n--, i++) { // Print the command line. argv[i] = va_arg(args, char *); printf(" %s", argv[i]); } putchar('\n'); argv[i] = NULL; va_end(args); assert(!execvp(argv[0], argv)); } else { int status; // Wait until the child finishes. while (waitpid(child, &status, 0) > 0) assert(WIFEXITED(status) && WEXITSTATUS(status) == 0); } } // Logging static void __attribute__((noreturn, format(printf, 1, 2))) error(const char *fmt, ...) { va_list args; fprintf(stderr, "%6s: ", Whoami); va_start(args, fmt); vfprintf(stderr, fmt, args); va_end(args); fputc('\n', stderr); exit(1); } static void __attribute__((format(printf, 1, 2))) logit(const char *fmt, ...) { va_list args; printf("%6s: ", Whoami); va_start(args, fmt); vprintf(fmt, args); va_end(args); putchar('\n'); } static void __attribute__((noreturn)) usage(const char *prg) { const char *fname; if (!(fname = strrchr(prg, '/'))) fname = prg; else fname = prg+1; printf("%s [-N] [-46] [-p {ping|tcp|sctp}] [-m <master's-ip>] " "[-s <slave's ip>] [-i]\n", fname); exit(1); } // Retrieve the IPv6 address of @iface. static void get_ipv6_address(char ip[IPV6_ADDRLEN], const char *iface) { FILE *st; char line[128]; st = cmd_pipe("ifconfig", iface, NULL); while (fgets(line, sizeof(line), st)) { char *p; // inet6 addr: fe80::243a:1aff:fe7d:4cf0/64 Scope:Link if (sscanf(line, " inet6 addr: %s", ip) < 1) continue; if ((p = strrchr(ip, '/')) != NULL) *p = '\0'; fclose(st); return; } abort(); } // Populate a sockaddr_in with @ip and @port. static void fill_saddr4(struct sockaddr_in *saddr, const char *ip, unsigned port) { memset(saddr, 0, sizeof(*saddr)); saddr->sin_family = AF_INET; assert(inet_pton(AF_INET, ip, &saddr->sin_addr)); saddr->sin_port = htons(port); } // Populate a sockaddr_in6 with @ip and @port. static void fill_saddr6(struct sockaddr_in6 *saddr, const char *ip, unsigned port) { memset(saddr, 0, sizeof(*saddr)); saddr->sin6_family = AF_INET6; assert(inet_pton(AF_INET6, ip, &saddr->sin6_addr) == 1); saddr->sin6_port = htons(port); } // Prepare a socket: create it, set socket options, bind() and listen() // if !@is_client. static int prepare(int is_master, unsigned ip_version, const char *proto, const char *ip, unsigned dst_port, int is_client) { int sfd, on; const char *iface; // The purpose of sleeping here is unknown, but if omitted, // IPv6 doesn't work properly. if (ip_version == 6 && !is_client) { struct timeval tv; gettimeofday(&tv, NULL); logit("sleeping for 2 seconds (%lu.%6lu)", tv.tv_sec, tv.tv_usec); sleep(2); gettimeofday(&tv, NULL); logit("woken up (%lu.%6lu)", tv.tv_sec, tv.tv_usec); } if (!strcmp(proto, "ping")) return -1; iface = is_master ? "veth0" : "veth1"; // Create the socket. logit("socket(%s, SOCK_STREAM, %s)", ip_version == 4 ? "PF_INET" : "PF_INET6", !strcmp(proto, "tcp") ? "IPPROTO_TCP" : "IPPROTO_SCTP"); if ((sfd = socket(ip_version == 4 ? PF_INET : PF_INET6, SOCK_STREAM, !strcmp(proto, "sctp") ? IPPROTO_SCTP : 0)) < 0) error("socket(): %m"); // veth generates link-local IPv6 addresses, so we must bind // to the interface. if (ip_version == 6) { logit("binding socket to %s", iface); assert(!setsockopt(sfd, SOL_SOCKET, SO_BINDTODEVICE, iface, strlen(iface) + 1)); } if (is_client) return sfd; // bind() on = 1; logit("setsockopt(SO_REUSEADDR)"); assert(!setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))); if (ip_version == 4) { struct sockaddr_in saddr; // bind() to @ip:@dst_port. logit("bind(%s:%u)", ip, dst_port); fill_saddr4(&saddr, ip, dst_port); if (bind(sfd, (const struct sockaddr *)&saddr, sizeof(saddr)) < 0) error("bind(%s:%u): %m", ip, dst_port); } else { char ip6[IPV6_ADDRLEN]; struct sockaddr_in6 saddr; // Bind to the IPv6 address of @iface and @dst_port. get_ipv6_address(ip6, iface); fill_saddr6(&saddr, ip6, dst_port); logit("bind([%s]:%u)", ip6, dst_port); if (bind(sfd, (const struct sockaddr *)&saddr, sizeof(saddr)) < 0) error("bind([%s]:%u): %m", ip6, dst_port); } logit("listen()"); assert(!listen(sfd, 1)); return sfd; } // connect() if necessary and communicate with @dst_ip and @dst_port. static void __attribute__((noreturn)) run(int is_master, int sfd, unsigned ip_version, const char *proto, const char *dst_ip, unsigned dst_port, int is_client) { const char *iface; iface = is_master ? "veth0" : "veth1"; if (!is_client) { // Server role if (!strcmp(proto, "ping")) // We'll be pinged, nothing to do anymore. for (;;) pause(); // TCP or SCTP for (;;) { int cfd; ssize_t len; char line[128]; // Read the socket line by line and print it. printf("%6s: accept()...", Whoami); fflush(stdout); assert((cfd = accept(sfd, NULL, NULL)) >= 0); putchar('\n'); while ((len = read(cfd, line, sizeof(line))) > 0) { line[len] = '\0'; printf("%s <- %s\n", Whoami, line); } close(cfd); } } else if (!strcmp(proto, "ping")) { // ping @dst_ip. if (ip_version == 4) cmd("ping", dst_ip, NULL); else cmd("ping6", "-I", iface, dst_ip, NULL); abort(); } else { // Client role TCP/SCTP static char const *const alpha[] = { "alpha", "beta", "gamma", "delta", "epsilon", "zeta", "eta", "theta", "iota", "kappa", "lambda", "mu", "nu", "xi", "omicron", "pi", "rho", "sigma", "tau", "upsilon", "phi", "chi", "psi", "omega", NULL }; const char *const *letter; printf("%6s: Connecting to %s:%u...", Whoami, dst_ip, dst_port); fflush(stdout); // connect() if (ip_version == 4) { struct sockaddr_in saddr; fill_saddr4(&saddr, dst_ip, dst_port); assert(!connect(sfd, (const struct sockaddr *)&saddr, sizeof(saddr))); } else { struct sockaddr_in6 saddr; fill_saddr6(&saddr, dst_ip, dst_port); assert(!connect(sfd, (const struct sockaddr *)&saddr, sizeof(saddr))); } putchar('\n'); // Send @alpha element by element. letter = &alpha[0]; for (;;) { printf("%s -> %s", Whoami, *letter); assert(write(sfd, *letter, strlen(*letter)) > 0); sleep(1); letter++; if (!*letter) letter = &alpha[0]; } } } /* The main function */ int main(int argc, char *argv[]) { FILE *st; char c, line[16]; int optchar, m2s[2], s2m[2]; int opt_master_connects, opt_new_namespace; unsigned opt_ip_version, opt_server_port; const char *opt_proto, *opt_master_ip, *opt_slave_ip; // Parse the command line. opt_ip_version = 4; opt_proto = "tcp"; opt_master_ip = "1.2.3.4"; opt_slave_ip = "1.2.3.5"; opt_server_port = 2222; opt_master_connects = 1; opt_new_namespace = 1; while ((optchar = getopt(argc, argv, "N46p:m:s:P:i")) != EOF) switch (optchar) { case 'N': opt_new_namespace = 0; break; case '4': opt_ip_version = 4; break; case '6': opt_ip_version = 6; break; case 'p': opt_proto = optarg; if (strcmp(opt_proto, "ping") && strcmp(opt_proto, "tcp") && strcmp(opt_proto, "sctp")) usage(argv[0]); break; case 'm': opt_master_ip = optarg; break; case 's': opt_slave_ip = optarg; break; case 'P': opt_server_port = atoi(optarg); break; case 'i': opt_master_connects = !opt_master_connects; break; default: usage(argv[0]); }; setvbuf(stdout, NULL, _IOLBF, 0); if (geteuid() != 0) error("you need to be superuser to use this program."); logit("configuring veth0"); cmd("modprobe", "veth", NULL); // Clean up: delete all existing veth devices. st = cmd_pipe("ip", "link", NULL); while (fgets(line, sizeof(line), st)) { char dev[8]; unsigned vethn; if (sscanf(line, "%*u: veth%u:", &vethn) != 1 || vethn % 2) continue; snprintf(dev, sizeof(dev), "veth%u", vethn); cmd("ip", "link", "del", dev, NULL); } fclose(st); // Prepare veth0. cmd("ip", "link", "add", "type", "veth", NULL); cmd("ip", "addr", "add", opt_master_ip, "dev", "veth0", NULL); cmd("ifconfig", "veth0", "up", NULL); // Add routes to the destination addresses. cmd("ip", "route", "add", "to", opt_slave_ip, "dev", "veth0", NULL); logit("veth0 configured"); // Fork to master (outside the namespace) and slave (contained // in a network namespace) branches. assert(!pipe(s2m)); assert(!pipe(m2s)); if (!fork()) { // Master int sfd; char slave_ip6[IPV6_ADDRLEN]; Whoami = "master"; close(m2s[0]); close(s2m[1]); if (opt_new_namespace) { char ppid[8]; // Wait until the slave has unshare()d, // then give it veth1. logit("waiting for slave to unshare()"); read(s2m[0], &c, 1); logit("slave has unshared, giving veth1 away"); snprintf(ppid, sizeof(ppid), "%u", getppid()); cmd("ip", "link", "set", "veth1", "netns", ppid, NULL); write(m2s[1], "x", 1); logit("veth1 has been given away"); // We've transferred veth1 to the slave. } // Wait for slave to configure, then we can acquire // the veth-generated IPv6 addresses. logit("waiting for slave to configure veth1"); read(s2m[0], &c, 1); logit("veth1 configured, preparing socket"); sfd = prepare(1, opt_ip_version, opt_proto, opt_master_ip, opt_server_port, opt_master_connects); logit("prepared socket"); if (opt_master_connects) { // Wait until slave prepares. if (opt_ip_version == 4) { logit("waiting for slave to prepare"); read(s2m[0], &c, 1); } else { // Retrieve the slave's IPv6 address. logit("waiting for slave's IPv6 address"); assert(read(s2m[0], slave_ip6, sizeof(slave_ip6)) == sizeof(slave_ip6)); } } else if (opt_ip_version == 6) { // Send out IPv6 address to the slave. char master_ip6[IPV6_ADDRLEN]; logit("sending our IPv6 address to slave"); get_ipv6_address(master_ip6, "veth0"); write(m2s[1], master_ip6, sizeof(master_ip6)); } else { logit("informing slave that we're prepared"); write(m2s[1], "x", 1); } logit("running..."); run(1, sfd, opt_ip_version, opt_proto, opt_ip_version == 4 ? opt_slave_ip : slave_ip6, opt_server_port, opt_master_connects); } else { // Slave int sfd; char master_ip6[IPV6_ADDRLEN]; Whoami = "slave"; close(m2s[1]); close(s2m[0]); // Let's have our own network space. if (opt_new_namespace) { logit("going into new network space"); assert(!unshare(CLONE_NEWNET)); // We've unshare()d. logit("residing in new network space, waiting for " "master to give veth1 to us"); write(s2m[1], "x", 1); read(m2s[0], &c, 1); // We've got veth1. } // Configure veth1. logit("configuring veth1"); cmd("ifconfig", "lo", "up", NULL); cmd("ifconfig", "veth1", "up", NULL); cmd("ip", "route", "add", "to", opt_master_ip, "dev", "veth1", NULL); cmd("ip", "addr", "add", opt_slave_ip, "dev", "veth1", NULL); logit("veth1 configured"); write(s2m[1], "x", 1); // Finished configuration. logit("preparing, socket"); sfd = prepare(0, opt_ip_version, opt_proto, opt_slave_ip, opt_server_port, !opt_master_connects); logit("prepared socket"); if (opt_master_connects) { if (opt_ip_version == 6) { // Send our IPv6 address to the master. char ip6[IPV6_ADDRLEN]; logit("sending master our IPv6 address"); get_ipv6_address(ip6, "veth1"); write(s2m[1], ip6, sizeof(ip6)); } else { logit("informing master that we're prepared"); write(s2m[1], "x", 1); } } else if (opt_ip_version == 6) { // Get the master's IPv6 address. logit("waiting for master's IPv6 address"); assert(read(m2s[0], master_ip6, sizeof(master_ip6)) == sizeof(master_ip6)); } else { logit("waiting for master to prepare"); read(m2s[0], &c, 1); } logit("running..."); run(0, sfd, opt_ip_version, opt_proto, opt_ip_version == 4 ? opt_master_ip : master_ip6, opt_server_port, !opt_master_connects); } /* Not reached */ } /* threesome.c */ ====================================================================== |
From: Adam E. <ada...@ns...> - 2013-04-24 08:11:18
|
On Wed, Apr 24, 2013 at 09:59:55AM +0200, Adam Endrodi wrote: > > On Tue, Apr 23, 2013 at 01:15:01PM -0400, ext Vlad Yasevich wrote: > > > > This list strips off all attachments except text, so your program > > didn't come through. Best to post a link to it. > > OK, I'll quote it at the end of this mail, maybe somebody will find > it useful. > > > SCTP is not namespace aware in 2.6.32. That would explain your > > SCTP results. > > Yeah, it really does. Can you tell from which version is it ns-aware? > > I still have a problem with SCTP over IPv6 even if I leave namespaces > out of scope. If i run `threesome -p sctp -6' it still complains that > "Cannot assign requested address", while `threesome -p tcp -6' works > perfectly. Sorry, I meant `./threesome -p sctp -N6' and `threesome -p tcp -N6' here. > > >(There's a bonus question: at the beginning of prepare() you'll find a > > > sleep() which I don't understand why is needed. Let it be enough to say > > > that without it IPv6 under TCP and ping behaves the same manner as for > > > SCTP.) -- adam |
From: Vlad Y. <vya...@gm...> - 2013-04-24 16:50:43
|
On 04/24/2013 04:07 AM, Adam Endrodi wrote: > On Wed, Apr 24, 2013 at 09:59:55AM +0200, Adam Endrodi wrote: >> >> On Tue, Apr 23, 2013 at 01:15:01PM -0400, ext Vlad Yasevich wrote: >>> >>> This list strips off all attachments except text, so your program >>> didn't come through. Best to post a link to it. >> >> OK, I'll quote it at the end of this mail, maybe somebody will find >> it useful. >> >>> SCTP is not namespace aware in 2.6.32. That would explain your >>> SCTP results. >> >> Yeah, it really does. Can you tell from which version is it ns-aware? >> >> I still have a problem with SCTP over IPv6 even if I leave namespaces >> out of scope. If i run `threesome -p sctp -6' it still complains that >> "Cannot assign requested address", while `threesome -p tcp -6' works >> perfectly. > > Sorry, I meant `./threesome -p sctp -N6' and `threesome -p tcp -N6' here. > >>>> (There's a bonus question: at the beginning of prepare() you'll find a >>>> sleep() which I don't understand why is needed. Let it be enough to say >>>> that without it IPv6 under TCP and ping behaves the same manner as for >>>> SCTP.) > So, I think the sleep for IPv6 is needed for DAD to finish. You can check that by checking to see if the addresses start out as tentative on the veth interface. The bind() for you most likely fails because you don't set sin6_scope_id(). Seems that SCTP ignores the fact that the socket is bound to device and looks for scope_id if the address is link-local. -vlad |
From: Adam E. <ada...@ns...> - 2013-04-25 08:40:12
|
On Wed, Apr 24, 2013 at 12:50:35PM -0400, ext Vlad Yasevich wrote: > On 04/24/2013 04:07 AM, Adam Endrodi wrote: > >> > >>>SCTP is not namespace aware in 2.6.32. That would explain your > >>>SCTP results. > >> > >>Yeah, it really does. Can you tell from which version is it ns-aware? Can you please answer this question? > So, I think the sleep for IPv6 is needed for DAD to finish. You can > check that by checking to see if the addresses start out as tentative > on the veth interface. What is DAD and how to check the tentativeness? > The bind() for you most likely fails because you don't set > sin6_scope_id(). Seems that SCTP ignores the fact that the socket is > bound to device and looks for scope_id if the address is link-local. I've added the scope_id, and the situation has improved: now bind() is successfull, but connect() blocks and doesn't succeed. The code with which I set the interface index is: # memset(&iface_info, 0, sizeof(iface_info)); # strcpy(iface_info.ifr_name, iface); # assert(!ioctl(sfd, SIOCGIFINDEX, &iface_info)); # saddr->sin6_scope_id = iface_info.ifr_ifindex; You can find the full source at http://pastebin.com/n3Tg6FQw Thanks, adam |
From: Vlad Y. <vya...@gm...> - 2013-04-25 14:48:49
|
On 04/25/2013 04:35 AM, Adam Endrodi wrote: > On Wed, Apr 24, 2013 at 12:50:35PM -0400, ext Vlad Yasevich wrote: >> On 04/24/2013 04:07 AM, Adam Endrodi wrote: >>>> >>>>> SCTP is not namespace aware in 2.6.32. That would explain your >>>>> SCTP results. >>>> >>>> Yeah, it really does. Can you tell from which version is it ns-aware? > > Can you please answer this question? 3.8 has that latest fixes. > >> So, I think the sleep for IPv6 is needed for DAD to finish. You can >> check that by checking to see if the addresses start out as tentative >> on the veth interface. > > What is DAD and how to check the tentativeness? Duplicate address detection. When IPv6 address is configured on the interface, the kernel delays it for about 1 second and checks to see if anyone on the link uses this addresses. Some point-to-point interfaces set IFF_NOARP which disable duplicate address detection thus allowing you to use the address right the way. Doesn't look like veth sets that by default so you would be susceptible to the delay. > >> The bind() for you most likely fails because you don't set >> sin6_scope_id(). Seems that SCTP ignores the fact that the socket is >> bound to device and looks for scope_id if the address is link-local. > > I've added the scope_id, and the situation has improved: now bind() is > successfull, but connect() blocks and doesn't succeed. The code with > which I set the interface index is: > > # memset(&iface_info, 0, sizeof(iface_info)); > # strcpy(iface_info.ifr_name, iface); > # assert(!ioctl(sfd, SIOCGIFINDEX, &iface_info)); > # saddr->sin6_scope_id = iface_info.ifr_ifindex; Try not binding to interface and see if it changes things. If so, then packets are most likely arriving on lo instead of veth and sctp rejecting it. -vlad > > You can find the full source at http://pastebin.com/n3Tg6FQw > > Thanks, > adam > > ------------------------------------------------------------------------------ > Try New Relic Now & We'll Send You this Cool Shirt > New Relic is the only SaaS-based application performance monitoring service > that delivers powerful full stack analytics. Optimize and monitor your > browser, app, & servers with just a few lines of code. Try New Relic > and get this awesome Nerd Life shirt! http://p.sf.net/sfu/newrelic_d2d_apr > _______________________________________________ > Lksctp-developers mailing list > Lks...@li... > https://lists.sourceforge.net/lists/listinfo/lksctp-developers > |
From: Adam E. <ada...@ns...> - 2013-04-25 15:24:47
|
On Thu, Apr 25, 2013 at 10:48:40AM -0400, ext Vlad Yasevich wrote: > > > >>The bind() for you most likely fails because you don't set > >>sin6_scope_id(). Seems that SCTP ignores the fact that the socket is > >>bound to device and looks for scope_id if the address is link-local. > > > >I've added the scope_id, and the situation has improved: now bind() is > >successfull, but connect() blocks and doesn't succeed. The code with > >which I set the interface index is: > > > ># memset(&iface_info, 0, sizeof(iface_info)); > ># strcpy(iface_info.ifr_name, iface); > ># assert(!ioctl(sfd, SIOCGIFINDEX, &iface_info)); > ># saddr->sin6_scope_id = iface_info.ifr_ifindex; > > Try not binding to interface and see if it changes things. If so, then > packets are most likely arriving on lo instead of veth and sctp > rejecting it. I've done so, and you seem to be right. Capture from lo: 17:14:41.385205 IP6 fe80::14ac:a0ff:fe88:3ef4.2222 > fe80::14ac:a0ff:fe88:3ef4.43126: sctp (1) [INIT ACK] [init tag: 555384379] [rwnd: 62464] [OS: 10] [MIS: 10] [init TSN: 2331289327] 17:14:41.385217 IP6 fe80::14ac:a0ff:fe88:3ef4.43126 > fe80::14ac:a0ff:fe88:3ef4.2222: sctp (1) [ABORT] 17:14:44.380944 IP6 fe80::14ac:a0ff:fe88:3ef4.2222 > fe80::14ac:a0ff:fe88:3ef4.43126: sctp (1) [INIT ACK] [init tag: 694291839] [rwnd: 62464] [OS: 10] [MIS: 10] [init TSN: 3640870654] 17:14:44.380956 IP6 fe80::14ac:a0ff:fe88:3ef4.43126 > fe80::14ac:a0ff:fe88:3ef4.2222: sctp (1) [ABORT] 17:14:50.380935 IP6 fe80::14ac:a0ff:fe88:3ef4.2222 > fe80::14ac:a0ff:fe88:3ef4.43126: sctp (1) [INIT ACK] [init tag: 3392470941] [rwnd: 62464] [OS: 10] [MIS: 10] [init TSN: 1449867390] 17:14:50.380948 IP6 fe80::14ac:a0ff:fe88:3ef4.43126 > fe80::14ac:a0ff:fe88:3ef4.2222: sctp (1) [ABORT] 17:15:02.380944 IP6 fe80::14ac:a0ff:fe88:3ef4.2222 > fe80::14ac:a0ff:fe88:3ef4.43126: sctp (1) [INIT ACK] [init tag: 2252399736] [rwnd: 62464] [OS: 10] [MIS: 10] [init TSN: 2249322920] 17:15:02.380956 IP6 fe80::14ac:a0ff:fe88:3ef4.43126 > fe80::14ac:a0ff:fe88:3ef4.2222: sctp (1) [ABORT] 17:15:26.380955 IP6 fe80::14ac:a0ff:fe88:3ef4.2222 > fe80::14ac:a0ff:fe88:3ef4.43126: sctp (1) [INIT ACK] [init tag: 3920373398] [rwnd: 62464] [OS: 10] [MIS: 10] [init TSN: 4146045988] 17:15:26.380973 IP6 fe80::14ac:a0ff:fe88:3ef4.43126 > fe80::14ac:a0ff:fe88:3ef4.2222: sctp (1) [ABORT] 17:16:14.380969 IP6 fe80::14ac:a0ff:fe88:3ef4.2222 > fe80::14ac:a0ff:fe88:3ef4.43126: sctp (1) [INIT ACK] [init tag: 2105652358] [rwnd: 62464] [OS: 10] [MIS: 10] [init TSN: 2074272665] 17:16:14.380980 IP6 fe80::14ac:a0ff:fe88:3ef4.43126 > fe80::14ac:a0ff:fe88:3ef4.2222: sctp (1) [ABORT] Capture from veth0: listening on veth0, link-type EN10MB (Ethernet), capture size 65535 bytes 17:09:26.672886 IP6 fe80::a434:52ff:fe76:8c17 > ff02::2: ICMP6, router solicitation, length 16 17:09:26.716835 IP6 fe80::94be:58ff:feec:32fb > ff02::2: ICMP6, router solicitation, length 16 17:09:27.484756 IP6 fe80::a434:52ff:fe76:8c17 > ff02::1:ffec:32fb: ICMP6, neighbor solicitation, who has fe80::94be:58ff:feec:32fb, length 32 17:09:27.484809 IP6 fe80::94be:58ff:feec:32fb > fe80::a434:52ff:fe76:8c17: ICMP6, neighbor advertisement, tgt is fe80::94be:58ff:feec:32fb, length 32 17:09:27.484814 IP6 fe80::94be:58ff:feec:32fb.43806 > fe80::94be:58ff:feec:32fb.2222: sctp (1) [INIT] [init tag: 1521002698] [rwnd: 62464] [OS: 10] [MIS: 65535] [init TSN: 23399978] 17:09:28.176829 IP6 fe80::94be:58ff:feec:32fb > ff02::16: HBH ICMP6, multicast listener report v2, 1 group record(s), length 28 17:09:29.904764 IP6 fe80::a434:52ff:fe76:8c17 > ff02::16: HBH ICMP6, multicast listener report v2, 1 group record(s), length 28 17:09:30.480774 IP6 fe80::94be:58ff:feec:32fb.43806 > fe80::94be:58ff:feec:32fb.2222: sctp (1) [INIT] [init tag: 1521002698] [rwnd: 62464] [OS: 10] [MIS: 65535] [init TSN: 23399978] 17:09:30.672764 IP6 fe80::a434:52ff:fe76:8c17 > ff02::2: ICMP6, router solicitation, length 16 17:09:30.716778 IP6 fe80::94be:58ff:feec:32fb > ff02::2: ICMP6, router solicitation, length 16 17:09:32.484775 IP6 fe80::94be:58ff:feec:32fb > fe80::a434:52ff:fe76:8c17: ICMP6, neighbor solicitation, who has fe80::a434:52ff:fe76:8c17, length 32 17:09:32.484810 IP6 fe80::a434:52ff:fe76:8c17 > fe80::94be:58ff:feec:32fb: ICMP6, neighbor advertisement, tgt is fe80::a434:52ff:fe76:8c17, length 24 17:09:34.672764 IP6 fe80::a434:52ff:fe76:8c17 > ff02::2: ICMP6, router solicitation, length 16 17:09:34.716779 IP6 fe80::94be:58ff:feec:32fb > ff02::2: ICMP6, router solicitation, length 16 17:09:36.480775 IP6 fe80::94be:58ff:feec:32fb.43806 > fe80::94be:58ff:feec:32fb.2222: sctp (1) [INIT] [init tag: 1521002698] [rwnd: 62464] [OS: 10] [MIS: 65535] [init TSN: 23399978] 17:09:48.480796 IP6 fe80::94be:58ff:feec:32fb.43806 > fe80::94be:58ff:feec:32fb.2222: sctp (1) [INIT] [init tag: 1521002698] [rwnd: 62464] [OS: 10] [MIS: 65535] [init TSN: 23399978] Capture from veth1: 17:12:35.893022 IP6 :: > ff02::1:ffe0:c242: ICMP6, neighbor solicitation, who has fe80::c01e:67ff:fee0:c242, length 24 17:12:36.452772 IP6 fe80::f432:85ff:fec4:62ef > ff02::2: ICMP6, router solicitation, length 16 17:12:36.892774 IP6 fe80::c01e:67ff:fee0:c242 > ff02::2: ICMP6, router solicitation, length 16 17:12:37.261014 IP6 fe80::f432:85ff:fec4:62ef > ff02::1:ffe0:c242: ICMP6, neighbor solicitation, who has fe80::c01e:67ff:fee0:c242, length 32 17:12:37.261036 IP6 fe80::c01e:67ff:fee0:c242 > fe80::f432:85ff:fec4:62ef: ICMP6, neighbor advertisement, tgt is fe80::c01e:67ff:fee0:c242, length 32 17:12:37.261045 IP6 fe80::c01e:67ff:fee0:c242.34456 > fe80::c01e:67ff:fee0:c242.2222: sctp (1) [INIT] [init tag: 2225940771] [rwnd: 62464] [OS: 10] [MIS: 65535] [init TSN: 3329781206] 17:12:40.257044 IP6 fe80::c01e:67ff:fee0:c242.34456 > fe80::c01e:67ff:fee0:c242.2222: sctp (1) [INIT] [init tag: 2225940771] [rwnd: 62464] [OS: 10] [MIS: 65535] [init TSN: 3329781206] 17:12:40.453041 IP6 fe80::f432:85ff:fec4:62ef > ff02::2: ICMP6, router solicitation, length 16 17:12:40.621003 IP6 fe80::c01e:67ff:fee0:c242 > ff02::16: HBH ICMP6, multicast listener report v2, 1 group record(s), length 28 17:12:40.892753 IP6 fe80::c01e:67ff:fee0:c242 > ff02::2: ICMP6, router solicitation, length 16 17:12:42.260752 IP6 fe80::c01e:67ff:fee0:c242 > fe80::f432:85ff:fec4:62ef: ICMP6, neighbor solicitation, who has fe80::f432:85ff:fec4:62ef, length 32 17:12:42.260794 IP6 fe80::f432:85ff:fec4:62ef > fe80::c01e:67ff:fee0:c242: ICMP6, neighbor advertisement, tgt is fe80::f432:85ff:fec4:62ef, length 24 17:12:44.452756 IP6 fe80::f432:85ff:fec4:62ef > ff02::2: ICMP6, router solicitation, length 16 17:12:44.473028 IP6 fe80::f432:85ff:fec4:62ef > ff02::16: HBH ICMP6, multicast listener report v2, 1 group record(s), length 28 17:12:44.893001 IP6 fe80::c01e:67ff:fee0:c242 > ff02::2: ICMP6, router solicitation, length 16 17:12:46.257044 IP6 fe80::c01e:67ff:fee0:c242.34456 > fe80::c01e:67ff:fee0:c242.2222: sctp (1) [INIT] [init tag: 2225940771] [rwnd: 62464] [OS: 10] [MIS: 65535] [init TSN: 3329781206] 17:12:58.257045 IP6 fe80::c01e:67ff:fee0:c242.34456 > fe80::c01e:67ff:fee0:c242.2222: sctp (1) [INIT] [init tag: 2225940771] [rwnd: 62464] [OS: 10] [MIS: 65535] [init TSN: 3329781206] 17:13:03.257037 IP6 fe80::f432:85ff:fec4:62ef > fe80::c01e:67ff:fee0:c242: ICMP6, neighbor solicitation, who has fe80::c01e:67ff:fee0:c242, length 32 17:13:03.257053 IP6 fe80::c01e:67ff:fee0:c242 > fe80::f432:85ff:fec4:62ef: ICMP6, neighbor advertisement, tgt is fe80::c01e:67ff:fee0:c242, length 24 Results are just about the same if I re-enable BINDTODEVICE. Shall we conclude that veth is not perfect for SCTP in this kernel version? -- Hozzad simul a farkam, a macskak nyelven ez annyit tesz, hogy "Viszlat!" adam |