diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 5e4d3739..19e0c36a 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -84,6 +84,7 @@ enum bpf_map_type { BPF_MAP_TYPE_PERCPU_HASH, BPF_MAP_TYPE_PERCPU_ARRAY, BPF_MAP_TYPE_STACK_TRACE, + BPF_MAP_TYPE_CGROUP_ARRAY, }; enum bpf_prog_type { @@ -93,6 +94,7 @@ enum bpf_prog_type { BPF_PROG_TYPE_SCHED_CLS, BPF_PROG_TYPE_SCHED_ACT, BPF_PROG_TYPE_TRACEPOINT, + BPF_PROG_TYPE_XDP, }; #define BPF_PSEUDO_MAP_FD 1 @@ -313,6 +315,66 @@ enum bpf_func_id { */ BPF_FUNC_skb_get_tunnel_opt, BPF_FUNC_skb_set_tunnel_opt, + + /** + * bpf_skb_change_proto(skb, proto, flags) + * Change protocol of the skb. Currently supported is + * v4 -> v6, v6 -> v4 transitions. The helper will also + * resize the skb. eBPF program is expected to fill the + * new headers via skb_store_bytes and lX_csum_replace. + * @skb: pointer to skb + * @proto: new skb->protocol type + * @flags: reserved + * Return: 0 on success or negative error + */ + BPF_FUNC_skb_change_proto, + + /** + * bpf_skb_change_type(skb, type) + * Change packet type of skb. + * @skb: pointer to skb + * @type: new skb->pkt_type type + * Return: 0 on success or negative error + */ + BPF_FUNC_skb_change_type, + + /** + * bpf_skb_in_cgroup(skb, map, index) - Check cgroup2 membership of skb + * @skb: pointer to skb + * @map: pointer to bpf_map in BPF_MAP_TYPE_CGROUP_ARRAY type + * @index: index of the cgroup in the bpf_map + * Return: + * == 0 skb failed the cgroup2 descendant test + * == 1 skb succeeded the cgroup2 descendant test + * < 0 error + */ + BPF_FUNC_skb_in_cgroup, + + /** + * bpf_get_hash_recalc(skb) + * Retrieve and possibly recalculate skb->hash. + * @skb: pointer to skb + * Return: hash + */ + BPF_FUNC_get_hash_recalc, + + /** + * u64 bpf_get_current_task(void) + * Returns current task_struct + * Return: current + */ + BPF_FUNC_get_current_task, + + /** + * bpf_probe_write_user(void *dst, void *src, int len) + * safely attempt to write to a location + * @dst: destination address in userspace + * @src: source address on stack + * @len: number of bytes to copy + * Return: 0 on success or negative error + */ + BPF_FUNC_probe_write_user, + __BPF_FUNC_MAX_ID, }; @@ -347,9 +409,11 @@ enum bpf_func_id { #define BPF_F_ZERO_CSUM_TX (1ULL << 1) #define BPF_F_DONT_FRAGMENT (1ULL << 2) -/* BPF_FUNC_perf_event_output flags. */ +/* BPF_FUNC_perf_event_output and BPF_FUNC_perf_event_read flags. */ #define BPF_F_INDEX_MASK 0xffffffffULL #define BPF_F_CURRENT_CPU BPF_F_INDEX_MASK +/* BPF_FUNC_perf_event_output for sk_buff input context. */ +#define BPF_F_CTXLEN_MASK (0xfffffULL << 32) /* user accessible mirror of in-kernel sk_buff. * new fields can only be added to the end of this structure @@ -386,4 +450,24 @@ struct bpf_tunnel_key { __u32 tunnel_label; }; +/* User return codes for XDP prog type. + * A valid XDP program must return one of these defined values. All other + * return codes are reserved for future use. Unknown return codes will result + * in packet drop. + */ +enum xdp_action { + XDP_ABORTED = 0, + XDP_DROP, + XDP_PASS, + XDP_TX, +}; + +/* user accessible metadata for XDP packet hook + * new fields must be added to the end of this structure + */ +struct xdp_md { + __u32 data; + __u32 data_end; +}; + #endif /* __LINUX_BPF_H__ */ diff --git a/include/linux/devlink.h b/include/linux/devlink.h index 0e21d001..b7c1a069 100644 --- a/include/linux/devlink.h +++ b/include/linux/devlink.h @@ -57,6 +57,8 @@ enum devlink_command { DEVLINK_CMD_SB_OCC_SNAPSHOT, DEVLINK_CMD_SB_OCC_MAX_CLEAR, + DEVLINK_CMD_ESWITCH_MODE_GET, + DEVLINK_CMD_ESWITCH_MODE_SET, /* add new commands above here */ __DEVLINK_CMD_MAX, @@ -95,6 +97,11 @@ enum devlink_sb_threshold_type { #define DEVLINK_SB_THRESHOLD_TO_ALPHA_MAX 20 +enum devlink_eswitch_mode { + DEVLINK_ESWITCH_MODE_LEGACY, + DEVLINK_ESWITCH_MODE_SWITCHDEV, +}; + enum devlink_attr { /* don't change the order or add anything between, this is ABI! */ DEVLINK_ATTR_UNSPEC, @@ -125,6 +132,7 @@ enum devlink_attr { DEVLINK_ATTR_SB_TC_INDEX, /* u16 */ DEVLINK_ATTR_SB_OCC_CUR, /* u32 */ DEVLINK_ATTR_SB_OCC_MAX, /* u32 */ + DEVLINK_ATTR_ESWITCH_MODE, /* u16 */ /* add new attributes above here, update the policy in devlink.c */ diff --git a/include/linux/fib_rules.h b/include/linux/fib_rules.h index 620c8a5d..14404b3e 100644 --- a/include/linux/fib_rules.h +++ b/include/linux/fib_rules.h @@ -50,6 +50,7 @@ enum { FRA_FWMASK, /* mask for netfilter mark */ FRA_OIFNAME, FRA_PAD, + FRA_L3MDEV, /* iif or oif is l3mdev goto its table */ __FRA_MAX }; diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h index fc3dcfa4..d9c76fe7 100644 --- a/include/linux/if_bridge.h +++ b/include/linux/if_bridge.h @@ -247,8 +247,37 @@ enum { enum { BRIDGE_XSTATS_UNSPEC, BRIDGE_XSTATS_VLAN, + BRIDGE_XSTATS_MCAST, + BRIDGE_XSTATS_PAD, __BRIDGE_XSTATS_MAX }; #define BRIDGE_XSTATS_MAX (__BRIDGE_XSTATS_MAX - 1) +enum { + BR_MCAST_DIR_RX, + BR_MCAST_DIR_TX, + BR_MCAST_DIR_SIZE +}; + +/* IGMP/MLD statistics */ +struct br_mcast_stats { + __u64 igmp_v1queries[BR_MCAST_DIR_SIZE]; + __u64 igmp_v2queries[BR_MCAST_DIR_SIZE]; + __u64 igmp_v3queries[BR_MCAST_DIR_SIZE]; + __u64 igmp_leaves[BR_MCAST_DIR_SIZE]; + __u64 igmp_v1reports[BR_MCAST_DIR_SIZE]; + __u64 igmp_v2reports[BR_MCAST_DIR_SIZE]; + __u64 igmp_v3reports[BR_MCAST_DIR_SIZE]; + __u64 igmp_parse_errors; + + __u64 mld_v1queries[BR_MCAST_DIR_SIZE]; + __u64 mld_v2queries[BR_MCAST_DIR_SIZE]; + __u64 mld_leaves[BR_MCAST_DIR_SIZE]; + __u64 mld_v1reports[BR_MCAST_DIR_SIZE]; + __u64 mld_v2reports[BR_MCAST_DIR_SIZE]; + __u64 mld_parse_errors; + + __u64 mcast_bytes[BR_MCAST_DIR_SIZE]; + __u64 mcast_packets[BR_MCAST_DIR_SIZE]; +}; #endif /* _LINUX_IF_BRIDGE_H */ diff --git a/include/linux/if_ether.h b/include/linux/if_ether.h index c396f317..51898e04 100644 --- a/include/linux/if_ether.h +++ b/include/linux/if_ether.h @@ -87,6 +87,7 @@ #define ETH_P_8021AH 0x88E7 /* 802.1ah Backbone Service Tag */ #define ETH_P_MVRP 0x88F5 /* 802.1Q MVRP */ #define ETH_P_1588 0x88F7 /* IEEE 1588 Timesync */ +#define ETH_P_NCSI 0x88F8 /* NCSI protocol */ #define ETH_P_PRP 0x88FB /* IEC 62439-3 PRP/HSRv0 */ #define ETH_P_FCOE 0x8906 /* Fibre Channel over Ethernet */ #define ETH_P_TDLS 0x890D /* TDLS */ diff --git a/include/linux/if_link.h b/include/linux/if_link.h index 15bbeb81..1feb7089 100644 --- a/include/linux/if_link.h +++ b/include/linux/if_link.h @@ -156,6 +156,7 @@ enum { IFLA_GSO_MAX_SEGS, IFLA_GSO_MAX_SIZE, IFLA_PAD, + IFLA_XDP, __IFLA_MAX }; @@ -271,6 +272,7 @@ enum { IFLA_BR_VLAN_DEFAULT_PVID, IFLA_BR_PAD, IFLA_BR_VLAN_STATS_ENABLED, + IFLA_BR_MCAST_STATS_ENABLED, __IFLA_BR_MAX, }; @@ -820,6 +822,7 @@ enum { IFLA_STATS_UNSPEC, /* also used as 64bit pad attribute */ IFLA_STATS_LINK_64, IFLA_STATS_LINK_XSTATS, + IFLA_STATS_LINK_XSTATS_SLAVE, __IFLA_STATS_MAX, }; @@ -839,4 +842,15 @@ enum { }; #define LINK_XSTATS_TYPE_MAX (__LINK_XSTATS_TYPE_MAX - 1) +/* XDP section */ + +enum { + IFLA_XDP_UNSPEC, + IFLA_XDP_FD, + IFLA_XDP_ATTACHED, + __IFLA_XDP_MAX, +}; + +#define IFLA_XDP_MAX (__IFLA_XDP_MAX - 1) + #endif /* _LINUX_IF_LINK_H */ diff --git a/include/linux/if_macsec.h b/include/linux/if_macsec.h index cbd4faa3..22939a3e 100644 --- a/include/linux/if_macsec.h +++ b/include/linux/if_macsec.h @@ -26,6 +26,8 @@ #define MACSEC_MIN_ICV_LEN 8 #define MACSEC_MAX_ICV_LEN 32 +/* upper limit for ICV length as recommended by IEEE802.1AE-2006 */ +#define MACSEC_STD_ICV_LEN 16 enum macsec_attrs { MACSEC_ATTR_UNSPEC, diff --git a/include/linux/if_tunnel.h b/include/linux/if_tunnel.h index f0201ca0..1fa343db 100644 --- a/include/linux/if_tunnel.h +++ b/include/linux/if_tunnel.h @@ -113,6 +113,7 @@ enum { IFLA_GRE_ENCAP_SPORT, IFLA_GRE_ENCAP_DPORT, IFLA_GRE_COLLECT_METADATA, + IFLA_GRE_IGNORE_DF, __IFLA_GRE_MAX, }; diff --git a/include/linux/in6.h b/include/linux/in6.h index aa5b66df..45aaaa40 100644 --- a/include/linux/in6.h +++ b/include/linux/in6.h @@ -143,6 +143,7 @@ struct in6_flowlabel_req { #define IPV6_TLV_PAD1 0 #define IPV6_TLV_PADN 1 #define IPV6_TLV_ROUTERALERT 5 +#define IPV6_TLV_CALIPSO 7 /* RFC 5570 */ #define IPV6_TLV_JUMBO 194 #define IPV6_TLV_HAO 201 /* home address option */ diff --git a/include/linux/inet_diag.h b/include/linux/inet_diag.h index 07e486cb..beb74ee1 100644 --- a/include/linux/inet_diag.h +++ b/include/linux/inet_diag.h @@ -72,6 +72,7 @@ enum { INET_DIAG_BC_AUTO, INET_DIAG_BC_S_COND, INET_DIAG_BC_D_COND, + INET_DIAG_BC_DEV_COND, /* u32 ifindex */ }; struct inet_diag_hostcond { diff --git a/include/linux/netlink_diag.h b/include/linux/netlink_diag.h index f2159d30..defd25fb 100644 --- a/include/linux/netlink_diag.h +++ b/include/linux/netlink_diag.h @@ -48,6 +48,7 @@ enum { #define NDIAG_SHOW_MEMINFO 0x00000001 /* show memory info of a socket */ #define NDIAG_SHOW_GROUPS 0x00000002 /* show groups of a netlink socket */ +/* deprecated since 4.6 */ #define NDIAG_SHOW_RING_CFG 0x00000004 /* show ring configuration */ #endif diff --git a/include/linux/pkt_cls.h b/include/linux/pkt_cls.h index 333b1716..5e6c61e7 100644 --- a/include/linux/pkt_cls.h +++ b/include/linux/pkt_cls.h @@ -61,8 +61,8 @@ struct tc_police { __u32 mtu; struct tc_ratespec rate; struct tc_ratespec peakrate; - int refcnt; - int bindcnt; + int refcnt; + int bindcnt; __u32 capab; }; @@ -70,10 +70,11 @@ struct tcf_t { __u64 install; __u64 lastuse; __u64 expires; + __u64 firstuse; }; struct tc_cnt { - int refcnt; + int refcnt; int bindcnt; }; @@ -378,6 +379,18 @@ enum { #define TCA_FLOWER_MAX (__TCA_FLOWER_MAX - 1) +/* Match-all classifier */ + +enum { + TCA_MATCHALL_UNSPEC, + TCA_MATCHALL_CLASSID, + TCA_MATCHALL_ACT, + TCA_MATCHALL_FLAGS, + __TCA_MATCHALL_MAX, +}; + +#define TCA_MATCHALL_MAX (__TCA_MATCHALL_MAX - 1) + /* Extended Matches */ struct tcf_ematch_tree_hdr { diff --git a/include/linux/tc_act/tc_skbedit.h b/include/linux/tc_act/tc_skbedit.h index fecb5cc4..a4d00c60 100644 --- a/include/linux/tc_act/tc_skbedit.h +++ b/include/linux/tc_act/tc_skbedit.h @@ -27,6 +27,7 @@ #define SKBEDIT_F_PRIORITY 0x1 #define SKBEDIT_F_QUEUE_MAPPING 0x2 #define SKBEDIT_F_MARK 0x4 +#define SKBEDIT_F_PTYPE 0x8 struct tc_skbedit { tc_gen; @@ -40,6 +41,7 @@ enum { TCA_SKBEDIT_QUEUE_MAPPING, TCA_SKBEDIT_MARK, TCA_SKBEDIT_PAD, + TCA_SKBEDIT_PTYPE, __TCA_SKBEDIT_MAX }; #define TCA_SKBEDIT_MAX (__TCA_SKBEDIT_MAX - 1) diff --git a/include/linux/tcp.h b/include/linux/tcp.h index 7f21db9b..f3dcdb77 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h @@ -115,12 +115,22 @@ enum { #define TCP_CC_INFO 26 /* Get Congestion Control (optional) info */ #define TCP_SAVE_SYN 27 /* Record SYN headers for new connections */ #define TCP_SAVED_SYN 28 /* Get SYN headers recorded for connection */ +#define TCP_REPAIR_WINDOW 29 /* Get/set window parameters */ struct tcp_repair_opt { __u32 opt_code; __u32 opt_val; }; +struct tcp_repair_window { + __u32 snd_wl1; + __u32 snd_wnd; + __u32 max_window; + + __u32 rcv_wnd; + __u32 rcv_wup; +}; + enum { TCP_NO_QUEUE, TCP_RECV_QUEUE, diff --git a/include/linux/tipc.h b/include/linux/tipc.h index ebd3b63c..40043008 100644 --- a/include/linux/tipc.h +++ b/include/linux/tipc.h @@ -60,26 +60,48 @@ struct tipc_name_seq { __u32 upper; }; +/* TIPC Address Size, Offset, Mask specification for Z.C.N + */ +#define TIPC_NODE_BITS 12 +#define TIPC_CLUSTER_BITS 12 +#define TIPC_ZONE_BITS 8 + +#define TIPC_NODE_OFFSET 0 +#define TIPC_CLUSTER_OFFSET TIPC_NODE_BITS +#define TIPC_ZONE_OFFSET (TIPC_CLUSTER_OFFSET + TIPC_CLUSTER_BITS) + +#define TIPC_NODE_SIZE ((1UL << TIPC_NODE_BITS) - 1) +#define TIPC_CLUSTER_SIZE ((1UL << TIPC_CLUSTER_BITS) - 1) +#define TIPC_ZONE_SIZE ((1UL << TIPC_ZONE_BITS) - 1) + +#define TIPC_NODE_MASK (TIPC_NODE_SIZE << TIPC_NODE_OFFSET) +#define TIPC_CLUSTER_MASK (TIPC_CLUSTER_SIZE << TIPC_CLUSTER_OFFSET) +#define TIPC_ZONE_MASK (TIPC_ZONE_SIZE << TIPC_ZONE_OFFSET) + +#define TIPC_ZONE_CLUSTER_MASK (TIPC_ZONE_MASK | TIPC_CLUSTER_MASK) + static __inline__ __u32 tipc_addr(unsigned int zone, unsigned int cluster, unsigned int node) { - return (zone << 24) | (cluster << 12) | node; + return (zone << TIPC_ZONE_OFFSET) | + (cluster << TIPC_CLUSTER_OFFSET) | + node; } static __inline__ unsigned int tipc_zone(__u32 addr) { - return addr >> 24; + return addr >> TIPC_ZONE_OFFSET; } static __inline__ unsigned int tipc_cluster(__u32 addr) { - return (addr >> 12) & 0xfff; + return (addr & TIPC_CLUSTER_MASK) >> TIPC_CLUSTER_OFFSET; } static __inline__ unsigned int tipc_node(__u32 addr) { - return addr & 0xfff; + return addr & TIPC_NODE_MASK; } /* diff --git a/include/linux/tipc_netlink.h b/include/linux/tipc_netlink.h index d4c8f142..5f3f6d09 100644 --- a/include/linux/tipc_netlink.h +++ b/include/linux/tipc_netlink.h @@ -56,6 +56,9 @@ enum { TIPC_NL_NET_GET, TIPC_NL_NET_SET, TIPC_NL_NAME_TABLE_GET, + TIPC_NL_MON_SET, + TIPC_NL_MON_GET, + TIPC_NL_MON_PEER_GET, __TIPC_NL_CMD_MAX, TIPC_NL_CMD_MAX = __TIPC_NL_CMD_MAX - 1 @@ -72,6 +75,8 @@ enum { TIPC_NLA_NODE, /* nest */ TIPC_NLA_NET, /* nest */ TIPC_NLA_NAME_TABLE, /* nest */ + TIPC_NLA_MON, /* nest */ + TIPC_NLA_MON_PEER, /* nest */ __TIPC_NLA_MAX, TIPC_NLA_MAX = __TIPC_NLA_MAX - 1 @@ -166,6 +171,20 @@ enum { TIPC_NLA_NAME_TABLE_MAX = __TIPC_NLA_NAME_TABLE_MAX - 1 }; +/* Monitor info */ +enum { + TIPC_NLA_MON_UNSPEC, + TIPC_NLA_MON_ACTIVATION_THRESHOLD, /* u32 */ + TIPC_NLA_MON_REF, /* u32 */ + TIPC_NLA_MON_ACTIVE, /* flag */ + TIPC_NLA_MON_BEARER_NAME, /* string */ + TIPC_NLA_MON_PEERCNT, /* u32 */ + TIPC_NLA_MON_LISTGEN, /* u32 */ + + __TIPC_NLA_MON_MAX, + TIPC_NLA_MON_MAX = __TIPC_NLA_MON_MAX - 1 +}; + /* Publication info */ enum { TIPC_NLA_PUBL_UNSPEC, @@ -182,6 +201,24 @@ enum { TIPC_NLA_PUBL_MAX = __TIPC_NLA_PUBL_MAX - 1 }; +/* Monitor peer info */ +enum { + TIPC_NLA_MON_PEER_UNSPEC, + + TIPC_NLA_MON_PEER_ADDR, /* u32 */ + TIPC_NLA_MON_PEER_DOMGEN, /* u32 */ + TIPC_NLA_MON_PEER_APPLIED, /* u32 */ + TIPC_NLA_MON_PEER_UPMAP, /* u64 */ + TIPC_NLA_MON_PEER_MEMBERS, /* tlv */ + TIPC_NLA_MON_PEER_UP, /* flag */ + TIPC_NLA_MON_PEER_HEAD, /* flag */ + TIPC_NLA_MON_PEER_LOCAL, /* flag */ + TIPC_NLA_MON_PEER_PAD, /* flag */ + + __TIPC_NLA_MON_PEER_MAX, + TIPC_NLA_MON_PEER_MAX = __TIPC_NLA_MON_PEER_MAX - 1 +}; + /* Nest, connection info */ enum { TIPC_NLA_CON_UNSPEC, diff --git a/ip/iprule.c b/ip/iprule.c index f3ada820..8f242067 100644 --- a/ip/iprule.c +++ b/ip/iprule.c @@ -37,7 +37,7 @@ static void usage(void) fprintf(stderr, " ip rule { flush | save | restore }\n"); fprintf(stderr, " ip rule [ list ]\n"); fprintf(stderr, "SELECTOR := [ not ] [ from PREFIX ] [ to PREFIX ] [ tos TOS ] [ fwmark FWMARK[/MASK] ]\n"); - fprintf(stderr, " [ iif STRING ] [ oif STRING ] [ pref NUMBER ]\n"); + fprintf(stderr, " [ iif STRING ] [ oif STRING ] [ pref NUMBER ] [ l3mdev ]\n"); fprintf(stderr, "ACTION := [ table TABLE_ID ]\n"); fprintf(stderr, " [ nat ADDRESS ]\n"); fprintf(stderr, " [ realms [SRCREALM/]DSTREALM ]\n"); @@ -57,6 +57,7 @@ int print_rule(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) int host_len = -1; __u32 table; struct rtattr *tb[FRA_MAX+1]; + SPRINT_BUF(b1); if (n->nlmsg_type != RTM_NEWRULE && n->nlmsg_type != RTM_DELRULE) @@ -74,7 +75,8 @@ int print_rule(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) fprintf(fp, "Deleted "); if (tb[FRA_PRIORITY]) - fprintf(fp, "%u:\t", *(unsigned *)RTA_DATA(tb[FRA_PRIORITY])); + fprintf(fp, "%u:\t", + rta_getattr_u32(tb[FRA_PRIORITY])); else fprintf(fp, "0:\t"); @@ -84,11 +86,11 @@ int print_rule(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) if (tb[FRA_SRC]) { if (r->rtm_src_len != host_len) { fprintf(fp, "from %s/%u ", - rt_addr_n2a_rta(r->rtm_family, tb[FRA_SRC]), - r->rtm_src_len); + rt_addr_n2a_rta(r->rtm_family, tb[FRA_SRC]), + r->rtm_src_len); } else { fprintf(fp, "from %s ", - format_host_rta(r->rtm_family, tb[FRA_SRC])); + format_host_rta(r->rtm_family, tb[FRA_SRC])); } } else if (r->rtm_src_len) { fprintf(fp, "from 0/%d ", r->rtm_src_len); @@ -99,11 +101,11 @@ int print_rule(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) if (tb[FRA_DST]) { if (r->rtm_dst_len != host_len) { fprintf(fp, "to %s/%u ", - rt_addr_n2a_rta(r->rtm_family, tb[FRA_DST]), - r->rtm_dst_len); + rt_addr_n2a_rta(r->rtm_family, tb[FRA_DST]), + r->rtm_dst_len); } else { fprintf(fp, "to %s ", - format_host_rta(r->rtm_family, tb[FRA_DST])); + format_host_rta(r->rtm_family, tb[FRA_DST])); } } else if (r->rtm_dst_len) { fprintf(fp, "to 0/%d ", r->rtm_dst_len); @@ -111,7 +113,8 @@ int print_rule(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) if (r->rtm_tos) { SPRINT_BUF(b1); - fprintf(fp, "tos %s ", rtnl_dsfield_n2a(r->rtm_tos, b1, sizeof(b1))); + fprintf(fp, "tos %s ", + rtnl_dsfield_n2a(r->rtm_tos, b1, sizeof(b1))); } if (tb[FRA_FWMARK] || tb[FRA_FWMASK]) { @@ -139,23 +142,29 @@ int print_rule(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) fprintf(fp, "[detached] "); } + if (tb[FRA_L3MDEV]) { + if (rta_getattr_u8(tb[FRA_L3MDEV])) + fprintf(fp, "lookup [l3mdev-table] "); + } + table = rtm_get_table(r, tb); if (table) { - fprintf(fp, "lookup %s ", rtnl_rttable_n2a(table, b1, sizeof(b1))); + fprintf(fp, "lookup %s ", + rtnl_rttable_n2a(table, b1, sizeof(b1))); if (tb[FRA_SUPPRESS_PREFIXLEN]) { int pl = rta_getattr_u32(tb[FRA_SUPPRESS_PREFIXLEN]); - if (pl != -1) { + if (pl != -1) fprintf(fp, "suppress_prefixlength %d ", pl); - } } if (tb[FRA_SUPPRESS_IFGROUP]) { int group = rta_getattr_u32(tb[FRA_SUPPRESS_IFGROUP]); if (group != -1) { SPRINT_BUF(b1); - fprintf(fp, "suppress_ifgroup %s ", rtnl_group_n2a(group, b1, sizeof(b1))); + fprintf(fp, "suppress_ifgroup %s ", + rtnl_group_n2a(group, b1, sizeof(b1))); } } } @@ -176,8 +185,8 @@ int print_rule(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) if (r->rtm_type == RTN_NAT) { if (tb[RTA_GATEWAY]) { fprintf(fp, "map-to %s ", - format_host_rta(r->rtm_family, - tb[RTA_GATEWAY])); + format_host_rta(r->rtm_family, + tb[RTA_GATEWAY])); } else fprintf(fp, "masquerade"); } else if (r->rtm_type == FR_ACT_GOTO) { @@ -191,7 +200,9 @@ int print_rule(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) } else if (r->rtm_type == FR_ACT_NOP) fprintf(fp, "nop"); else if (r->rtm_type != RTN_UNICAST) - fprintf(fp, "%s", rtnl_rtntype_n2a(r->rtm_type, b1, sizeof(b1))); + fprintf(fp, "%s", + rtnl_rtntype_n2a(r->rtm_type, + b1, sizeof(b1))); fprintf(fp, "\n"); fflush(fp); @@ -218,7 +229,8 @@ static int save_rule_prep(void) return 0; } -static int save_rule(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) +static int save_rule(const struct sockaddr_nl *who, + struct nlmsghdr *n, void *arg) { int ret; @@ -276,7 +288,8 @@ static int rule_dump_check_magic(void) ret = fread(&magic, sizeof(magic), 1, stdin); if (magic != rule_dump_magic) { - fprintf(stderr, "Magic mismatch (%d elems, %x magic)\n", ret, magic); + fprintf(stderr, "Magic mismatch (%d elems, %x magic)\n", + ret, magic); return -1; } @@ -311,7 +324,9 @@ static int iprule_restore(void) static int iprule_modify(int cmd, int argc, char **argv) { + int l3mdev_rule = 0; int table_ok = 0; + __u32 tid = 0; struct { struct nlmsghdr n; struct rtmsg r; @@ -340,14 +355,16 @@ static int iprule_modify(int cmd, int argc, char **argv) NEXT_ARG(); get_prefix(&dst, *argv, req.r.rtm_family); req.r.rtm_src_len = dst.bitlen; - addattr_l(&req.n, sizeof(req), FRA_SRC, &dst.data, dst.bytelen); + addattr_l(&req.n, sizeof(req), FRA_SRC, + &dst.data, dst.bytelen); } else if (strcmp(*argv, "to") == 0) { inet_prefix dst; NEXT_ARG(); get_prefix(&dst, *argv, req.r.rtm_family); req.r.rtm_dst_len = dst.bitlen; - addattr_l(&req.n, sizeof(req), FRA_DST, &dst.data, dst.bytelen); + addattr_l(&req.n, sizeof(req), FRA_DST, + &dst.data, dst.bytelen); } else if (matches(*argv, "preference") == 0 || matches(*argv, "order") == 0 || matches(*argv, "priority") == 0) { @@ -370,15 +387,19 @@ static int iprule_modify(int cmd, int argc, char **argv) __u32 fwmark, fwmask; NEXT_ARG(); - if ((slash = strchr(*argv, '/')) != NULL) + + slash = strchr(*argv, '/'); + if (slash != NULL) *slash = '\0'; if (get_u32(&fwmark, *argv, 0)) invarg("fwmark value is invalid\n", *argv); addattr32(&req.n, sizeof(req), FRA_FWMARK, fwmark); if (slash) { if (get_u32(&fwmask, slash+1, 0)) - invarg("fwmask value is invalid\n", slash+1); - addattr32(&req.n, sizeof(req), FRA_FWMASK, fwmask); + invarg("fwmask value is invalid\n", + slash+1); + addattr32(&req.n, sizeof(req), + FRA_FWMASK, fwmask); } } else if (matches(*argv, "realms") == 0) { __u32 realm; @@ -389,8 +410,6 @@ static int iprule_modify(int cmd, int argc, char **argv) addattr32(&req.n, sizeof(req), FRA_FLOW, realm); } else if (matches(*argv, "table") == 0 || strcmp(*argv, "lookup") == 0) { - __u32 tid; - NEXT_ARG(); if (rtnl_rttable_a2n(&tid, *argv)) invarg("invalid table ID\n", *argv); @@ -407,35 +426,46 @@ static int iprule_modify(int cmd, int argc, char **argv) NEXT_ARG(); if (get_s32(&pl, *argv, 0) || pl < 0) - invarg("suppress_prefixlength value is invalid\n", *argv); - addattr32(&req.n, sizeof(req), FRA_SUPPRESS_PREFIXLEN, pl); + invarg("suppress_prefixlength value is invalid\n", + *argv); + addattr32(&req.n, sizeof(req), + FRA_SUPPRESS_PREFIXLEN, pl); } else if (matches(*argv, "suppress_ifgroup") == 0 || strcmp(*argv, "sup_group") == 0) { NEXT_ARG(); int group; if (rtnl_group_a2n(&group, *argv)) - invarg("Invalid \"suppress_ifgroup\" value\n", *argv); - addattr32(&req.n, sizeof(req), FRA_SUPPRESS_IFGROUP, group); + invarg("Invalid \"suppress_ifgroup\" value\n", + *argv); + addattr32(&req.n, sizeof(req), + FRA_SUPPRESS_IFGROUP, group); } else if (strcmp(*argv, "dev") == 0 || strcmp(*argv, "iif") == 0) { NEXT_ARG(); - addattr_l(&req.n, sizeof(req), FRA_IFNAME, *argv, strlen(*argv)+1); + addattr_l(&req.n, sizeof(req), FRA_IFNAME, + *argv, strlen(*argv)+1); } else if (strcmp(*argv, "oif") == 0) { NEXT_ARG(); - addattr_l(&req.n, sizeof(req), FRA_OIFNAME, *argv, strlen(*argv)+1); + addattr_l(&req.n, sizeof(req), FRA_OIFNAME, + *argv, strlen(*argv)+1); + } else if (strcmp(*argv, "l3mdev") == 0) { + addattr8(&req.n, sizeof(req), FRA_L3MDEV, 1); + table_ok = 1; + l3mdev_rule = 1; } else if (strcmp(*argv, "nat") == 0 || matches(*argv, "map-to") == 0) { NEXT_ARG(); fprintf(stderr, "Warning: route NAT is deprecated\n"); - addattr32(&req.n, sizeof(req), RTA_GATEWAY, get_addr32(*argv)); + addattr32(&req.n, sizeof(req), RTA_GATEWAY, + get_addr32(*argv)); req.r.rtm_type = RTN_NAT; } else { int type; - if (strcmp(*argv, "type") == 0) { + if (strcmp(*argv, "type") == 0) NEXT_ARG(); - } + if (matches(*argv, "help") == 0) usage(); else if (matches(*argv, "goto") == 0) { @@ -445,7 +475,8 @@ static int iprule_modify(int cmd, int argc, char **argv) NEXT_ARG(); if (get_u32(&target, *argv, 0)) invarg("invalid target\n", *argv); - addattr32(&req.n, sizeof(req), FRA_GOTO, target); + addattr32(&req.n, sizeof(req), + FRA_GOTO, target); } else if (matches(*argv, "nop") == 0) type = FR_ACT_NOP; else if (rtnl_rtntype_a2n(&type, *argv)) @@ -457,6 +488,12 @@ static int iprule_modify(int cmd, int argc, char **argv) argv++; } + if (l3mdev_rule && tid != 0) { + fprintf(stderr, + "table can not be specified for l3mdev rules\n"); + return -EINVAL; + } + if (req.r.rtm_family == AF_UNSPEC) req.r.rtm_family = AF_INET; @@ -470,7 +507,8 @@ static int iprule_modify(int cmd, int argc, char **argv) } -static int flush_rule(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) +static int flush_rule(const struct sockaddr_nl *who, struct nlmsghdr *n, + void *arg) { struct rtnl_handle rth2; struct rtmsg *r = NLMSG_DATA(n); @@ -545,7 +583,8 @@ int do_iprule(int argc, char **argv) } else if (matches(argv[0], "help") == 0) usage(); - fprintf(stderr, "Command \"%s\" is unknown, try \"ip rule help\".\n", *argv); + fprintf(stderr, + "Command \"%s\" is unknown, try \"ip rule help\".\n", *argv); exit(-1); } @@ -563,7 +602,8 @@ int do_multirule(int argc, char **argv) case RTNL_FAMILY_IP6MR: break; default: - fprintf(stderr, "Multicast rules are only supported for IPv4/IPv6, was: %i\n", + fprintf(stderr, + "Multicast rules are only supported for IPv4/IPv6, was: %i\n", preferred_family); exit(-1); } diff --git a/man/man8/ip-fou.8 b/man/man8/ip-fou.8 index 0fa22ee6..0c8f0a4d 100644 --- a/man/man8/ip-fou.8 +++ b/man/man8/ip-fou.8 @@ -56,7 +56,7 @@ in the delete command. .PP .SS Configure a FOU receive port for GRE bound to 7777 .nf -# ip fou add port 8888 ipproto 47 +# ip fou add port 7777 ipproto 47 .PP .SS Configure a FOU receive port for IPIP bound to 8888 .nf diff --git a/man/man8/tc-skbedit.8 b/man/man8/tc-skbedit.8 index e6902960..003f05c9 100644 --- a/man/man8/tc-skbedit.8 +++ b/man/man8/tc-skbedit.8 @@ -11,6 +11,8 @@ skbedit - SKB editing action .IR PRIORITY " ] [" .B mark .IR MARK " ]" +.B ptype +.IR PTYPE " ]" .SH DESCRIPTION The .B skbedit @@ -52,6 +54,13 @@ Change the packet's firewall mark value. is an unsigned 32bit value in automatically detected format (i.e., prefix with .RB ' 0x ' for hexadecimal interpretation, etc.). +.TP +.BI ptype " PTYPE" +Override the packet's type. Useful for setting packet type to host when +needing to allow ingressing packets with the wrong MAC address but +correct IP address. +.I PTYPE +is one of: host, otherhost, broadcast, multicast .SH SEE ALSO .BR tc (8), .BR tc-pedit (8) diff --git a/tc/m_skbedit.c b/tc/m_skbedit.c index eca6a8ac..368debc2 100644 --- a/tc/m_skbedit.c +++ b/tc/m_skbedit.c @@ -26,14 +26,17 @@ #include "utils.h" #include "tc_util.h" #include +#include -static void -explain(void) +static void explain(void) { - fprintf(stderr, "Usage: ... skbedit <[QM] [PM] [MM]>\n" + fprintf(stderr, "Usage: ... skbedit <[QM] [PM] [MM] [PT]>\n" "QM = queue_mapping QUEUE_MAPPING\n" "PM = priority PRIORITY\n" "MM = mark MARK\n" + "PT = ptype PACKETYPE\n" + "PACKETYPE = is one of:\n" + " host, otherhost, broadcast, multicast\n" "QUEUE_MAPPING = device transmit queue to use\n" "PRIORITY = classID to assign to priority field\n" "MARK = firewall mark to set\n"); @@ -55,7 +58,7 @@ parse_skbedit(struct action_util *a, int *argc_p, char ***argv_p, int tca_id, int ok = 0; struct rtattr *tail; unsigned int tmp; - __u16 queue_mapping; + __u16 queue_mapping, ptype; __u32 flags = 0, priority, mark; struct tc_skbedit sel = { 0 }; @@ -90,6 +93,24 @@ parse_skbedit(struct action_util *a, int *argc_p, char ***argv_p, int tca_id, return -1; } ok++; + } else if (matches(*argv, "ptype") == 0) { + + NEXT_ARG(); + if (matches(*argv, "host") == 0) { + ptype = PACKET_HOST; + } else if (matches(*argv, "broadcast") == 0) { + ptype = PACKET_BROADCAST; + } else if (matches(*argv, "multicast") == 0) { + ptype = PACKET_MULTICAST; + } else if (matches(*argv, "otherhost") == 0) { + ptype = PACKET_OTHERHOST; + } else { + fprintf(stderr, "Illegal ptype (%s)\n", + *argv); + return -1; + } + flags |= SKBEDIT_F_PTYPE; + ok++; } else if (matches(*argv, "help") == 0) { usage(); } else { @@ -134,6 +155,9 @@ parse_skbedit(struct action_util *a, int *argc_p, char ***argv_p, int tca_id, if (flags & SKBEDIT_F_MARK) addattr_l(n, MAX_MSG, TCA_SKBEDIT_MARK, &mark, sizeof(mark)); + if (flags & SKBEDIT_F_PTYPE) + addattr_l(n, MAX_MSG, TCA_SKBEDIT_PTYPE, + &ptype, sizeof(ptype)); tail->rta_len = (char *)NLMSG_TAIL(n) - (char *)tail; *argc_p = argc; @@ -148,7 +172,7 @@ static int print_skbedit(struct action_util *au, FILE *f, struct rtattr *arg) SPRINT_BUF(b1); __u32 *priority; __u32 *mark; - __u16 *queue_mapping; + __u16 *queue_mapping, *ptype; struct tc_skbedit *p = NULL; if (arg == NULL) @@ -176,8 +200,22 @@ static int print_skbedit(struct action_util *au, FILE *f, struct rtattr *arg) mark = RTA_DATA(tb[TCA_SKBEDIT_MARK]); fprintf(f, " mark %d", *mark); } + if (tb[TCA_SKBEDIT_PTYPE] != NULL) { + ptype = RTA_DATA(tb[TCA_SKBEDIT_PTYPE]); + if (*ptype == PACKET_HOST) + fprintf(f, " ptype host"); + else if (*ptype == PACKET_BROADCAST) + fprintf(f, " ptype broadcast"); + else if (*ptype == PACKET_MULTICAST) + fprintf(f, " ptype multicast"); + else if (*ptype == PACKET_OTHERHOST) + fprintf(f, " ptype otherhost"); + else + fprintf(f, " ptype %d", *ptype); + } - fprintf(f, "\n\t index %d ref %d bind %d", p->index, p->refcnt, p->bindcnt); + fprintf(f, "\n\t index %d ref %d bind %d", + p->index, p->refcnt, p->bindcnt); if (show_stats) { if (tb[TCA_SKBEDIT_TM]) {