Merge branch 'master' into net-next

This commit is contained in:
Stephen Hemminger 2017-08-03 16:11:22 -07:00
commit 89bcb455a1
5 changed files with 151 additions and 111 deletions

View File

@ -1012,14 +1012,95 @@ static unsigned int get_ifa_flags(struct ifaddrmsg *ifa,
ifa->ifa_flags; ifa->ifa_flags;
} }
/* Mapping from argument to address flag mask */
struct {
const char *name;
unsigned long value;
} ifa_flag_names[] = {
{ "secondary", IFA_F_SECONDARY },
{ "temporary", IFA_F_SECONDARY },
{ "nodad", IFA_F_NODAD },
{ "optimistic", IFA_F_OPTIMISTIC },
{ "dadfailed", IFA_F_DADFAILED },
{ "home", IFA_F_HOMEADDRESS },
{ "deprecated", IFA_F_DEPRECATED },
{ "tentative", IFA_F_TENTATIVE },
{ "permanent", IFA_F_PERMANENT },
{ "mngtmpaddr", IFA_F_MANAGETEMPADDR },
{ "noprefixroute", IFA_F_NOPREFIXROUTE },
{ "autojoin", IFA_F_MCAUTOJOIN },
{ "stable-privacy", IFA_F_STABLE_PRIVACY },
};
static void print_ifa_flags(FILE *fp, const struct ifaddrmsg *ifa,
unsigned int flags)
{
unsigned int i;
for (i = 0; i < ARRAY_SIZE(ifa_flag_names); i++) {
unsigned long mask = ifa_flag_names[i].value;
if (mask == IFA_F_PERMANENT) {
if (!(flags & mask))
fprintf(fp, "dynamic ");
} else if (flags & mask) {
if (mask == IFA_F_SECONDARY &&
ifa->ifa_family == AF_INET6)
fprintf(fp, "temporary ");
else
fprintf(fp, "%s ", ifa_flag_names[i].name);
}
flags &= ~mask;
}
if (flags)
fprintf(fp, "flags %02x ", flags);
}
static int get_filter(const char *arg)
{
unsigned int i;
/* Special cases */
if (strcmp(arg, "dynamic") == 0) {
filter.flags &= ~IFA_F_PERMANENT;
filter.flagmask |= IFA_F_PERMANENT;
} else if (strcmp(arg, "primary") == 0) {
filter.flags &= ~IFA_F_SECONDARY;
filter.flagmask |= IFA_F_SECONDARY;
} else if (*arg == '-') {
for (i = 0; i < ARRAY_SIZE(ifa_flag_names); i++) {
if (strcmp(arg + 1, ifa_flag_names[i].name))
continue;
filter.flags &= ifa_flag_names[i].value;
filter.flagmask |= ifa_flag_names[i].value;
return 0;
}
return -1;
} else {
for (i = 0; i < ARRAY_SIZE(ifa_flag_names); i++) {
if (strcmp(arg, ifa_flag_names[i].name))
continue;
filter.flags |= ifa_flag_names[i].value;
filter.flagmask |= ifa_flag_names[i].value;
return 0;
}
return -1;
}
return 0;
}
int print_addrinfo(const struct sockaddr_nl *who, struct nlmsghdr *n, int print_addrinfo(const struct sockaddr_nl *who, struct nlmsghdr *n,
void *arg) void *arg)
{ {
FILE *fp = arg; FILE *fp = arg;
struct ifaddrmsg *ifa = NLMSG_DATA(n); struct ifaddrmsg *ifa = NLMSG_DATA(n);
int len = n->nlmsg_len; int len = n->nlmsg_len;
int deprecated = 0;
/* Use local copy of ifa_flags to not interfere with filtering code */
unsigned int ifa_flags; unsigned int ifa_flags;
struct rtattr *rta_tb[IFA_MAX+1]; struct rtattr *rta_tb[IFA_MAX+1];
@ -1144,52 +1225,9 @@ int print_addrinfo(const struct sockaddr_nl *who, struct nlmsghdr *n,
rta_tb[IFA_ANYCAST])); rta_tb[IFA_ANYCAST]));
} }
fprintf(fp, "scope %s ", rtnl_rtscope_n2a(ifa->ifa_scope, b1, sizeof(b1))); fprintf(fp, "scope %s ", rtnl_rtscope_n2a(ifa->ifa_scope, b1, sizeof(b1)));
if (ifa_flags & IFA_F_SECONDARY) {
ifa_flags &= ~IFA_F_SECONDARY; print_ifa_flags(fp, ifa, ifa_flags);
if (ifa->ifa_family == AF_INET6)
fprintf(fp, "temporary ");
else
fprintf(fp, "secondary ");
}
if (ifa_flags & IFA_F_TENTATIVE) {
ifa_flags &= ~IFA_F_TENTATIVE;
fprintf(fp, "tentative ");
}
if (ifa_flags & IFA_F_DEPRECATED) {
ifa_flags &= ~IFA_F_DEPRECATED;
deprecated = 1;
fprintf(fp, "deprecated ");
}
if (ifa_flags & IFA_F_HOMEADDRESS) {
ifa_flags &= ~IFA_F_HOMEADDRESS;
fprintf(fp, "home ");
}
if (ifa_flags & IFA_F_NODAD) {
ifa_flags &= ~IFA_F_NODAD;
fprintf(fp, "nodad ");
}
if (ifa_flags & IFA_F_MANAGETEMPADDR) {
ifa_flags &= ~IFA_F_MANAGETEMPADDR;
fprintf(fp, "mngtmpaddr ");
}
if (ifa_flags & IFA_F_NOPREFIXROUTE) {
ifa_flags &= ~IFA_F_NOPREFIXROUTE;
fprintf(fp, "noprefixroute ");
}
if (ifa_flags & IFA_F_MCAUTOJOIN) {
ifa_flags &= ~IFA_F_MCAUTOJOIN;
fprintf(fp, "autojoin ");
}
if (!(ifa_flags & IFA_F_PERMANENT))
fprintf(fp, "dynamic ");
else
ifa_flags &= ~IFA_F_PERMANENT;
if (ifa_flags & IFA_F_DADFAILED) {
ifa_flags &= ~IFA_F_DADFAILED;
fprintf(fp, "dadfailed ");
}
if (ifa_flags)
fprintf(fp, "flags %02x ", ifa_flags);
if (rta_tb[IFA_LABEL]) if (rta_tb[IFA_LABEL])
fprintf(fp, "%s", rta_getattr_str(rta_tb[IFA_LABEL])); fprintf(fp, "%s", rta_getattr_str(rta_tb[IFA_LABEL]));
if (rta_tb[IFA_CACHEINFO]) { if (rta_tb[IFA_CACHEINFO]) {
@ -1205,7 +1243,7 @@ int print_addrinfo(const struct sockaddr_nl *who, struct nlmsghdr *n,
if (ci->ifa_prefered == INFINITY_LIFE_TIME) if (ci->ifa_prefered == INFINITY_LIFE_TIME)
fprintf(fp, "forever"); fprintf(fp, "forever");
else { else {
if (deprecated) if (ifa_flags & IFA_F_DEPRECATED)
fprintf(fp, "%dsec", ci->ifa_prefered); fprintf(fp, "%dsec", ci->ifa_prefered);
else else
fprintf(fp, "%usec", ci->ifa_prefered); fprintf(fp, "%usec", ci->ifa_prefered);
@ -1608,52 +1646,8 @@ static int ipaddr_list_flush_or_save(int argc, char **argv, int action)
filter.scope = scope; filter.scope = scope;
} else if (strcmp(*argv, "up") == 0) { } else if (strcmp(*argv, "up") == 0) {
filter.up = 1; filter.up = 1;
} else if (strcmp(*argv, "dynamic") == 0) { } else if (get_filter(*argv) == 0) {
filter.flags &= ~IFA_F_PERMANENT;
filter.flagmask |= IFA_F_PERMANENT;
} else if (strcmp(*argv, "permanent") == 0) {
filter.flags |= IFA_F_PERMANENT;
filter.flagmask |= IFA_F_PERMANENT;
} else if (strcmp(*argv, "secondary") == 0 ||
strcmp(*argv, "temporary") == 0) {
filter.flags |= IFA_F_SECONDARY;
filter.flagmask |= IFA_F_SECONDARY;
} else if (strcmp(*argv, "primary") == 0) {
filter.flags &= ~IFA_F_SECONDARY;
filter.flagmask |= IFA_F_SECONDARY;
} else if (strcmp(*argv, "tentative") == 0) {
filter.flags |= IFA_F_TENTATIVE;
filter.flagmask |= IFA_F_TENTATIVE;
} else if (strcmp(*argv, "-tentative") == 0) {
filter.flags &= ~IFA_F_TENTATIVE;
filter.flagmask |= IFA_F_TENTATIVE;
} else if (strcmp(*argv, "deprecated") == 0) {
filter.flags |= IFA_F_DEPRECATED;
filter.flagmask |= IFA_F_DEPRECATED;
} else if (strcmp(*argv, "-deprecated") == 0) {
filter.flags &= ~IFA_F_DEPRECATED;
filter.flagmask |= IFA_F_DEPRECATED;
} else if (strcmp(*argv, "home") == 0) {
filter.flags |= IFA_F_HOMEADDRESS;
filter.flagmask |= IFA_F_HOMEADDRESS;
} else if (strcmp(*argv, "nodad") == 0) {
filter.flags |= IFA_F_NODAD;
filter.flagmask |= IFA_F_NODAD;
} else if (strcmp(*argv, "mngtmpaddr") == 0) {
filter.flags |= IFA_F_MANAGETEMPADDR;
filter.flagmask |= IFA_F_MANAGETEMPADDR;
} else if (strcmp(*argv, "noprefixroute") == 0) {
filter.flags |= IFA_F_NOPREFIXROUTE;
filter.flagmask |= IFA_F_NOPREFIXROUTE;
} else if (strcmp(*argv, "autojoin") == 0) {
filter.flags |= IFA_F_MCAUTOJOIN;
filter.flagmask |= IFA_F_MCAUTOJOIN;
} else if (strcmp(*argv, "dadfailed") == 0) {
filter.flags |= IFA_F_DADFAILED;
filter.flagmask |= IFA_F_DADFAILED;
} else if (strcmp(*argv, "-dadfailed") == 0) {
filter.flags &= ~IFA_F_DADFAILED;
filter.flagmask |= IFA_F_DADFAILED;
} else if (strcmp(*argv, "label") == 0) { } else if (strcmp(*argv, "label") == 0) {
NEXT_ARG(); NEXT_ARG();
filter.label = *argv; filter.label = *argv;

View File

@ -208,11 +208,11 @@ static int bpf_parse_string(char *arg, bool from_file, __u16 *bpf_len,
if (from_file) { if (from_file) {
size_t tmp_len, op_len = sizeof("65535 255 255 4294967295,"); size_t tmp_len, op_len = sizeof("65535 255 255 4294967295,");
char *tmp_string, *last; char *tmp_string, *pos, c, c_prev = ' ';
FILE *fp; FILE *fp;
tmp_len = sizeof("4096,") + BPF_MAXINSNS * op_len; tmp_len = sizeof("4096,") + BPF_MAXINSNS * op_len;
tmp_string = calloc(1, tmp_len); tmp_string = pos = calloc(1, tmp_len);
if (tmp_string == NULL) if (tmp_string == NULL)
return -ENOMEM; return -ENOMEM;
@ -223,17 +223,33 @@ static int bpf_parse_string(char *arg, bool from_file, __u16 *bpf_len,
return -ENOENT; return -ENOENT;
} }
if (!fgets(tmp_string, tmp_len, fp)) { while ((c = fgetc(fp)) != EOF) {
switch (c) {
case '\n':
if (c_prev != ',')
*(pos++) = ',';
break;
case ' ':
case '\t':
if (c_prev != ' ')
*(pos++) = c;
break;
default:
*(pos++) = c;
}
if (pos - tmp_string == tmp_len)
break;
c_prev = c;
}
if (!feof(fp)) {
free(tmp_string); free(tmp_string);
fclose(fp); fclose(fp);
return -EIO; return -E2BIG;
} }
fclose(fp); fclose(fp);
*pos = 0;
last = &tmp_string[strlen(tmp_string) - 1];
if (*last == '\n')
*last = 0;
*need_release = true; *need_release = true;
*bpf_string = tmp_string; *bpf_string = tmp_string;

View File

@ -616,12 +616,19 @@ done:
return err; return err;
} }
static const char *family_name_verbose(int family)
{
if (family == AF_UNSPEC)
return "any valid";
return family_name(family);
}
int get_addr(inet_prefix *dst, const char *arg, int family) int get_addr(inet_prefix *dst, const char *arg, int family)
{ {
if (get_addr_1(dst, arg, family)) { if (get_addr_1(dst, arg, family)) {
fprintf(stderr, fprintf(stderr,
"Error: %s address is expected rather than \"%s\".\n", "Error: %s address is expected rather than \"%s\".\n",
family_name(dst->family), arg); family_name_verbose(family), arg);
exit(1); exit(1);
} }
return 0; return 0;
@ -639,7 +646,7 @@ int get_prefix(inet_prefix *dst, char *arg, int family)
if (get_prefix_1(dst, arg, family)) { if (get_prefix_1(dst, arg, family)) {
fprintf(stderr, fprintf(stderr,
"Error: %s prefix is expected rather than \"%s\".\n", "Error: %s prefix is expected rather than \"%s\".\n",
family_name(dst->family), arg); family_name_verbose(family), arg);
exit(1); exit(1);
} }
return 0; return 0;

View File

@ -6,15 +6,37 @@ simple - basic example action
.in +8 .in +8
.ti -8 .ti -8
.BR tc " ... " "action simple" .BR tc " ... " "action simple"
.I STRING [
.BI sdata " STRING"
] [
.BI index " INDEX"
] [
.I CONTROL
]
.ti -8
.IR CONTROL " := {"
.BR reclassify " | " pipe " | " drop " | " continue " | " ok " }"
.SH DESCRIPTION .SH DESCRIPTION
This is a pedagogical example rather than an actually useful action. Upon every access, it prints the given This is a pedagogical example rather than an actually useful action. Upon every access, it prints the given
.I STRING .I STRING
which may be of arbitrary length. which may be of arbitrary length.
.SH OPTIONS .SH OPTIONS
.TP .TP
.I STRING .BI sdata " STRING"
The actual string to print. The actual string to print.
.TP
.BI index " INDEX"
Optional action index value.
.TP
.I CONTROL
Indicate how
.B tc
should proceed after executing the action. For a description of the possible
.I CONTROL
values, see
.BR tc-actions (8).
.SH EXAMPLES .SH EXAMPLES
The following example makes the kernel yell "Incoming ICMP!" every time it sees The following example makes the kernel yell "Incoming ICMP!" every time it sees
an incoming ICMP on eth0. Steps are: an incoming ICMP on eth0. Steps are:
@ -36,7 +58,7 @@ display stats again and observe increment by 1
.EX .EX
hadi@noma1:$ tc qdisc add dev eth0 ingress hadi@noma1:$ tc qdisc add dev eth0 ingress
hadi@noma1:$tc filter add dev eth0 parent ffff: protocol ip prio 5 \\ hadi@noma1:$tc filter add dev eth0 parent ffff: protocol ip prio 5 \\
u32 match ip protocol 1 0xff flowid 1:1 action simple "Incoming ICMP" u32 match ip protocol 1 0xff flowid 1:1 action simple sdata "Incoming ICMP"
hadi@noma1:$ sudo tc -s filter ls dev eth0 parent ffff: hadi@noma1:$ sudo tc -s filter ls dev eth0 parent ffff:
filter protocol ip pref 5 u32 filter protocol ip pref 5 u32
@ -74,3 +96,4 @@ display stats again and observe increment by 1
.EE .EE
.SH SEE ALSO .SH SEE ALSO
.BR tc (8) .BR tc (8)
.BR tc-actions (8)

View File

@ -81,10 +81,10 @@
#endif #endif
static void explain(void) static void explain(void)
{ {
fprintf(stderr, "Usage:... simple [sdata STRING] [CONTROL] [index INDEX]\n"); fprintf(stderr, "Usage:... simple [sdata STRING] [index INDEX] [CONTROL]\n");
fprintf(stderr, "\tSTRING being an arbitrary string\n" fprintf(stderr, "\tSTRING being an arbitrary string\n"
"\tCONTROL := reclassify|pipe|drop|continue|ok\n" "\tINDEX := optional index value used\n"
"\tINDEX := optional index value used\n"); "\tCONTROL := reclassify|pipe|drop|continue|ok\n");
} }
static void usage(void) static void usage(void)