Merge ssh://gitolite.kernel.org/pub/scm/network/iproute2/iproute2-next

This commit is contained in:
Stephen Hemminger
2025-01-21 07:03:48 -08:00
19 changed files with 377 additions and 17 deletions

View File

@@ -68,6 +68,8 @@ enum {
FRA_SPORT_RANGE, /* sport */
FRA_DPORT_RANGE, /* dport */
FRA_DSCP, /* dscp */
FRA_FLOWLABEL, /* flowlabel */
FRA_FLOWLABEL_MASK, /* flowlabel mask */
__FRA_MAX
};

View File

@@ -1313,6 +1313,8 @@ enum {
IFLA_NETKIT_MODE,
IFLA_NETKIT_SCRUB,
IFLA_NETKIT_PEER_SCRUB,
IFLA_NETKIT_HEADROOM,
IFLA_NETKIT_TAILROOM,
__IFLA_NETKIT_MAX,
};
#define IFLA_NETKIT_MAX (__IFLA_NETKIT_MAX - 1)
@@ -1392,6 +1394,7 @@ enum {
IFLA_VXLAN_VNIFILTER, /* only applicable with COLLECT_METADATA mode */
IFLA_VXLAN_LOCALBYPASS,
IFLA_VXLAN_LABEL_POLICY, /* IPv6 flow label policy; ifla_vxlan_label_policy */
IFLA_VXLAN_RESERVED_BITS,
__IFLA_VXLAN_MAX
};
#define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1)

View File

