Commit 39afc4b0 authored by Stephen Hemminger's avatar Stephen Hemminger

Merge branch 'master' into net-next

parents bc9fb257 bbac6c63
......@@ -27,7 +27,7 @@
#include "rt_names.h"
#include "utils.h"
static unsigned int filter_index;
static unsigned int filter_index, filter_vlan;
static void usage(void)
{
......@@ -35,7 +35,7 @@ static void usage(void)
" [ self ] [ master ] [ use ] [ router ]\n"
" [ local | static | dynamic ] [ dst IPADDR ] [ vlan VID ]\n"
" [ port PORT] [ vni VNI ] [ via DEV ]\n");
fprintf(stderr, " bridge fdb [ show [ br BRDEV ] [ brport DEV ] ]\n");
fprintf(stderr, " bridge fdb [ show [ br BRDEV ] [ brport DEV ] [ vlan VID ] ]\n");
exit(-1);
}
......@@ -65,6 +65,7 @@ int print_fdb(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
struct ndmsg *r = NLMSG_DATA(n);
int len = n->nlmsg_len;
struct rtattr *tb[NDA_MAX+1];
__u16 vid = 0;
if (n->nlmsg_type != RTM_NEWNEIGH && n->nlmsg_type != RTM_DELNEIGH) {
fprintf(stderr, "Not RTM_NEWNEIGH: %08x %08x %08x\n",
......@@ -88,6 +89,12 @@ int print_fdb(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
parse_rtattr(tb, NDA_MAX, NDA_RTA(r),
n->nlmsg_len - NLMSG_LENGTH(sizeof(*r)));
if (tb[NDA_VLAN])
vid = rta_getattr_u16(tb[NDA_VLAN]);
if (filter_vlan && filter_vlan != vid)
return 0;
if (n->nlmsg_type == RTM_DELNEIGH)
fprintf(fp, "Deleted ");
......@@ -115,11 +122,8 @@ int print_fdb(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
RTA_DATA(tb[NDA_DST])));
}
if (tb[NDA_VLAN]) {
__u16 vid = rta_getattr_u16(tb[NDA_VLAN]);
if (vid)
fprintf(fp, "vlan %hu ", vid);
}
if (tb[NDA_PORT])
fprintf(fp, "port %d ", ntohs(rta_getattr_u16(tb[NDA_PORT])));
......@@ -190,6 +194,11 @@ static int fdb_show(int argc, char **argv)
} else if (strcmp(*argv, "br") == 0) {
NEXT_ARG();
br = *argv;
} else if (strcmp(*argv, "vlan") == 0) {
NEXT_ARG();
if (filter_vlan)
duparg("vlan", *argv);
filter_vlan = atoi(*argv);
} else {
if (matches(*argv, "help") == 0)
usage();
......
......@@ -24,12 +24,12 @@
((struct rtattr *)(((char *)(r)) + NLMSG_ALIGN(sizeof(struct br_port_msg))))
#endif
static unsigned int filter_index;
static unsigned int filter_index, filter_vlan;
static void usage(void)
{
fprintf(stderr, "Usage: bridge mdb { add | del } dev DEV port PORT grp GROUP [permanent | temp] [vid VID]\n");
fprintf(stderr, " bridge mdb {show} [ dev DEV ]\n");
fprintf(stderr, " bridge mdb {show} [ dev DEV ] [ vid VID ]\n");
exit(-1);
}
......@@ -92,6 +92,8 @@ static void print_mdb_entry(FILE *f, int ifindex, struct br_mdb_entry *e,
const void *src;
int af;
if (filter_vlan && e->vid != filter_vlan)
return;
af = e->addr.proto == htons(ETH_P_IP) ? AF_INET : AF_INET6;
src = af == AF_INET ? (const void *)&e->addr.u.ip4 :
(const void *)&e->addr.u.ip6;
......@@ -195,6 +197,11 @@ static int mdb_show(int argc, char **argv)
if (filter_dev)
duparg("dev", *argv);
filter_dev = *argv;
} else if (strcmp(*argv, "vid") == 0) {
NEXT_ARG();
if (filter_vlan)
duparg("vid", *argv);
filter_vlan = atoi(*argv);
}
argc--; argv++;
}
......
......@@ -13,13 +13,13 @@
#include "br_common.h"
#include "utils.h"
static unsigned int filter_index;
static unsigned int filter_index, filter_vlan;
static void usage(void)
{
fprintf(stderr, "Usage: bridge vlan { add | del } vid VLAN_ID dev DEV [ pvid] [ untagged ]\n");
fprintf(stderr, " [ self ] [ master ]\n");
fprintf(stderr, " bridge vlan { show } [ dev DEV ]\n");
fprintf(stderr, " bridge vlan { show } [ dev DEV ] [ vid VLAN_ID ]\n");
exit(-1);
}
......@@ -138,6 +138,26 @@ static int vlan_modify(int cmd, int argc, char **argv)
return 0;
}
/* In order to use this function for both filtering and non-filtering cases
* we need to make it a tristate:
* return -1 - if filtering we've gone over so don't continue
* return 0 - skip entry and continue (applies to range start or to entries
* which are less than filter_vlan)
* return 1 - print the entry and continue
*/
static int filter_vlan_check(struct bridge_vlan_info *vinfo)
{
/* if we're filtering we should stop on the first greater entry */
if (filter_vlan && vinfo->vid > filter_vlan &&
!(vinfo->flags & BRIDGE_VLAN_INFO_RANGE_END))
return -1;
if ((vinfo->flags & BRIDGE_VLAN_INFO_RANGE_BEGIN) ||
vinfo->vid < filter_vlan)
return 0;
return 1;
}
static int print_vlan(const struct sockaddr_nl *who,
struct nlmsghdr *n,
void *arg)
......@@ -169,26 +189,40 @@ static int print_vlan(const struct sockaddr_nl *who,
/* if AF_SPEC isn't there, vlan table is not preset for this port */
if (!tb[IFLA_AF_SPEC]) {
fprintf(fp, "%s\tNone\n", ll_index_to_name(ifm->ifi_index));
if (!filter_vlan)
fprintf(fp, "%s\tNone\n",
ll_index_to_name(ifm->ifi_index));
return 0;
} else {
struct rtattr *i, *list = tb[IFLA_AF_SPEC];
int rem = RTA_PAYLOAD(list);
__u16 last_vid_start = 0;
fprintf(fp, "%s", ll_index_to_name(ifm->ifi_index));
if (!filter_vlan)
fprintf(fp, "%s", ll_index_to_name(ifm->ifi_index));
for (i = RTA_DATA(list); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) {
struct bridge_vlan_info *vinfo;
int vcheck_ret;
if (i->rta_type != IFLA_BRIDGE_VLAN_INFO)
continue;
vinfo = RTA_DATA(i);
if (vinfo->flags & BRIDGE_VLAN_INFO_RANGE_END)
fprintf(fp, "-%hu", vinfo->vid);
else
fprintf(fp, "\t %hu", vinfo->vid);
if (vinfo->flags & BRIDGE_VLAN_INFO_RANGE_BEGIN)
if (!(vinfo->flags & BRIDGE_VLAN_INFO_RANGE_END))
last_vid_start = vinfo->vid;
vcheck_ret = filter_vlan_check(vinfo);
if (vcheck_ret == -1)
break;
else if (vcheck_ret == 0)
continue;
if (filter_vlan)
fprintf(fp, "%s",
ll_index_to_name(ifm->ifi_index));
fprintf(fp, "\t %hu", last_vid_start);
if (last_vid_start != vinfo->vid)
fprintf(fp, "-%hu", vinfo->vid);
if (vinfo->flags & BRIDGE_VLAN_INFO_PVID)
fprintf(fp, " PVID");
if (vinfo->flags & BRIDGE_VLAN_INFO_UNTAGGED)
......@@ -196,7 +230,8 @@ static int print_vlan(const struct sockaddr_nl *who,
fprintf(fp, "\n");
}
}
fprintf(fp, "\n");
if (!filter_vlan)
fprintf(fp, "\n");
fflush(fp);
return 0;
}
......@@ -211,6 +246,11 @@ static int vlan_show(int argc, char **argv)
if (filter_dev)
duparg("dev", *argv);
filter_dev = *argv;
} else if (strcmp(*argv, "vid") == 0) {
NEXT_ARG();
if (filter_vlan)
duparg("vid", *argv);
filter_vlan = atoi(*argv);
}
argc--; argv++;
}
......
......@@ -6,7 +6,14 @@
*/
#define JMP_MAP_ID 0xabccba
BPF_PROG_ARRAY(jmp_tc, JMP_MAP_ID, PIN_OBJECT_NS, 1);
struct bpf_elf_map __section_maps jmp_tc = {
.type = BPF_MAP_TYPE_PROG_ARRAY,
.id = JMP_MAP_ID,
.size_key = sizeof(uint32_t),
.size_value = sizeof(uint32_t),
.pinning = PIN_OBJECT_NS,
.max_elem = 1,
};
__section_tail(JMP_MAP_ID, 0)
int cls_loop(struct __sk_buff *skb)
......
......@@ -33,7 +33,13 @@
* [...]
*/
BPF_PROG_ARRAY(jmp_tc, 0, PIN_GLOBAL_NS, 1);
struct bpf_elf_map __section_maps jmp_tc = {
.type = BPF_MAP_TYPE_PROG_ARRAY,
.size_key = sizeof(uint32_t),
.size_value = sizeof(uint32_t),
.pinning = PIN_GLOBAL_NS,
.max_elem = 1,
};
__section("aaa")
int cls_aaa(struct __sk_buff *skb)
......
......@@ -192,6 +192,7 @@ struct bpf_elf_map __section("maps") map_proto = {
.size_key = sizeof(uint8_t),
.size_value = sizeof(struct count_tuple),
.max_elem = 256,
.flags = BPF_F_NO_PREALLOC,
};
struct bpf_elf_map __section("maps") map_queue = {
......@@ -200,6 +201,7 @@ struct bpf_elf_map __section("maps") map_queue = {
.size_key = sizeof(uint32_t),
.size_value = sizeof(struct count_queue),
.max_elem = 1024,
.flags = BPF_F_NO_PREALLOC,
};
struct bpf_elf_map __section("maps") map_drops = {
......
......@@ -18,7 +18,13 @@
* instance is being created.
*/
BPF_ARRAY4(map_sh, 0, PIN_OBJECT_NS, 1); /* or PIN_GLOBAL_NS, or PIN_NONE */
struct bpf_elf_map __section_maps map_sh = {
.type = BPF_MAP_TYPE_ARRAY,
.size_key = sizeof(uint32_t),
.size_value = sizeof(uint32_t),
.pinning = PIN_OBJECT_NS, /* or PIN_GLOBAL_NS, or PIN_NONE */
.max_elem = 1,
};
__section("egress")
int emain(struct __sk_buff *skb)
......
......@@ -26,10 +26,31 @@
* classifier behaviour.
*/
BPF_PROG_ARRAY(jmp_tc, FOO, PIN_OBJECT_NS, MAX_JMP_SIZE);
BPF_PROG_ARRAY(jmp_ex, BAR, PIN_OBJECT_NS, 1);
BPF_ARRAY4(map_sh, 0, PIN_OBJECT_NS, 1);
struct bpf_elf_map __section_maps jmp_tc = {
.type = BPF_MAP_TYPE_PROG_ARRAY,
.id = FOO,
.size_key = sizeof(uint32_t),
.size_value = sizeof(uint32_t),
.pinning = PIN_OBJECT_NS,
.max_elem = MAX_JMP_SIZE,
};
struct bpf_elf_map __section_maps jmp_ex = {
.type = BPF_MAP_TYPE_PROG_ARRAY,
.id = BAR,
.size_key = sizeof(uint32_t),
.size_value = sizeof(uint32_t),
.pinning = PIN_OBJECT_NS,
.max_elem = 1,
};
struct bpf_elf_map __section_maps map_sh = {
.type = BPF_MAP_TYPE_ARRAY,
.size_key = sizeof(uint32_t),
.size_value = sizeof(uint32_t),
.pinning = PIN_OBJECT_NS,
.max_elem = 1,
};
__section_tail(FOO, ENTRY_0)
int cls_case1(struct __sk_buff *skb)
......
......@@ -99,51 +99,6 @@
char ____license[] __section_license = NAME
#endif
#ifndef __BPF_MAP
# define __BPF_MAP(NAME, TYPE, ID, SIZE_KEY, SIZE_VALUE, PIN, MAX_ELEM) \
struct bpf_elf_map __section_maps NAME = { \
.type = (TYPE), \
.id = (ID), \
.size_key = (SIZE_KEY), \
.size_value = (SIZE_VALUE), \
.pinning = (PIN), \
.max_elem = (MAX_ELEM), \
}
#endif
#ifndef BPF_HASH
# define BPF_HASH(NAME, ID, SIZE_KEY, SIZE_VALUE, PIN, MAX_ELEM) \
__BPF_MAP(NAME, BPF_MAP_TYPE_HASH, ID, SIZE_KEY, SIZE_VALUE, \
PIN, MAX_ELEM)
#endif
#ifndef BPF_ARRAY
# define BPF_ARRAY(NAME, ID, SIZE_VALUE, PIN, MAX_ELEM) \
__BPF_MAP(NAME, BPF_MAP_TYPE_ARRAY, ID, sizeof(uint32_t), \
SIZE_VALUE, PIN, MAX_ELEM)
#endif
#ifndef BPF_ARRAY2
# define BPF_ARRAY2(NAME, ID, PIN, MAX_ELEM) \
BPF_ARRAY(NAME, ID, sizeof(uint16_t), PIN, MAX_ELEM)
#endif
#ifndef BPF_ARRAY4
# define BPF_ARRAY4(NAME, ID, PIN, MAX_ELEM) \
BPF_ARRAY(NAME, ID, sizeof(uint32_t), PIN, MAX_ELEM)
#endif
#ifndef BPF_ARRAY8
# define BPF_ARRAY8(NAME, ID, PIN, MAX_ELEM) \
BPF_ARRAY(NAME, ID, sizeof(uint64_t), PIN, MAX_ELEM)
#endif
#ifndef BPF_PROG_ARRAY
# define BPF_PROG_ARRAY(NAME, ID, PIN, MAX_ELEM) \
__BPF_MAP(NAME, BPF_MAP_TYPE_PROG_ARRAY, ID, sizeof(uint32_t), \
sizeof(uint32_t), PIN, MAX_ELEM)
#endif
/** Classifier helper */
#ifndef BPF_H_DEFAULT
......@@ -212,6 +167,8 @@ static int BPF_FUNC(l3_csum_replace, struct __sk_buff *skb, uint32_t off,
uint32_t from, uint32_t to, uint32_t flags);
static int BPF_FUNC(l4_csum_replace, struct __sk_buff *skb, uint32_t off,
uint32_t from, uint32_t to, uint32_t flags);
static int BPF_FUNC(csum_diff, const void *from, uint32_t from_size,
const void *to, uint32_t to_size, uint32_t seed);
/* Packet vlan encap/decap */
static int BPF_FUNC(skb_vlan_push, struct __sk_buff *skb, uint16_t proto,
......@@ -225,6 +182,11 @@ static int BPF_FUNC(skb_set_tunnel_key, struct __sk_buff *skb,
const struct bpf_tunnel_key *from, uint32_t size,
uint32_t flags);
static int BPF_FUNC(skb_get_tunnel_opt, struct __sk_buff *skb,
void *to, uint32_t size);
static int BPF_FUNC(skb_set_tunnel_opt, struct __sk_buff *skb,
const void *from, uint32_t size);
/** LLVM built-ins, mem*() routines work for constant size */
#ifndef lock_xadd
......
......@@ -32,6 +32,7 @@ struct bpf_elf_map {
__u32 size_key;
__u32 size_value;
__u32 max_elem;
__u32 flags;
__u32 id;
__u32 pinning;
};
......
......@@ -326,7 +326,7 @@ static void print_vfinfo(FILE *fp, struct rtattr *vfinfo)
* this kernel.
*/
tmp = (struct rtattr *)((char *)vf[IFLA_VF_TX_RATE] +
vf[IFLA_VF_TX_RATE]->rta_len);
vf[IFLA_VF_TX_RATE]->rta_len);
if (tmp->rta_type != IFLA_VF_SPOOFCHK)
vf_spoofchk = NULL;
......@@ -338,7 +338,7 @@ static void print_vfinfo(FILE *fp, struct rtattr *vfinfo)
* this kernel.
*/
tmp = (struct rtattr *)((char *)vf[IFLA_VF_SPOOFCHK] +
vf[IFLA_VF_SPOOFCHK]->rta_len);
vf[IFLA_VF_SPOOFCHK]->rta_len);
if (tmp->rta_type != IFLA_VF_LINK_STATE)
vf_linkstate = NULL;
......@@ -349,7 +349,7 @@ static void print_vfinfo(FILE *fp, struct rtattr *vfinfo)
fprintf(fp, "%s vf %d MAC %s", _SL_, vf_mac->vf,
ll_addr_n2a((unsigned char *)&vf_mac->mac,
ETH_ALEN, 0, b1, sizeof(b1)));
ETH_ALEN, 0, b1, sizeof(b1)));
if (vf_vlan->vlan)
fprintf(fp, ", vlan %d", vf_vlan->vlan);
if (vf_vlan->qos)
......@@ -380,6 +380,13 @@ static void print_vfinfo(FILE *fp, struct rtattr *vfinfo)
else
fprintf(fp, ", link-state disable");
}
if (vf[IFLA_VF_TRUST]) {
struct ifla_vf_trust *vf_trust = RTA_DATA(vf[IFLA_VF_TRUST]);
if (vf_trust->setting != -1)
fprintf(fp, ", trust %s",
vf_trust->setting ? "on" : "off");
}
if (vf[IFLA_VF_STATS] && show_stats)
print_vf_stats64(fp, vf[IFLA_VF_STATS]);
}
......@@ -782,7 +789,7 @@ int print_linkinfo(const struct sockaddr_nl *who,
fprintf(fp, "%d: ", ifi->ifi_index);
color_fprintf(fp, COLOR_IFNAME, "%s",
tb[IFLA_IFNAME] ? rta_getattr_str(tb[IFLA_IFNAME]) : "<nil>");
tb[IFLA_IFNAME] ? rta_getattr_str(tb[IFLA_IFNAME]) : "<nil>");
if (tb[IFLA_LINK]) {
SPRINT_BUF(b1);
......@@ -813,22 +820,6 @@ int print_linkinfo(const struct sockaddr_nl *who,
fprintf(fp, "master %s ", ll_idx_n2a(*(int *)RTA_DATA(tb[IFLA_MASTER]), b1));
}
if (tb[IFLA_PHYS_PORT_ID]) {
SPRINT_BUF(b1);
fprintf(fp, "portid %s ",
hexstring_n2a(RTA_DATA(tb[IFLA_PHYS_PORT_ID]),
RTA_PAYLOAD(tb[IFLA_PHYS_PORT_ID]),
b1, sizeof(b1)));
}
if (tb[IFLA_PHYS_SWITCH_ID]) {
SPRINT_BUF(b1);
fprintf(fp, "switchid %s ",
hexstring_n2a(RTA_DATA(tb[IFLA_PHYS_SWITCH_ID]),
RTA_PAYLOAD(tb[IFLA_PHYS_SWITCH_ID]),
b1, sizeof(b1)));
}
if (tb[IFLA_OPERSTATE])
print_operstate(fp, rta_getattr_u8(tb[IFLA_OPERSTATE]));
......@@ -852,10 +843,10 @@ int print_linkinfo(const struct sockaddr_nl *who,
if (tb[IFLA_ADDRESS]) {
color_fprintf(fp, COLOR_MAC, "%s",
ll_addr_n2a(RTA_DATA(tb[IFLA_ADDRESS]),
RTA_PAYLOAD(tb[IFLA_ADDRESS]),
ifi->ifi_type,
b1, sizeof(b1)));
ll_addr_n2a(RTA_DATA(tb[IFLA_ADDRESS]),
RTA_PAYLOAD(tb[IFLA_ADDRESS]),
ifi->ifi_type,
b1, sizeof(b1)));
}
if (tb[IFLA_BROADCAST]) {
if (ifi->ifi_flags&IFF_POINTOPOINT)
......@@ -863,10 +854,10 @@ int print_linkinfo(const struct sockaddr_nl *who,
else
fprintf(fp, " brd ");
color_fprintf(fp, COLOR_MAC, "%s",
ll_addr_n2a(RTA_DATA(tb[IFLA_BROADCAST]),
RTA_PAYLOAD(tb[IFLA_BROADCAST]),
ifi->ifi_type,
b1, sizeof(b1)));
ll_addr_n2a(RTA_DATA(tb[IFLA_BROADCAST]),
RTA_PAYLOAD(tb[IFLA_BROADCAST]),
ifi->ifi_type,
b1, sizeof(b1)));
}
}
......@@ -884,15 +875,46 @@ int print_linkinfo(const struct sockaddr_nl *who,
fprintf(fp, " protodown on ");
}
if (tb[IFLA_PROMISCUITY] && show_details)
fprintf(fp, " promiscuity %u ",
*(int *)RTA_DATA(tb[IFLA_PROMISCUITY]));
if (show_details) {
if (tb[IFLA_PROMISCUITY])
fprintf(fp, " promiscuity %u ",
*(int *)RTA_DATA(tb[IFLA_PROMISCUITY]));
if (tb[IFLA_LINKINFO])
print_linktype(fp, tb[IFLA_LINKINFO]);
if (do_link && tb[IFLA_AF_SPEC])
print_af_spec(fp, tb[IFLA_AF_SPEC]);
if (tb[IFLA_NUM_TX_QUEUES])
fprintf(fp, "numtxqueues %u ",
rta_getattr_u32(tb[IFLA_NUM_TX_QUEUES]));
if (tb[IFLA_NUM_RX_QUEUES])
fprintf(fp, "numrxqueues %u ",
rta_getattr_u32(tb[IFLA_NUM_RX_QUEUES]));
if (tb[IFLA_LINKINFO] && show_details)
print_linktype(fp, tb[IFLA_LINKINFO]);
if (tb[IFLA_PHYS_PORT_NAME])
fprintf(fp, "portname %s ",
rta_getattr_str(tb[IFLA_PHYS_PORT_NAME]));
if (tb[IFLA_PHYS_PORT_ID]) {
SPRINT_BUF(b1);
fprintf(fp, "portid %s ",
hexstring_n2a(RTA_DATA(tb[IFLA_PHYS_PORT_ID]),
RTA_PAYLOAD(tb[IFLA_PHYS_PORT_ID]),
b1, sizeof(b1)));
}
if (tb[IFLA_PHYS_SWITCH_ID]) {
SPRINT_BUF(b1);
fprintf(fp, "switchid %s ",
hexstring_n2a(RTA_DATA(tb[IFLA_PHYS_SWITCH_ID]),
RTA_PAYLOAD(tb[IFLA_PHYS_SWITCH_ID]),
b1, sizeof(b1)));
}
}
if (do_link && tb[IFLA_AF_SPEC] && show_details)
print_af_spec(fp, tb[IFLA_AF_SPEC]);
if ((do_link || show_details) && tb[IFLA_IFALIAS]) {
fprintf(fp, "%s alias %s", _SL_,
......
......@@ -20,6 +20,7 @@
#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include <limits.h>
#ifdef HAVE_ELF
#include <libelf.h>
......@@ -184,7 +185,7 @@ static int bpf_ops_parse(int argc, char **argv, struct sock_filter *bpf_ops,
}
if (i != bpf_len) {
fprintf(stderr, "Parsed program length is less than encodedlength parameter!\n");
fprintf(stderr, "Parsed program length is less than encoded length parameter!\n");
ret = -EINVAL;
goto out;
}
......@@ -214,6 +215,30 @@ void bpf_print_ops(FILE *f, struct rtattr *bpf_ops, __u16 len)
ops[i].jf, ops[i].k);
}
static void bpf_map_pin_report(const struct bpf_elf_map *pin,
const struct bpf_elf_map *obj)
{
fprintf(stderr, "Map specification differs from pinned file!\n");
if (obj->type != pin->type)
fprintf(stderr, " - Type: %u (obj) != %u (pin)\n",
obj->type, pin->type);
if (obj->size_key != pin->size_key)
fprintf(stderr, " - Size key: %u (obj) != %u (pin)\n",
obj->size_key, pin->size_key);
if (obj->size_value != pin->size_value)
fprintf(stderr, " - Size value: %u (obj) != %u (pin)\n",
obj->size_value, pin->size_value);
if (obj->max_elem != pin->max_elem)
fprintf(stderr, " - Max elems: %u (obj) != %u (pin)\n",
obj->max_elem, pin->max_elem);
if (obj->flags != pin->flags)
fprintf(stderr, " - Flags: %#x (obj) != %#x (pin)\n",
obj->flags, pin->flags);
fprintf(stderr, "\n");
}
static int bpf_map_selfcheck_pinned(int fd, const struct bpf_elf_map *map,
int length)
{
......@@ -240,6 +265,8 @@ static int bpf_map_selfcheck_pinned(int fd, const struct bpf_elf_map *map,
tmp.size_value = val;
else if (sscanf(buff, "max_entries:\t%u", &val) == 1)
tmp.max_elem = val;
else if (sscanf(buff, "map_flags:\t%i", &val) == 1)
tmp.flags = val;
}
fclose(fp);
......@@ -256,7 +283,7 @@ static int bpf_map_selfcheck_pinned(int fd, const struct bpf_elf_map *map,
if (!memcmp(&tmp, &zero, length))
return 0;
fprintf(stderr, "Map specs from pinned file differ!\n");
bpf_map_pin_report(&tmp, map);
return -EINVAL;
}
}
......@@ -735,7 +762,19 @@ bpf_dump_error(struct bpf_elf_ctx *ctx, const char *format, ...)
va_end(vl);
if (ctx->log && ctx->log[0]) {
fprintf(stderr, "%s\n", ctx->log);
if (ctx->verbose) {
fprintf(stderr, "%s\n", ctx->log);
} else {
unsigned int off = 0, len = strlen(ctx->log);
if (len > BPF_MAX_LOG) {
off = len - BPF_MAX_LOG;
fprintf(stderr, "Skipped %u bytes, use \'verb\' option for the full verbose log.\n[...]\n",
off);
}
fprintf(stderr, "%s\n", ctx->log + off);
}
memset(ctx->log, 0, ctx->log_size);
}
}
......@@ -763,8 +802,9 @@ static int bpf_log_realloc(struct bpf_elf_ctx *ctx)
return 0;
}
static int bpf_map_create(enum bpf_map_type type, unsigned int size_key,
unsigned int size_value, unsigned int max_elem)
static int bpf_map_create(enum bpf_map_type type, uint32_t size_key,
uint32_t size_value, uint32_t max_elem,
uint32_t flags)
{
union bpf_attr attr;
......@@ -773,6 +813,7 @@ static int bpf_map_create(enum bpf_map_type type, unsigned int size_key,
attr.key_size = size_key;
attr.value_size = size_value;
attr.max_entries = max_elem;
attr.map_flags = flags;
return bpf(BPF_MAP_CREATE, &attr, sizeof(attr));
}
......@@ -1055,14 +1096,16 @@ static void bpf_prog_report(int fd, const char *section,
const struct bpf_elf_prog *prog,
struct bpf_elf_ctx *ctx)
{
fprintf(stderr, "Prog section \'%s\' %s%s (%d)!\n", section,
unsigned int insns = prog->size / sizeof(struct bpf_insn);
fprintf(stderr, "\nProg section \'%s\' %s%s (%d)!\n", section,
fd < 0 ? "rejected: " : "loaded",
fd < 0 ? strerror(errno) : "",
fd < 0 ? errno : fd);
fprintf(stderr, " - Type: %u\n", prog->type);
fprintf(stderr, " - Instructions: %zu\n",
prog->size / sizeof(struct bpf_insn));
fprintf(stderr, " - Instructions: %u (%u over limit)\n",
insns, insns > BPF_MAXINSNS ? insns - BPF_MAXINSNS : 0);
fprintf(stderr, " - License: %s\n\n", prog->license);
bpf_dump_error(ctx, "Verifier analysis:\n\n");
......@@ -1112,7 +1155,8 @@ static void bpf_map_report(int fd, const char *name,
fprintf(stderr, " - Pinning: %u\n", map->pinning);
fprintf(stderr, " - Size key: %u\n", map->size_key);
fprintf(stderr, " - Size value: %u\n", map->size_value);
fprintf(stderr, " - Max elems: %u\n\n", map->max_elem);
fprintf(stderr, " - Max elems: %u\n", map->max_elem);
fprintf(stderr, " - Flags: %#x\n\n", map->flags);
}
static int bpf_map_attach(const char *name, const struct bpf_elf_map *map,
......@@ -1139,7 +1183,7 @@ static int bpf_map_attach(const char *name, const struct bpf_elf_map *map,
errno = 0;
fd = bpf_map_create(map->type, map->size_key, map->size_value,
map->max_elem);
map->max_elem, map->flags);
if (fd < 0 || ctx->verbose) {
bpf_map_report(fd, name, map, ctx);
if (fd < 0)
......@@ -1283,6 +1327,11 @@ static int bpf_fetch_strtab(struct bpf_elf_ctx *ctx, int section,
return 0;
}
static bool bpf_has_map_data(const struct bpf_elf_ctx *ctx)
{
return ctx->sym_tab && ctx->str_tab && ctx->sec_maps;
}
static int bpf_fetch_ancillary(struct bpf_elf_ctx *ctx)
{
struct bpf_elf_sec_data data;
......@@ -1306,13 +1355,13 @@ static int bpf_fetch_ancillary(struct bpf_elf_ctx *ctx)
!strcmp(data.sec_name, ".strtab"))
ret = bpf_fetch_strtab(ctx, i, &data);
if (ret < 0) {
fprintf(stderr, "Error parsing section %d! Perhapscheck with readelf -a?\n",
fprintf(stderr, "Error parsing section %d! Perhaps check with readelf -a?\n",
i);
break;
}
}
if (ctx->sym_tab && ctx->str_tab && ctx->sec_maps) {
if (bpf_has_map_data(ctx)) {
ret = bpf_maps_attach_all(ctx);
if (ret < 0) {
fprintf(stderr, "Error loading maps into kernel!\n");
......@@ -1348,7 +1397,7 @@ static int bpf_fetch_prog(struct bpf_elf_ctx *ctx, const char *section)
fd = bpf_prog_attach(section, &prog, ctx);
if (fd < 0)
continue;
break;
ctx->sec_done[i] = true;
break;
......@@ -1412,7 +1461,8 @@ static int bpf_apply_relo_data(struct bpf_elf_ctx *ctx,
return 0;
}
static int bpf_fetch_prog_relo(struct bpf_elf_ctx *ctx, const char *section)
static int bpf_fetch_prog_relo(struct bpf_elf_ctx *ctx, const char *section,
bool *lderr)
{
struct bpf_elf_sec_data data_relo, data_insn;
struct bpf_elf_prog prog;
......@@ -1442,8 +1492,10 @@ static int bpf_fetch_prog_relo(struct bpf_elf_ctx *ctx, const char *section)
prog.license = ctx->license;
fd = bpf_prog_attach(section, &prog, ctx);
if (fd < 0)
continue;
if (fd < 0) {
*lderr = true;
break;
}
ctx->sec_done[i] = true;
ctx->sec_done[idx] = true;
......@@ -1455,11 +1507,12 @@ static int bpf_fetch_prog_relo(struct bpf_elf_ctx *ctx, const char *section)
static int bpf_fetch_prog_sec(struct bpf_elf_ctx *ctx, const char *section)
{
bool lderr = false;
int ret = -1;
if (ctx->sym_tab)
ret = bpf_fetch_prog_relo(ctx, section);
if (ret < 0)
if (bpf_has_map_data(ctx))
ret = bpf_fetch_prog_relo(ctx, section, &lderr);
if (ret < 0 && !lderr)
ret = bpf_fetch_prog(ctx, section);
return ret;
......@@ -1504,8 +1557,12 @@ static int bpf_fill_prog_arrays(struct bpf_elf_ctx *ctx)
ret = bpf_map_update(ctx->map_fds[idx], &key_id,
&fd, BPF_ANY);
if (ret < 0)
return -ENOENT;
if (ret < 0) {
if (errno == E2BIG)
fprintf(stderr, "Tail call key %u for map %u out of bounds?\n",
key_id, map_id);
return -errno;
}
ctx->sec_done[i] = true;
}
......
......@@ -33,6 +33,10 @@ enum {
#define BPF_ENV_UDS "TC_BPF_UDS"
#define BPF_ENV_MNT "TC_BPF_MNT"
#ifndef BPF_MAX_LOG
# define BPF_MAX_LOG 4096
#endif
#ifndef BPF_FS_MAGIC
# define BPF_FS_MAGIC 0xcafe4a11
#endif
......
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