Commit d2ccb70a authored by Stephen Hemminger's avatar Stephen Hemminger

Merge branch 'master' into net-next

parents 343dc908 0ee9052f
...@@ -3,7 +3,7 @@ IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o ipnetns.o \ ...@@ -3,7 +3,7 @@ IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o ipnetns.o \
ipmaddr.o ipmonitor.o ipmroute.o ipprefix.o iptuntap.o iptoken.o \ ipmaddr.o ipmonitor.o ipmroute.o ipprefix.o iptuntap.o iptoken.o \
ipxfrm.o xfrm_state.o xfrm_policy.o xfrm_monitor.o \ ipxfrm.o xfrm_state.o xfrm_policy.o xfrm_monitor.o \
iplink_vlan.o link_veth.o link_gre.o iplink_can.o \ iplink_vlan.o link_veth.o link_gre.o iplink_can.o \
iplink_macvlan.o iplink_macvtap.o ipl2tp.o link_vti.o link_vti6.o \ iplink_macvlan.o ipl2tp.o link_vti.o link_vti6.o \
iplink_vxlan.o tcp_metrics.o iplink_ipoib.o ipnetconf.o link_ip6tnl.o \ iplink_vxlan.o tcp_metrics.o iplink_ipoib.o ipnetconf.o link_ip6tnl.o \
link_iptnl.o link_gre6.o iplink_bond.o iplink_bond_slave.o iplink_hsr.o \ link_iptnl.o link_gre6.o iplink_bond.o iplink_bond_slave.o iplink_hsr.o \
iplink_bridge.o iplink_bridge_slave.o ipfou.o iplink_ipvlan.o \ iplink_bridge.o iplink_bridge_slave.o ipfou.o iplink_ipvlan.o \
......
/* /*
* iplink_vlan.c VLAN device support * iplink_macvlan.c macvlan/macvtap device support
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
...@@ -20,31 +20,40 @@ ...@@ -20,31 +20,40 @@
#include "utils.h" #include "utils.h"
#include "ip_common.h" #include "ip_common.h"
static void print_explain(FILE *f) #define pfx_err(lu, ...) { \
fprintf(stderr, "%s: ", lu->id); \
fprintf(stderr, __VA_ARGS__); \
fprintf(stderr, "\n"); \
}
static void print_explain(struct link_util *lu, FILE *f)
{ {
fprintf(f, fprintf(f,
"Usage: ... macvlan mode { private | vepa | bridge | passthru }\n" "Usage: ... %s mode { private | vepa | bridge | passthru [nopromisc] }\n",
lu->id
); );
} }
static void explain(void) static void explain(struct link_util *lu)
{ {
print_explain(stderr); print_explain(lu, stderr);
} }
static int mode_arg(void) static int mode_arg(const char *arg)
{ {
fprintf(stderr, "Error: argument of \"mode\" must be \"private\", " fprintf(stderr, "Error: argument of \"mode\" must be \"private\", "
"\"vepa\", \"bridge\" or \"passthru\" \n"); "\"vepa\", \"bridge\" or \"passthru\", not \"%s\"\n", arg);
return -1; return -1;
} }
static int macvlan_parse_opt(struct link_util *lu, int argc, char **argv, static int macvlan_parse_opt(struct link_util *lu, int argc, char **argv,
struct nlmsghdr *n) struct nlmsghdr *n)
{ {
__u32 mode = 0;
__u16 flags = 0;
while (argc > 0) { while (argc > 0) {
if (matches(*argv, "mode") == 0) { if (matches(*argv, "mode") == 0) {
__u32 mode = 0;
NEXT_ARG(); NEXT_ARG();
if (strcmp(*argv, "private") == 0) if (strcmp(*argv, "private") == 0)
...@@ -56,26 +65,39 @@ static int macvlan_parse_opt(struct link_util *lu, int argc, char **argv, ...@@ -56,26 +65,39 @@ static int macvlan_parse_opt(struct link_util *lu, int argc, char **argv,
else if (strcmp(*argv, "passthru") == 0) else if (strcmp(*argv, "passthru") == 0)
mode = MACVLAN_MODE_PASSTHRU; mode = MACVLAN_MODE_PASSTHRU;
else else
return mode_arg(); return mode_arg(*argv);
} else if (matches(*argv, "nopromisc") == 0) {
addattr32(n, 1024, IFLA_MACVLAN_MODE, mode); flags |= MACVLAN_FLAG_NOPROMISC;
} else if (matches(*argv, "help") == 0) { } else if (matches(*argv, "help") == 0) {
explain(); explain(lu);
return -1; return -1;
} else { } else {
fprintf(stderr, "macvlan: unknown option \"%s\"?\n", *argv); pfx_err(lu, "unknown option \"%s\"?", *argv);
explain(); explain(lu);
return -1; return -1;
} }
argc--, argv++; argc--, argv++;
} }
if (mode)
addattr32(n, 1024, IFLA_MACVLAN_MODE, mode);
if (flags) {
if (flags & MACVLAN_FLAG_NOPROMISC &&
mode != MACVLAN_MODE_PASSTHRU) {
pfx_err(lu, "nopromisc flag only valid in passthru mode");
explain(lu);
return -1;
}
addattr16(n, 1024, IFLA_MACVLAN_FLAGS, flags);
}
return 0; return 0;
} }
static void macvlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) static void macvlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
{ {
__u32 mode; __u32 mode;
__u16 flags;
if (!tb) if (!tb)
return; return;
...@@ -91,12 +113,20 @@ static void macvlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[] ...@@ -91,12 +113,20 @@ static void macvlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]
: mode == MACVLAN_MODE_BRIDGE ? "bridge" : mode == MACVLAN_MODE_BRIDGE ? "bridge"
: mode == MACVLAN_MODE_PASSTHRU ? "passthru" : mode == MACVLAN_MODE_PASSTHRU ? "passthru"
: "unknown"); : "unknown");
if (!tb[IFLA_MACVLAN_FLAGS] ||
RTA_PAYLOAD(tb[IFLA_MACVLAN_FLAGS]) < sizeof(__u16))
return;
flags = rta_getattr_u16(tb[IFLA_MACVLAN_FLAGS]);
if (flags & MACVLAN_FLAG_NOPROMISC)
fprintf(f, "nopromisc ");
} }
static void macvlan_print_help(struct link_util *lu, int argc, char **argv, static void macvlan_print_help(struct link_util *lu, int argc, char **argv,
FILE *f) FILE *f)
{ {
print_explain(f); print_explain(lu, f);
} }
struct link_util macvlan_link_util = { struct link_util macvlan_link_util = {
...@@ -106,3 +136,11 @@ struct link_util macvlan_link_util = { ...@@ -106,3 +136,11 @@ struct link_util macvlan_link_util = {
.print_opt = macvlan_print_opt, .print_opt = macvlan_print_opt,
.print_help = macvlan_print_help, .print_help = macvlan_print_help,
}; };
struct link_util macvtap_link_util = {
.id = "macvtap",
.maxattr = IFLA_MACVLAN_MAX,
.parse_opt = macvlan_parse_opt,
.print_opt = macvlan_print_opt,
.print_help = macvlan_print_help,
};
/*
* iplink_macvtap.c macvtap device support
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <linux/if_link.h>
#include "rt_names.h"
#include "utils.h"
#include "ip_common.h"
static void print_explain(FILE *f)
{
fprintf(stderr,
"Usage: ... macvtap mode { private | vepa | bridge | passthru }\n"
);
}
static void explain(void)
{
print_explain(stderr);
}
static int mode_arg(const char *arg)
{
fprintf(stderr, "Error: argument of \"mode\" must be \"private\", "
"\"vepa\", \"bridge\" or \"passthru\", not \"%s\"\n", arg);
return -1;
}
static int macvtap_parse_opt(struct link_util *lu, int argc, char **argv,
struct nlmsghdr *n)
{
while (argc > 0) {
if (matches(*argv, "mode") == 0) {
__u32 mode = 0;
NEXT_ARG();
if (strcmp(*argv, "private") == 0)
mode = MACVLAN_MODE_PRIVATE;
else if (strcmp(*argv, "vepa") == 0)
mode = MACVLAN_MODE_VEPA;
else if (strcmp(*argv, "bridge") == 0)
mode = MACVLAN_MODE_BRIDGE;
else if (strcmp(*argv, "passthru") == 0)
mode = MACVLAN_MODE_PASSTHRU;
else
return mode_arg(*argv);
addattr32(n, 1024, IFLA_MACVLAN_MODE, mode);
} else if (matches(*argv, "help") == 0) {
explain();
return -1;
} else {
fprintf(stderr, "macvtap: unknown command \"%s\"?\n", *argv);
explain();
return -1;
}
argc--, argv++;
}
return 0;
}
static void macvtap_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
{
__u32 mode;
if (!tb)
return;
if (!tb[IFLA_MACVLAN_MODE] ||
RTA_PAYLOAD(tb[IFLA_MACVLAN_MODE]) < sizeof(__u32))
return;
mode = rta_getattr_u32(tb[IFLA_VLAN_ID]);
fprintf(f, " mode %s ",
mode == MACVLAN_MODE_PRIVATE ? "private"
: mode == MACVLAN_MODE_VEPA ? "vepa"
: mode == MACVLAN_MODE_BRIDGE ? "bridge"
: mode == MACVLAN_MODE_PASSTHRU ? "passthru"
: "unknown");
}
static void macvtap_print_help(struct link_util *lu, int argc, char **argv,
FILE *f)
{
print_explain(f);
}
struct link_util macvtap_link_util = {
.id = "macvtap",
.maxattr = IFLA_MACVLAN_MAX,
.parse_opt = macvtap_parse_opt,
.print_opt = macvtap_print_opt,
.print_help = macvtap_print_help,
};
...@@ -768,6 +768,56 @@ the following additional arguments are supported: ...@@ -768,6 +768,56 @@ the following additional arguments are supported:
.in -8 .in -8
.TP
MACVLAN and MACVTAP Type Support
For a link of type
.I MACVLAN
or
.I MACVTAP
the following additional arguments are supported:
.BI "ip link add link " DEVICE " name " NAME
.BR type " { " macvlan " | " macvtap " } "
.BR mode " { " private " | " vepa " | " bridge " | " passthru
.BR " [ " nopromisc " ] } "
.in +8
.sp
.BR type " { " macvlan " | " macvtap " } "
- specifies the link type to use.
.BR macvlan " creates just a virtual interface, while "
.BR macvtap " in addition creates a character device "
.BR /dev/tapX " to be used just like a " tuntap " device."
.B mode private
- Do not allow communication between
.B macvlan
instances on the same physical interface, even if the external switch supports
hairpin mode.
.B mode vepa
- Virtual Ethernet Port Aggregator mode. Data from one
.B macvlan
instance to the other on the same physical interface is transmitted over the
physical interface. Either the attached switch needs to support hairpin mode,
or there must be a TCP/IP router forwarding the packets in order to allow
communication. This is the default mode.
.B mode bridge
- In bridge mode, all endpoints are directly connected to each other,
communication is not redirected through the physical interface's peer.
.BR mode " " passthru " [ " nopromisc " ] "
- This mode gives more power to a single endpoint, usually in
.BR macvtap " mode. It is not allowed for more than one endpoint on the same "
physical interface. All traffic will be forwarded to this endpoint, allowing
virtio guests to change MAC address or set promiscuous mode in order to bridge
the interface or create vlan interfaces on top of it. By default, this mode
forces the underlying interface into promiscuous mode. Passing the
.BR nopromisc " flag prevents this, so the promisc flag may be controlled "
using standard tools.
.in -8
.SS ip link delete - delete virtual link .SS ip link delete - delete virtual link
.TP .TP
......
...@@ -457,7 +457,9 @@ static void user_ent_hash_build(void) ...@@ -457,7 +457,9 @@ static void user_ent_hash_build(void)
user_ent_hash_build_init = 1; user_ent_hash_build_init = 1;
strcpy(name, root); strncpy(name, root, sizeof(name)-1);
name[sizeof(name)-1] = 0;
if (strlen(name) == 0 || name[strlen(name)-1] != '/') if (strlen(name) == 0 || name[strlen(name)-1] != '/')
strcat(name, "/"); strcat(name, "/");
...@@ -481,7 +483,7 @@ static void user_ent_hash_build(void) ...@@ -481,7 +483,7 @@ static void user_ent_hash_build(void)
if (getpidcon(pid, &pid_context) != 0) if (getpidcon(pid, &pid_context) != 0)
pid_context = strdup(no_ctx); pid_context = strdup(no_ctx);
sprintf(name + nameoff, "%d/fd/", pid); snprintf(name + nameoff, sizeof(name) - nameoff, "%d/fd/", pid);
pos = strlen(name); pos = strlen(name);
if ((dir1 = opendir(name)) == NULL) { if ((dir1 = opendir(name)) == NULL) {
free(pid_context); free(pid_context);
...@@ -502,7 +504,7 @@ static void user_ent_hash_build(void) ...@@ -502,7 +504,7 @@ static void user_ent_hash_build(void)
if (sscanf(d1->d_name, "%d%c", &fd, &crap) != 1) if (sscanf(d1->d_name, "%d%c", &fd, &crap) != 1)
continue; continue;
sprintf(name+pos, "%d", fd); snprintf(name+pos, sizeof(name) - pos, "%d", fd);
link_len = readlink(name, lnk, sizeof(lnk)-1); link_len = readlink(name, lnk, sizeof(lnk)-1);
if (link_len == -1) if (link_len == -1)
...@@ -2738,7 +2740,7 @@ static int unix_show(struct filter *f) ...@@ -2738,7 +2740,7 @@ static int unix_show(struct filter *f)
struct sockstat *u, **insp; struct sockstat *u, **insp;
int flags; int flags;
if (!(u = malloc(sizeof(*u)))) if (!(u = calloc(1, sizeof(*u))))
break; break;
u->name = NULL; u->name = NULL;
u->peer_name = NULL; u->peer_name = NULL;
...@@ -3088,11 +3090,13 @@ static int netlink_show_one(struct filter *f, ...@@ -3088,11 +3090,13 @@ static int netlink_show_one(struct filter *f,
strncpy(procname, "kernel", 6); strncpy(procname, "kernel", 6);
} else if (pid > 0) { } else if (pid > 0) {
FILE *fp; FILE *fp;
sprintf(procname, "%s/%d/stat", snprintf(procname, sizeof(procname), "%s/%d/stat",
getenv("PROC_ROOT") ? : "/proc", pid); getenv("PROC_ROOT") ? : "/proc", pid);
if ((fp = fopen(procname, "r")) != NULL) { if ((fp = fopen(procname, "r")) != NULL) {
if (fscanf(fp, "%*d (%[^)])", procname) == 1) { if (fscanf(fp, "%*d (%[^)])", procname) == 1) {
sprintf(procname+strlen(procname), "/%d", pid); snprintf(procname+strlen(procname),
sizeof(procname)-strlen(procname),
"/%d", pid);
done = 1; done = 1;
} }
fclose(fp); fclose(fp);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment