static void usage(void)
{
- fprintf(stderr, "Usage: bridge mdb { add | del } dev DEV port PORT grp GROUP [permanent | temp]\n");
+ 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");
exit(-1);
}
fprintf(f, "\n");
}
-static void print_mdb_entry(FILE *f, int ifindex, struct br_mdb_entry *e)
+static void print_mdb_entry(FILE *f, int ifindex, struct br_mdb_entry *e,
+ struct nlmsghdr *n)
{
SPRINT_BUF(abuf);
-
- if (e->addr.proto == htons(ETH_P_IP))
- fprintf(f, "dev %s port %s grp %s %s\n", ll_index_to_name(ifindex),
- ll_index_to_name(e->ifindex),
- inet_ntop(AF_INET, &e->addr.u.ip4, abuf, sizeof(abuf)),
- (e->state & MDB_PERMANENT) ? "permanent" : "temp");
- else
- fprintf(f, "dev %s port %s grp %s %s\n", ll_index_to_name(ifindex),
- ll_index_to_name(e->ifindex),
- inet_ntop(AF_INET6, &e->addr.u.ip6, abuf, sizeof(abuf)),
- (e->state & MDB_PERMANENT) ? "permanent" : "temp");
+ const void *src;
+ int af;
+
+ 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;
+ if (n->nlmsg_type == RTM_DELMDB)
+ fprintf(f, "Deleted ");
+ fprintf(f, "dev %s port %s grp %s %s", ll_index_to_name(ifindex),
+ ll_index_to_name(e->ifindex),
+ inet_ntop(af, src, abuf, sizeof(abuf)),
+ (e->state & MDB_PERMANENT) ? "permanent" : "temp");
+ if (e->vid)
+ fprintf(f, " vid %hu", e->vid);
+ fprintf(f, "\n");
}
-static void br_print_mdb_entry(FILE *f, int ifindex, struct rtattr *attr)
+static void br_print_mdb_entry(FILE *f, int ifindex, struct rtattr *attr,
+ struct nlmsghdr *n)
{
struct rtattr *i;
int rem;
rem = RTA_PAYLOAD(attr);
for (i = RTA_DATA(attr); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) {
e = RTA_DATA(i);
- print_mdb_entry(f, ifindex, e);
+ print_mdb_entry(f, ifindex, e, n);
}
}
int rem = RTA_PAYLOAD(tb[MDBA_MDB]);
for (i = RTA_DATA(tb[MDBA_MDB]); RTA_OK(i, rem); i = RTA_NEXT(i, rem))
- br_print_mdb_entry(fp, r->ifindex, i);
+ br_print_mdb_entry(fp, r->ifindex, i, n);
}
if (tb[MDBA_ROUTER]) {
} req;
struct br_mdb_entry entry;
char *d = NULL, *p = NULL, *grp = NULL;
+ short vid = 0;
memset(&req, 0, sizeof(req));
memset(&entry, 0, sizeof(entry));
entry.state |= MDB_PERMANENT;
} else if (strcmp(*argv, "temp") == 0) {
;/* nothing */
+ } else if (strcmp(*argv, "vid") == 0) {
+ NEXT_ARG();
+ vid = atoi(*argv);
} else {
if (matches(*argv, "help") == 0)
usage();
} else
entry.addr.proto = htons(ETH_P_IP);
+ entry.vid = vid;
addattr_l(&req.n, sizeof(req), MDBA_SET_ENTRY, &entry, sizeof(entry));
if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
BPF_MAP_TYPE_HASH,
BPF_MAP_TYPE_ARRAY,
BPF_MAP_TYPE_PROG_ARRAY,
+ BPF_MAP_TYPE_PERF_EVENT_ARRAY,
};
enum bpf_prog_type {
* Return: 0 on success
*/
BPF_FUNC_get_current_comm,
+
+ /**
+ * bpf_get_cgroup_classid(skb) - retrieve a proc's classid
+ * @skb: pointer to skb
+ * Return: classid if != 0
+ */
+ BPF_FUNC_get_cgroup_classid,
+ BPF_FUNC_skb_vlan_push, /* bpf_skb_vlan_push(skb, vlan_proto, vlan_tci) */
+ BPF_FUNC_skb_vlan_pop, /* bpf_skb_vlan_pop(skb) */
+
+ /**
+ * bpf_skb_[gs]et_tunnel_key(skb, key, size, flags)
+ * retrieve or populate tunnel metadata
+ * @skb: pointer to skb
+ * @key: pointer to 'struct bpf_tunnel_key'
+ * @size: size of 'struct bpf_tunnel_key'
+ * @flags: room for future extensions
+ * Retrun: 0 on success
+ */
+ BPF_FUNC_skb_get_tunnel_key,
+ BPF_FUNC_skb_set_tunnel_key,
+ BPF_FUNC_perf_event_read, /* u64 bpf_perf_event_read(&map, index) */
__BPF_FUNC_MAX_ID,
};
__u32 ifindex;
__u32 tc_index;
__u32 cb[5];
+ __u32 hash;
+};
+
+struct bpf_tunnel_key {
+ __u32 tunnel_id;
+ __u32 remote_ipv4;
};
#endif /* __LINUX_BPF_H__ */
FRA_UNUSED5,
FRA_FWMARK, /* mark */
FRA_FLOW, /* flow/class id */
- FRA_UNUSED6,
+ FRA_TUN_ID,
FRA_SUPPRESS_IFGROUP,
FRA_SUPPRESS_PREFIXLEN,
FRA_TABLE, /* Extended table id */
#define MDB_TEMPORARY 0
#define MDB_PERMANENT 1
__u8 state;
+ __u16 vid;
struct {
union {
__be32 ip4;
IFLA_PHYS_SWITCH_ID,
IFLA_LINK_NETNSID,
IFLA_PHYS_PORT_NAME,
+ IFLA_PROTO_DOWN,
__IFLA_MAX
};
IFLA_VXLAN_REMCSUM_RX,
IFLA_VXLAN_GBP,
IFLA_VXLAN_REMCSUM_NOPARTIAL,
+ IFLA_VXLAN_COLLECT_METADATA,
__IFLA_VXLAN_MAX
};
#define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1)
IFLA_BOND_AD_ACTOR_SYS_PRIO,
IFLA_BOND_AD_USER_PORT_KEY,
IFLA_BOND_AD_ACTOR_SYSTEM,
+ IFLA_BOND_TLB_DYNAMIC_LB,
__IFLA_BOND_MAX,
};
#define MPLS_LABEL_OAMALERT 14 /* RFC3429 */
#define MPLS_LABEL_EXTENSION 15 /* RFC7274 */
+#define MPLS_LABEL_FIRST_UNRESERVED 16 /* RFC3032 */
+
#endif /* _MPLS_H */
/* Routing message attributes */
+enum ip_tunnel_t {
+ IP_TUN_UNSPEC,
+ IP_TUN_ID,
+ IP_TUN_DST,
+ IP_TUN_SRC,
+ IP_TUN_TTL,
+ IP_TUN_TOS,
+ IP_TUN_SPORT,
+ IP_TUN_DPORT,
+ IP_TUN_FLAGS,
+ __IP_TUN_MAX,
+};
+
+#define IP_TUN_MAX (__IP_TUN_MAX - 1)
+
enum rtattr_type_t {
RTA_UNSPEC,
RTA_DST,
RTA_VIA,
RTA_NEWDST,
RTA_PREF,
+ RTA_ENCAP_TYPE,
+ RTA_ENCAP,
__RTA_MAX
};
fprintf(fp, " link-netnsid unknown");
}
+ if (tb[IFLA_PROTO_DOWN]) {
+ if (rta_getattr_u8(tb[IFLA_PROTO_DOWN]))
+ fprintf(fp, " protodown on ");
+ }
+
if (tb[IFLA_PROMISCUITY] && show_details)
fprintf(fp, " promiscuity %u ",
*(int*)RTA_DATA(tb[IFLA_PROMISCUITY]));
fprintf(stderr, " [ master DEVICE ]\n");
fprintf(stderr, " [ nomaster ]\n");
fprintf(stderr, " [ addrgenmode { eui64 | none } ]\n");
+ fprintf(stderr, " [ protodown { on | off } ]\n");
fprintf(stderr, " ip link show [ DEVICE | group GROUP ] [up] [master DEV] [type TYPE]\n");
if (iplink_have_newlink()) {
invarg("Invalid \"link-netnsid\" value\n", *argv);
addattr32(&req->n, sizeof(*req), IFLA_LINK_NETNSID,
link_netnsid);
+ } else if (strcmp(*argv, "protodown") == 0) {
+ unsigned int proto_down;
+
+ NEXT_ARG();
+ if (strcmp(*argv, "on") == 0)
+ proto_down = 1;
+ else if (strcmp(*argv, "off") == 0)
+ proto_down = 0;
+ else
+ return on_off("protodown", *argv);
+ addattr8(&req->n, sizeof(*req), IFLA_PROTO_DOWN,
+ proto_down);
} else {
if (strcmp(*argv, "dev") == 0) {
NEXT_ARG();
" [ min_links MIN_LINKS ]\n"
" [ lp_interval LP_INTERVAL ]\n"
" [ packets_per_slave PACKETS_PER_SLAVE ]\n"
+ " [ tlb_dynamic_lb TLB_DYNAMIC_LB ]\n"
" [ lacp_rate LACP_RATE ]\n"
" [ ad_select AD_SELECT ]\n"
" [ ad_user_port_key PORTKEY ]\n"
{
__u8 mode, use_carrier, primary_reselect, fail_over_mac;
__u8 xmit_hash_policy, num_peer_notif, all_slaves_active;
- __u8 lacp_rate, ad_select;
+ __u8 lacp_rate, ad_select, tlb_dynamic_lb;
__u16 ad_user_port_key, ad_actor_sys_prio;
__u32 miimon, updelay, downdelay, arp_interval, arp_validate;
__u32 arp_all_targets, resend_igmp, min_links, lp_interval;
return -1;
addattr_l(n, 1024, IFLA_BOND_AD_ACTOR_SYSTEM,
abuf, len);
+ } else if (matches(*argv, "tlb_dynamic_lb") == 0) {
+ NEXT_ARG();
+ if (get_u8(&tlb_dynamic_lb, *argv, 0)) {
+ invarg("invalid tlb_dynamic_lb", *argv);
+ return -1;
+ }
+ addattr8(n, 1024, IFLA_BOND_TLB_DYNAMIC_LB,
+ tlb_dynamic_lb);
} else if (matches(*argv, "help") == 0) {
explain();
return -1;
RTA_PAYLOAD(tb[IFLA_BOND_AD_ACTOR_SYSTEM]),
1 /*ARPHDR_ETHER*/, b1, sizeof(b1)));
}
+
+ if (tb[IFLA_BOND_TLB_DYNAMIC_LB]) {
+ fprintf(f, "tlb_dynamic_lb %u ",
+ rta_getattr_u8(tb[IFLA_BOND_TLB_DYNAMIC_LB]));
+ }
}
static void bond_print_help(struct link_util *lu, int argc, char **argv,
.IR PORT
.B grp
.IR GROUP " [ "
-.BR permanent " | " temp " ]"
+.BR permanent " | " temp " ] [ "
+.B vid
+.IR VID " ] "
.ti -8
.BR "bridge mdb show " [ "
- the mdb entry is temporary (default)
.sp
+.TP
+.BI vid " VID"
+the VLAN ID which is known to have members of this multicast group.
+
.in -8
.SS bridge mdb delete - delete a multicast group database entry
This command removes an existing mdb entry.
.br
.BR multicast " { " on " | " off " } |"
.br
+.BR protodown " { " on " | " off " } |"
+.br
.B txqueuelen
.IR PACKETS " |"
.br
.B MULTICAST
flag on the device.
+.TP
+.BR "protodown on " or " protodown off"
+change the
+.B PROTODOWN
+state on the device. Indicates that a protocol error has been detected on the port. Switch drivers can react to this error by doing a phys down on the switch port.
+
.TP
.BR "dynamic on " or " dynamic off"
change the
static void explain(void)
{
- fprintf(stderr, "Usage: ... bpf ...\n");
+ fprintf(stderr, "Usage: ... bpf ... [ index INDEX ]\n");
fprintf(stderr, "\n");
fprintf(stderr, "BPF use case:\n");
fprintf(stderr, " bytecode BPF_BYTECODE\n");
fprintf(stderr, "\n");
fprintf(stderr, "Where UDS_FILE points to a unix domain socket file in order\n");
fprintf(stderr, "to hand off control of all created eBPF maps to an agent.\n");
+ fprintf(stderr, "\n");
+ fprintf(stderr, "Where optionally INDEX points to an existing action, or\n");
+ fprintf(stderr, "explicitly specifies an action index upon creation.\n");
}
static void usage(void)
struct rtattr *tail;
struct tc_act_bpf parm = { 0 };
struct sock_filter bpf_ops[BPF_MAXINSNS];
+ bool ebpf_fill = false, bpf_fill = false;
bool ebpf = false, seen_run = false;
const char *bpf_uds_name = NULL;
const char *bpf_sec_name = NULL;
bpf_obj, bpf_sec_name);
bpf_fd = ret;
+ ebpf_fill = true;
} else {
bpf_len = ret;
+ bpf_fill = true;
}
} else if (matches(*argv, "help") == 0) {
usage();
+ } else if (matches(*argv, "index") == 0) {
+ break;
} else {
if (!seen_run)
goto opt_bpf;
}
}
- if ((!bpf_len && !ebpf) || (!bpf_fd && ebpf)) {
- fprintf(stderr, "bpf: Bytecode needs to be passed\n");
- explain();
- return -1;
- }
-
tail = NLMSG_TAIL(n);
addattr_l(n, MAX_MSG, tca_id, NULL, 0);
addattr_l(n, MAX_MSG, TCA_ACT_BPF_PARMS, &parm, sizeof(parm));
- if (ebpf) {
+ if (ebpf_fill) {
addattr32(n, MAX_MSG, TCA_ACT_BPF_FD, bpf_fd);
addattrstrz(n, MAX_MSG, TCA_ACT_BPF_NAME, bpf_name);
- } else {
+ } else if (bpf_fill) {
addattr16(n, MAX_MSG, TCA_ACT_BPF_OPS_LEN, bpf_len);
addattr_l(n, MAX_MSG, TCA_ACT_BPF_OPS, &bpf_ops,
bpf_len * sizeof(struct sock_filter));