@@ -79,6 +79,8 @@ enum {
#define IPPROTO_MPLS IPPROTO_MPLS
IPPROTO_ETHERNET = 143, /* Ethernet-within-IPv6 Encapsulation */
#define IPPROTO_ETHERNET IPPROTO_ETHERNET
IPPROTO_AGGFRAG = 144, /* AGGFRAG in ESP (RFC 9347) */
#define IPPROTO_AGGFRAG IPPROTO_AGGFRAG
IPPROTO_RAW = 255, /* Raw IP packets */
#define IPPROTO_RAW IPPROTO_RAW
IPPROTO_SMC = 256, /* Shared Memory Communications */

View File

@@ -137,6 +137,22 @@ struct ip_beet_phdr {
__u8 reserved;
};
struct ip_iptfs_hdr {
__u8 subtype; /* 0*: basic, 1: CC */
__u8 flags;
__be16 block_offset;
};
struct ip_iptfs_cc_hdr {
__u8 subtype; /* 0: basic, 1*: CC */
__u8 flags;
__be16 block_offset;
__be32 loss_rate;
__be64 rtt_adelay_xdelay;
__be32 tval;
__be32 techo;
};
/* index values for the variables in ipv4_devconf */
enum
{

View File

@@ -14,7 +14,8 @@ enum {
IPSEC_MODE_ANY = 0, /* We do not support this for SA */
IPSEC_MODE_TRANSPORT = 1,
IPSEC_MODE_TUNNEL = 2,
IPSEC_MODE_BEET = 3
IPSEC_MODE_BEET = 3,
IPSEC_MODE_IPTFS = 4
};
enum {

View File

@@ -93,10 +93,18 @@ enum {
RTM_NEWPREFIX = 52,
#define RTM_NEWPREFIX RTM_NEWPREFIX
RTM_GETMULTICAST = 58,
RTM_NEWMULTICAST = 56,
#define RTM_NEWMULTICAST RTM_NEWMULTICAST
RTM_DELMULTICAST,
#define RTM_DELMULTICAST RTM_DELMULTICAST
RTM_GETMULTICAST,
#define RTM_GETMULTICAST RTM_GETMULTICAST
RTM_GETANYCAST = 62,
RTM_NEWANYCAST = 60,
#define RTM_NEWANYCAST RTM_NEWANYCAST
RTM_DELANYCAST,
#define RTM_DELANYCAST RTM_DELANYCAST
RTM_GETANYCAST,
#define RTM_GETANYCAST RTM_GETANYCAST
RTM_NEWNEIGHTBL = 64,
@@ -389,6 +397,7 @@ enum rtattr_type_t {
RTA_SPORT,
RTA_DPORT,
RTA_NH_ID,
RTA_FLOWLABEL,
__RTA_MAX
};
@@ -772,6 +781,12 @@ enum rtnetlink_groups {
#define RTNLGRP_TUNNEL RTNLGRP_TUNNEL
RTNLGRP_STATS,
#define RTNLGRP_STATS RTNLGRP_STATS
RTNLGRP_IPV4_MCADDR,
#define RTNLGRP_IPV4_MCADDR RTNLGRP_IPV4_MCADDR
RTNLGRP_IPV6_MCADDR,
#define RTNLGRP_IPV6_MCADDR RTNLGRP_IPV6_MCADDR
RTNLGRP_IPV6_ACADDR,
#define RTNLGRP_IPV6_ACADDR RTNLGRP_IPV6_ACADDR
__RTNLGRP_MAX
};
#define RTNLGRP_MAX (__RTNLGRP_MAX - 1)

View File

@@ -186,6 +186,7 @@ enum
LINUX_MIB_TIMEWAITKILLED, /* TimeWaitKilled */
LINUX_MIB_PAWSACTIVEREJECTED, /* PAWSActiveRejected */
LINUX_MIB_PAWSESTABREJECTED, /* PAWSEstabRejected */
LINUX_MIB_PAWS_OLD_ACK, /* PAWSOldAck */
LINUX_MIB_DELAYEDACKS, /* DelayedACKs */
LINUX_MIB_DELAYEDACKLOCKED, /* DelayedACKLocked */
LINUX_MIB_DELAYEDACKLOST, /* DelayedACKLost */
@@ -339,6 +340,8 @@ enum
LINUX_MIB_XFRMACQUIREERROR, /* XfrmAcquireError */
LINUX_MIB_XFRMOUTSTATEDIRERROR, /* XfrmOutStateDirError */
LINUX_MIB_XFRMINSTATEDIRERROR, /* XfrmInStateDirError */
LINUX_MIB_XFRMINIPTFSERROR, /* XfrmInIptfsError */
LINUX_MIB_XFRMOUTNOQSPACE, /* XfrmOutNoQueueSpace */
__LINUX_MIB_XFRMMAX
};
@@ -358,6 +361,11 @@ enum
LINUX_MIB_TLSRXDEVICERESYNC, /* TlsRxDeviceResync */
LINUX_MIB_TLSDECRYPTRETRY, /* TlsDecryptRetry */
LINUX_MIB_TLSRXNOPADVIOL, /* TlsRxNoPadViolation */
LINUX_MIB_TLSRXREKEYOK, /* TlsRxRekeyOk */
LINUX_MIB_TLSRXREKEYERROR, /* TlsRxRekeyError */
LINUX_MIB_TLSTXREKEYOK, /* TlsTxRekeyOk */
LINUX_MIB_TLSTXREKEYERROR, /* TlsTxRekeyError */
LINUX_MIB_TLSRXREKEYRECEIVED, /* TlsRxRekeyReceived */
__LINUX_MIB_TLSMAX
};

View File

@@ -158,7 +158,8 @@ enum {
#define XFRM_MODE_ROUTEOPTIMIZATION 2
#define XFRM_MODE_IN_TRIGGER 3
#define XFRM_MODE_BEET 4
#define XFRM_MODE_MAX 5
#define XFRM_MODE_IPTFS 5
#define XFRM_MODE_MAX 6
/* Netlink configuration messages. */
enum {
@@ -323,6 +324,12 @@ enum xfrm_attr_type_t {
XFRMA_SA_DIR, /* __u8 */
XFRMA_NAT_KEEPALIVE_INTERVAL, /* __u32 in seconds for NAT keepalive */
XFRMA_SA_PCPU, /* __u32 */
XFRMA_IPTFS_DROP_TIME, /* __u32 in: usec to wait for next seq */
XFRMA_IPTFS_REORDER_WINDOW, /* __u16 in: reorder window size (pkts) */
XFRMA_IPTFS_DONT_FRAG, /* out: don't use fragmentation */
XFRMA_IPTFS_INIT_DELAY, /* __u32 out: initial packet wait delay (usec) */
XFRMA_IPTFS_MAX_QSIZE, /* __u32 out: max ingress queue size (octets) */
XFRMA_IPTFS_PKT_SIZE, /* __u32 out: size of outer packet, 0 for PMTU */
__XFRMA_MAX
#define XFRMA_OUTPUT_MARK XFRMA_SET_MARK /* Compatibility */

View File

@@ -1504,7 +1504,12 @@ int print_addrinfo(struct nlmsghdr *n, void *arg)
SPRINT_BUF(b1);
if (n->nlmsg_type != RTM_NEWADDR && n->nlmsg_type != RTM_DELADDR)
if (n->nlmsg_type != RTM_NEWADDR &&
n->nlmsg_type != RTM_DELADDR &&
n->nlmsg_type != RTM_NEWMULTICAST &&
n->nlmsg_type != RTM_DELMULTICAST &&
n->nlmsg_type != RTM_NEWANYCAST &&
n->nlmsg_type != RTM_DELANYCAST)
return 0;
len -= NLMSG_LENGTH(sizeof(*ifa));
if (len < 0) {
@@ -1564,7 +1569,9 @@ int print_addrinfo(struct nlmsghdr *n, void *arg)
print_headers(fp, "[ADDR]");
if (n->nlmsg_type == RTM_DELADDR)
if (n->nlmsg_type == RTM_DELADDR ||
n->nlmsg_type == RTM_DELMULTICAST ||
n->nlmsg_type == RTM_DELANYCAST)
print_bool(PRINT_ANY, "deleted", "Deleted ", true);
if (!brief) {
@@ -1639,6 +1646,16 @@ int print_addrinfo(struct nlmsghdr *n, void *arg)
rta_tb[IFA_ANYCAST]));
}
if (rta_tb[IFA_MULTICAST]) {
print_string(PRINT_FP, NULL, "%s ", "mcast");
print_color_string(PRINT_ANY,
ifa_family_color(ifa->ifa_family),
"multicast",
"%s ",
format_host_rta(ifa->ifa_family,
rta_tb[IFA_MULTICAST]));
}
print_string(PRINT_ANY,
"scope",
"scope %s ",

View File

@@ -16,6 +16,12 @@ static void print_explain(FILE *f)
{
fprintf(f,
"Usage: ... rmnet mux_id MUXID\n"
" [ ingress-deaggregation { on | off } ]\n"
" [ ingress-commands { on | off } ]\n"
" [ ingress-mapv4-checksum { on | off } ]\n"
" [ egress-mapv4-checksum { on | off } ]\n"
" [ ingress-mapv5-checksum { on | off } ]\n"
" [ egress-mapv5-checksum { on | off } ]\n"
"\n"
"MUXID := 1-254\n"
);
@@ -29,15 +35,95 @@ static void explain(void)
static int rmnet_parse_opt(struct link_util *lu, int argc, char **argv,
struct nlmsghdr *n)
{
struct ifla_rmnet_flags flags = { 0 };
__u16 mux_id;
int ret;
while (argc > 0) {
if (matches(*argv, "mux_id") == 0) {
if (strcmp(*argv, "mux_id") == 0) {
NEXT_ARG();
if (get_u16(&mux_id, *argv, 0))
invarg("mux_id is invalid", *argv);
addattr16(n, 1024, IFLA_RMNET_MUX_ID, mux_id);
} else if (matches(*argv, "help") == 0) {
} else if (strcmp(*argv, "ingress-deaggregation") == 0) {
bool deaggregation;
NEXT_ARG();
deaggregation = parse_on_off("ingress-deaggregation", *argv, &ret);
if (ret)
return ret;
flags.mask |= RMNET_FLAGS_INGRESS_DEAGGREGATION;
if (deaggregation)
flags.flags |= RMNET_FLAGS_INGRESS_DEAGGREGATION;
else
flags.flags &= ~RMNET_FLAGS_INGRESS_DEAGGREGATION;
} else if (strcmp(*argv, "ingress-commands") == 0) {
bool commands;
NEXT_ARG();
commands = parse_on_off("ingress-commands", *argv, &ret);
if (ret)
return ret;
flags.mask |= RMNET_FLAGS_INGRESS_MAP_COMMANDS;
if (commands)
flags.flags |= RMNET_FLAGS_INGRESS_MAP_COMMANDS;
else
flags.flags &= ~RMNET_FLAGS_INGRESS_MAP_COMMANDS;
} else if (strcmp(*argv, "ingress-mapv4-checksum") == 0) {
bool mapv4_checksum;
NEXT_ARG();
mapv4_checksum = parse_on_off("ingress-mapv4-checksum", *argv, &ret);
if (ret)
return ret;
flags.mask |= RMNET_FLAGS_INGRESS_MAP_CKSUMV4;
if (mapv4_checksum)
flags.flags |= RMNET_FLAGS_INGRESS_MAP_CKSUMV4;
else
flags.flags &= ~RMNET_FLAGS_INGRESS_MAP_CKSUMV4;
} else if (strcmp(*argv, "egress-mapv4-checksum") == 0) {
bool mapv4_checksum;
NEXT_ARG();
mapv4_checksum = parse_on_off("egress-mapv4-checksum", *argv, &ret);
if (ret)
return ret;
flags.mask |= RMNET_FLAGS_EGRESS_MAP_CKSUMV4;
if (mapv4_checksum)
flags.flags |= RMNET_FLAGS_EGRESS_MAP_CKSUMV4;
else
flags.flags &= ~RMNET_FLAGS_EGRESS_MAP_CKSUMV4;
} else if (strcmp(*argv, "ingress-mapv5-checksum") == 0) {
bool mapv5_checksum;
NEXT_ARG();
mapv5_checksum = parse_on_off("ingress-mapv5-checksum", *argv, &ret);
if (ret)
return ret;
flags.mask |= RMNET_FLAGS_INGRESS_MAP_CKSUMV5;
if (mapv5_checksum)
flags.flags |= RMNET_FLAGS_INGRESS_MAP_CKSUMV5;
else
flags.flags &= ~RMNET_FLAGS_INGRESS_MAP_CKSUMV5;
} else if (strcmp(*argv, "egress-mapv5-checksum") == 0) {
bool mapv5_checksum;
NEXT_ARG();
mapv5_checksum = parse_on_off("egress-mapv5-checksum", *argv, &ret);
if (ret)
return ret;
flags.mask |= RMNET_FLAGS_EGRESS_MAP_CKSUMV5;
if (mapv5_checksum)
flags.flags |= RMNET_FLAGS_EGRESS_MAP_CKSUMV5;
else
flags.flags &= ~RMNET_FLAGS_EGRESS_MAP_CKSUMV5;
} else if (strcmp(*argv, "help") == 0) {
explain();
return -1;
} else {
@@ -48,11 +134,34 @@ static int rmnet_parse_opt(struct link_util *lu, int argc, char **argv,
argc--, argv++;
}
if (flags.mask)
addattr_l(n, 1024, IFLA_RMNET_FLAGS, &flags, sizeof(flags));
return 0;
}
static void rmnet_print_flags(FILE *fp, __u32 flags)
{
open_json_array(PRINT_ANY, is_json_context() ? "flags" : "<");
#define _PF(f) if (flags & RMNET_FLAGS_##f) { \
flags &= ~RMNET_FLAGS_##f; \
print_string(PRINT_ANY, NULL, flags ? "%s," : "%s", #f); \
}
_PF(INGRESS_DEAGGREGATION);
_PF(INGRESS_MAP_COMMANDS);
_PF(INGRESS_MAP_CKSUMV4);
_PF(EGRESS_MAP_CKSUMV4);
_PF(INGRESS_MAP_CKSUMV5);
_PF(EGRESS_MAP_CKSUMV5);
#undef _PF
if (flags)
print_hex(PRINT_ANY, NULL, "%x", flags);
close_json_array(PRINT_ANY, "> ");
}
static void rmnet_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
{
struct ifla_rmnet_flags *flags;
if (!tb)
return;
@@ -64,6 +173,13 @@ static void rmnet_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
"mux_id",
"mux_id %u ",
rta_getattr_u16(tb[IFLA_RMNET_MUX_ID]));
if (tb[IFLA_RMNET_FLAGS]) {
if (RTA_PAYLOAD(tb[IFLA_RMNET_FLAGS]) < sizeof(*flags))
return;
flags = RTA_DATA(tb[IFLA_RMNET_FLAGS]);
rmnet_print_flags(f, flags->flags);
}
}
static void rmnet_print_help(struct link_util *lu, int argc, char **argv,

View File

@@ -52,6 +52,7 @@ static void print_explain(FILE *f)
" [ dev PHYS_DEV ]\n"
" [ dstport PORT ]\n"
" [ srcport MIN MAX ]\n"
" [ reserved_bits VALUE ]\n"
" [ [no]learning ]\n"
" [ [no]proxy ]\n"
" [ [no]rsc ]\n"
@@ -337,6 +338,17 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv,
check_duparg(&attrs, IFLA_VXLAN_LOCALBYPASS,
*argv, *argv);
addattr8(n, 1024, IFLA_VXLAN_LOCALBYPASS, 0);
} else if (strcmp(*argv, "reserved_bits") == 0) {
NEXT_ARG();
__be64 bits;
check_duparg(&attrs, IFLA_VXLAN_RESERVED_BITS,
*argv, *argv);
if (get_be64(&bits, *argv, 0))
invarg("reserved_bits", *argv);
addattr_l(n, 1024, IFLA_VXLAN_RESERVED_BITS,
&bits, sizeof(bits));
} else if (!matches(*argv, "external")) {
check_duparg(&attrs, IFLA_VXLAN_COLLECT_METADATA,
*argv, *argv);
@@ -601,6 +613,14 @@ static void vxlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
((maxaddr = rta_getattr_u32(tb[IFLA_VXLAN_LIMIT])) != 0))
print_uint(PRINT_ANY, "limit", "maxaddr %u ", maxaddr);
if (tb[IFLA_VXLAN_RESERVED_BITS]) {
__be64 reserved_bits =
rta_getattr_u64(tb[IFLA_VXLAN_RESERVED_BITS]);
print_0xhex(PRINT_ANY, "reserved_bits",
"reserved_bits %#llx ", ntohll(reserved_bits));
}
if (tb[IFLA_VXLAN_GBP])
print_null(PRINT_ANY, "gbp", "gbp ", NULL);
if (tb[IFLA_VXLAN_GPE])

View File

@@ -30,8 +30,8 @@ static void usage(void)
fprintf(stderr,
"Usage: ip monitor [ all | OBJECTS ] [ FILE ] [ label ] [ all-nsid ]\n"
" [ dev DEVICE ]\n"
"OBJECTS := address | link | mroute | neigh | netconf |\n"
" nexthop | nsid | prefix | route | rule | stats\n"
"OBJECTS := address | link | mroute | maddress | acaddress | neigh |\n"
" netconf | nexthop | nsid | prefix | route | rule | stats\n"
"FILE := file FILENAME\n");
exit(-1);
}
@@ -152,6 +152,13 @@ static int accept_msg(struct rtnl_ctrl_data *ctrl,
ipstats_print(n, arg);
return 0;
case RTM_DELMULTICAST:
case RTM_NEWMULTICAST:
case RTM_DELANYCAST:
case RTM_NEWANYCAST:
print_addrinfo(n, arg);
return 0;
case NLMSG_ERROR:
case NLMSG_NOOP:
case NLMSG_DONE:
@@ -178,6 +185,8 @@ static int accept_msg(struct rtnl_ctrl_data *ctrl,
#define IPMON_LRULE BIT(8)
#define IPMON_LNSID BIT(9)
#define IPMON_LNEXTHOP BIT(10)
#define IPMON_LMADDR BIT(11)
#define IPMON_LACADDR BIT(12)
#define IPMON_L_ALL (~0)
@@ -202,6 +211,10 @@ int do_ipmonitor(int argc, char **argv)
lmask |= IPMON_LLINK;
} else if (matches(*argv, "address") == 0) {
lmask |= IPMON_LADDR;
} else if (matches(*argv, "maddress") == 0) {
lmask |= IPMON_LMADDR;
} else if (strcmp(*argv, "acaddress") == 0) {
lmask |= IPMON_LACADDR;
} else if (matches(*argv, "route") == 0) {
lmask |= IPMON_LROUTE;
} else if (matches(*argv, "mroute") == 0) {
@@ -326,6 +339,30 @@ int do_ipmonitor(int argc, char **argv)
exit(1);
}
if (lmask & IPMON_LMADDR) {
if ((!preferred_family || preferred_family == AF_INET) &&
rtnl_add_nl_group(&rth, RTNLGRP_IPV4_MCADDR) < 0) {
fprintf(stderr,
"Failed to add ipv4 mcaddr group to list\n");
exit(1);
}
if ((!preferred_family || preferred_family == AF_INET6) &&
rtnl_add_nl_group(&rth, RTNLGRP_IPV6_MCADDR) < 0) {
fprintf(stderr,
"Failed to add ipv6 mcaddr group to list\n");
exit(1);
}
}
if (lmask & IPMON_LACADDR) {
if ((!preferred_family || preferred_family == AF_INET6) &&
rtnl_add_nl_group(&rth, RTNLGRP_IPV6_ACADDR) < 0) {
fprintf(stderr,
"Failed to add ipv6 acaddr group to list\n");
exit(1);
}
}
if (listen_all_nsid && rtnl_listen_all_nsid(&rth) < 0)
exit(1);

View File

@@ -67,7 +67,7 @@ static void usage(void)
" [ mark NUMBER ] [ vrf NAME ]\n"
" [ uid NUMBER ] [ ipproto PROTOCOL ]\n"
" [ sport NUMBER ] [ dport NUMBER ]\n"
" [ as ADDRESS ]\n"
" [ as ADDRESS ] [ flowlabel FLOWLABEL ]\n"
" ip route { add | del | change | append | replace } ROUTE\n"
"SELECTOR := [ root PREFIX ] [ match PREFIX ] [ exact PREFIX ]\n"
" [ table TABLE_ID ] [ vrf NAME ] [ proto RTPROTO ]\n"
@@ -2129,6 +2129,14 @@ static int iproute_get(int argc, char **argv)
invarg("Invalid \"ipproto\" value\n",
*argv);
addattr8(&req.n, sizeof(req), RTA_IP_PROTO, ipproto);
} else if (strcmp(*argv, "flowlabel") == 0) {
__be32 flowlabel;
NEXT_ARG();
if (get_be32(&flowlabel, *argv, 0))
invarg("invalid flowlabel", *argv);
addattr32(&req.n, sizeof(req), RTA_FLOWLABEL,
flowlabel);
} else {
inet_prefix addr;

View File

@@ -46,7 +46,7 @@ static void usage(void)
" [ ipproto PROTOCOL ]\n"
" [ sport [ NUMBER | NUMBER-NUMBER ]\n"
" [ dport [ NUMBER | NUMBER-NUMBER ] ]\n"
" [ dscp DSCP ]\n"
" [ dscp DSCP ] [ flowlabel FLOWLABEL[/MASK] ]\n"
"ACTION := [ table TABLE_ID ]\n"
" [ protocol PROTO ]\n"
" [ nat ADDRESS ]\n"
@@ -69,6 +69,7 @@ static struct
unsigned int pref, prefmask;
unsigned int fwmark, fwmask;
unsigned int dscp, dscpmask;
__u32 flowlabel, flowlabel_mask;
uint64_t tun_id;
char iif[IFNAMSIZ];
char oif[IFNAMSIZ];
@@ -232,6 +233,19 @@ static bool filter_nlmsg(struct nlmsghdr *n, struct rtattr **tb, int host_len)
}
}
if (filter.flowlabel_mask) {
__u32 flowlabel, flowlabel_mask;
if (!tb[FRA_FLOWLABEL] || !tb[FRA_FLOWLABEL_MASK])
return false;
flowlabel = rta_getattr_be32(tb[FRA_FLOWLABEL]);
flowlabel_mask = rta_getattr_be32(tb[FRA_FLOWLABEL_MASK]);
if (filter.flowlabel != flowlabel ||
filter.flowlabel_mask != flowlabel_mask)
return false;
}
table = frh_get_table(frh, tb);
if (filter.tb > 0 && filter.tb ^ table)
return false;
@@ -489,6 +503,23 @@ int print_rule(struct nlmsghdr *n, void *arg)
rtnl_dscp_n2a(dscp, b1, sizeof(b1)));
}
/* The kernel will either provide both attributes, or none */
if (tb[FRA_FLOWLABEL] && tb[FRA_FLOWLABEL_MASK]) {
__u32 flowlabel, flowlabel_mask;
flowlabel = rta_getattr_be32(tb[FRA_FLOWLABEL]);
flowlabel_mask = rta_getattr_be32(tb[FRA_FLOWLABEL_MASK]);
print_0xhex(PRINT_ANY, "flowlabel", " flowlabel %#llx",
flowlabel);
if (flowlabel_mask == LABEL_MAX_MASK)
print_0xhex(PRINT_JSON, "flowlabel_mask", NULL,
flowlabel_mask);
else
print_0xhex(PRINT_ANY, "flowlabel_mask", "/%#llx",
flowlabel_mask);
}
print_string(PRINT_FP, NULL, "\n", "");
close_json_object();
fflush(fp);
@@ -569,6 +600,24 @@ static int flush_rule(struct nlmsghdr *n, void *arg)
return 0;
}
static void iprule_flowlabel_parse(char *arg, __u32 *flowlabel,
__u32 *flowlabel_mask)
{
char *slash;
slash = strchr(arg, '/');
if (slash != NULL)
*slash = '\0';
if (get_u32(flowlabel, arg, 0))
invarg("invalid flowlabel", arg);
if (slash) {
if (get_u32(flowlabel_mask, slash + 1, 0))
invarg("invalid flowlabel mask", slash + 1);
} else {
*flowlabel_mask = LABEL_MAX_MASK;
}
}
static int iprule_list_flush_or_save(int argc, char **argv, int action)
{
rtnl_filter_t filter_fn;
@@ -726,6 +775,11 @@ static int iprule_list_flush_or_save(int argc, char **argv, int action)
invarg("invalid dscp\n", *argv);
filter.dscp = dscp;
filter.dscpmask = 1;
} else if (strcmp(*argv, "flowlabel") == 0) {
NEXT_ARG();
iprule_flowlabel_parse(*argv, &filter.flowlabel,
&filter.flowlabel_mask);
} else {
if (matches(*argv, "dst") == 0 ||
matches(*argv, "to") == 0) {
@@ -1011,6 +1065,16 @@ static int iprule_modify(int cmd, int argc, char **argv)
if (rtnl_dscp_a2n(&dscp, *argv))
invarg("invalid dscp\n", *argv);
addattr8(&req.n, sizeof(req), FRA_DSCP, dscp);
} else if (strcmp(*argv, "flowlabel") == 0) {
__u32 flowlabel, flowlabel_mask;
NEXT_ARG();
iprule_flowlabel_parse(*argv, &flowlabel,
&flowlabel_mask);
addattr32(&req.n, sizeof(req), FRA_FLOWLABEL,
htonl(flowlabel));
addattr32(&req.n, sizeof(req), FRA_FLOWLABEL_MASK,
htonl(flowlabel_mask));
} else {
int type;

View File

@@ -632,6 +632,8 @@ the following additional arguments are supported:
] [
.BI srcport " MIN MAX "
] [
.BI reserved_bits " VALUE "
] [
.RB [ no ] learning
] [
.RB [ no ] proxy
@@ -725,6 +727,13 @@ bit is not set.
- specifies the range of port numbers to use as UDP
source ports to communicate to the remote VXLAN tunnel endpoint.
.sp
.BI reserved_bits " VALUE "
- by default the kernel rejects packets that have bits set outside of the fields
required by the features enabled on the VXLAN netdevice. \fBreserved_bits\fR is
a 64-bit quantity specifying which bits it should be possible to set in a VXLAN
header. Each bit set in the value is a tolerated bit set in a packet.
.sp
.RB [ no ] learning
- specifies if unknown source link layer addresses and IP addresses

View File

@@ -54,8 +54,9 @@ command is the first in the command line and then the object list follows:
.I OBJECT-LIST
is the list of object types that we want to monitor.
It may contain
.BR link ", " address ", " route ", " mroute ", " prefix ", "
.BR neigh ", " netconf ", " rule ", " stats ", " nsid " and " nexthop "."
.BR link ", " address ", " route ", " mroute ", " maddress ", " acaddress ", "
.BR prefix ", "neigh ", " netconf ", " rule ", " stats ", " nsid " and "
.BR nexthop "."
If no
.B file
argument is given,

View File

@@ -47,7 +47,9 @@ ip-route \- routing table management
.B dport
.IR NUMBER " ] ["
.B as
.IR ADDRESS " ]"
.IR ADDRESS " ] ["
.B flowlabel
.IR FLOWLABEL " ]
.ti -8
.BR "ip route" " { " add " | " del " | " change " | " append " | "\
@@ -1316,6 +1318,10 @@ was given, relookup the route with the source set to the preferred
address received from the first lookup.
If policy routing is used, it may be a different route.
.TP
.BI flowlabel " FLOWLABEL"
ipv6 flow label as seen by the route lookup
.P
Note that this operation is not equivalent to
.BR "ip route show" .

View File

@@ -58,7 +58,9 @@ ip-rule \- routing policy database management
.IR NUMBER " | "
.IR NUMBER "-" NUMBER " ] ] [ "
.B tun_id
.IR TUN_ID " ]"
.IR TUN_ID " ] [ "
.B flowlabel
.IR FLOWLABEL\fR[\fB/\fIMASK "] ]"
.BR
@@ -322,6 +324,10 @@ In the last case the router does not translate the packets, but
masquerades them to this address.
Using map-to instead of nat means the same thing.
.TP
.BI flowlabel " FLOWLABEL\fR[\fB/\fIMASK\fR]"
select the IPv6 flow label to match with an optional mask.
.B Warning:
Changes to the RPDB made with these commands do not become active
immediately. It is assumed that after a script finishes a batch of

View File

@@ -32,7 +32,8 @@ static void explain(void)
" [ timer_slack TIME]\n"
" [ ce_threshold TIME ]\n"
" [ horizon TIME ]\n"
" [ horizon_{cap|drop} ]\n");
" [ horizon_{cap|drop} ]\n"
" [ offload_horizon TIME ]\n");
}
static unsigned int ilog2(unsigned int val)
@@ -64,6 +65,7 @@ static int fq_parse_opt(const struct qdisc_util *qu, int argc, char **argv,
unsigned int ce_threshold;
unsigned int timer_slack;
unsigned int horizon;
unsigned int offload_horizon;
__u8 horizon_drop = 255;
bool set_plimit = false;
bool set_flow_plimit = false;
@@ -79,6 +81,7 @@ static int fq_parse_opt(const struct qdisc_util *qu, int argc, char **argv,
bool set_horizon = false;
bool set_priomap = false;
bool set_weights = false;
bool set_offload_horizon = false;
int weights[FQ_BANDS];
int pacing = -1;
struct rtattr *tail;
@@ -155,6 +158,13 @@ static int fq_parse_opt(const struct qdisc_util *qu, int argc, char **argv,
return -1;
}
set_horizon = true;
} else if (strcmp(*argv, "offload_horizon") == 0) {
NEXT_ARG();
if (get_time(&offload_horizon, *argv)) {
fprintf(stderr, "Illegal \"offload_horizon\"\n");
return -1;
}
set_offload_horizon = true;
} else if (strcmp(*argv, "defrate") == 0) {
NEXT_ARG();
if (strchr(*argv, '%')) {
@@ -333,6 +343,9 @@ static int fq_parse_opt(const struct qdisc_util *qu, int argc, char **argv,
if (set_weights)
addattr_l(n, 1024, TCA_FQ_WEIGHTS,
weights, sizeof(weights));
if (set_offload_horizon)
addattr_l(n, 1024, TCA_FQ_OFFLOAD_HORIZON,
&offload_horizon, sizeof(offload_horizon));
addattr_nest_end(n, tail);
return 0;
}
@@ -348,6 +361,7 @@ static int fq_print_opt(const struct qdisc_util *qu, FILE *f, struct rtattr *opt
unsigned int orphan_mask;
unsigned int ce_threshold;
unsigned int timer_slack;
__u32 offload_horizon;
unsigned int horizon;
__u8 horizon_drop;
@@ -487,6 +501,14 @@ static int fq_print_opt(const struct qdisc_util *qu, FILE *f, struct rtattr *opt
print_null(PRINT_ANY, "horizon_drop", "horizon_drop ", NULL);
}
if (tb[TCA_FQ_OFFLOAD_HORIZON] &&
RTA_PAYLOAD(tb[TCA_FQ_OFFLOAD_HORIZON]) >= sizeof(__u32)) {
offload_horizon = rta_getattr_u32(tb[TCA_FQ_OFFLOAD_HORIZON]);
print_uint(PRINT_JSON, "offload_horizon", NULL, offload_horizon);
print_string(PRINT_FP, NULL, "offload_horizon %s ",
sprint_time(offload_horizon, b1));
}
return 0;
}