Merge branch 'master' into net-next
This commit is contained in:
commit
328374dcfe
|
|
@ -28,6 +28,10 @@
|
|||
|
||||
#define ESWITCH_MODE_LEGACY "legacy"
|
||||
#define ESWITCH_MODE_SWITCHDEV "switchdev"
|
||||
#define ESWITCH_INLINE_MODE_NONE "none"
|
||||
#define ESWITCH_INLINE_MODE_LINK "link"
|
||||
#define ESWITCH_INLINE_MODE_NETWORK "network"
|
||||
#define ESWITCH_INLINE_MODE_TRANSPORT "transport"
|
||||
|
||||
#define pr_err(args...) fprintf(stderr, ##args)
|
||||
#define pr_out(args...) fprintf(stdout, ##args)
|
||||
|
|
@ -132,6 +136,7 @@ static void ifname_map_free(struct ifname_map *ifname_map)
|
|||
#define DL_OPT_SB_TH BIT(9)
|
||||
#define DL_OPT_SB_TC BIT(10)
|
||||
#define DL_OPT_ESWITCH_MODE BIT(11)
|
||||
#define DL_OPT_ESWITCH_INLINE_MODE BIT(12)
|
||||
|
||||
struct dl_opts {
|
||||
uint32_t present; /* flags of present items */
|
||||
|
|
@ -148,6 +153,7 @@ struct dl_opts {
|
|||
uint32_t sb_threshold;
|
||||
uint16_t sb_tc_index;
|
||||
enum devlink_eswitch_mode eswitch_mode;
|
||||
enum devlink_eswitch_inline_mode eswitch_inline_mode;
|
||||
};
|
||||
|
||||
struct dl {
|
||||
|
|
@ -305,6 +311,9 @@ static int attr_cb(const struct nlattr *attr, void *data)
|
|||
if (type == DEVLINK_ATTR_ESWITCH_MODE &&
|
||||
mnl_attr_validate(attr, MNL_TYPE_U16) < 0)
|
||||
return MNL_CB_ERROR;
|
||||
if (type == DEVLINK_ATTR_ESWITCH_INLINE_MODE &&
|
||||
mnl_attr_validate(attr, MNL_TYPE_U8) < 0)
|
||||
return MNL_CB_ERROR;
|
||||
tb[type] = attr;
|
||||
return MNL_CB_OK;
|
||||
}
|
||||
|
|
@ -682,6 +691,24 @@ static int eswitch_mode_get(const char *typestr,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int eswitch_inline_mode_get(const char *typestr,
|
||||
enum devlink_eswitch_inline_mode *p_mode)
|
||||
{
|
||||
if (strcmp(typestr, ESWITCH_INLINE_MODE_NONE) == 0) {
|
||||
*p_mode = DEVLINK_ESWITCH_INLINE_MODE_NONE;
|
||||
} else if (strcmp(typestr, ESWITCH_INLINE_MODE_LINK) == 0) {
|
||||
*p_mode = DEVLINK_ESWITCH_INLINE_MODE_LINK;
|
||||
} else if (strcmp(typestr, ESWITCH_INLINE_MODE_NETWORK) == 0) {
|
||||
*p_mode = DEVLINK_ESWITCH_INLINE_MODE_NETWORK;
|
||||
} else if (strcmp(typestr, ESWITCH_INLINE_MODE_TRANSPORT) == 0) {
|
||||
*p_mode = DEVLINK_ESWITCH_INLINE_MODE_TRANSPORT;
|
||||
} else {
|
||||
pr_err("Unknown eswitch inline mode \"%s\"\n", typestr);
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dl_argv_parse(struct dl *dl, uint32_t o_required,
|
||||
uint32_t o_optional)
|
||||
{
|
||||
|
|
@ -803,6 +830,19 @@ static int dl_argv_parse(struct dl *dl, uint32_t o_required,
|
|||
if (err)
|
||||
return err;
|
||||
o_found |= DL_OPT_ESWITCH_MODE;
|
||||
} else if (dl_argv_match(dl, "inline-mode") &&
|
||||
(o_all & DL_OPT_ESWITCH_INLINE_MODE)) {
|
||||
const char *typestr;
|
||||
|
||||
dl_arg_inc(dl);
|
||||
err = dl_argv_str(dl, &typestr);
|
||||
if (err)
|
||||
return err;
|
||||
err = eswitch_inline_mode_get(
|
||||
typestr, &opts->eswitch_inline_mode);
|
||||
if (err)
|
||||
return err;
|
||||
o_found |= DL_OPT_ESWITCH_INLINE_MODE;
|
||||
} else {
|
||||
pr_err("Unknown option \"%s\"\n", dl_argv(dl));
|
||||
return -EINVAL;
|
||||
|
|
@ -863,6 +903,12 @@ static int dl_argv_parse(struct dl *dl, uint32_t o_required,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((o_required & DL_OPT_ESWITCH_INLINE_MODE) &&
|
||||
!(o_found & DL_OPT_ESWITCH_INLINE_MODE)) {
|
||||
pr_err("E-Switch inline-mode option expected.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -909,6 +955,9 @@ static void dl_opts_put(struct nlmsghdr *nlh, struct dl *dl)
|
|||
if (opts->present & DL_OPT_ESWITCH_MODE)
|
||||
mnl_attr_put_u16(nlh, DEVLINK_ATTR_ESWITCH_MODE,
|
||||
opts->eswitch_mode);
|
||||
if (opts->present & DL_OPT_ESWITCH_INLINE_MODE)
|
||||
mnl_attr_put_u8(nlh, DEVLINK_ATTR_ESWITCH_INLINE_MODE,
|
||||
opts->eswitch_inline_mode);
|
||||
}
|
||||
|
||||
static int dl_argv_parse_put(struct nlmsghdr *nlh, struct dl *dl,
|
||||
|
|
@ -963,6 +1012,9 @@ static bool dl_dump_filter(struct dl *dl, struct nlattr **tb)
|
|||
static void cmd_dev_help(void)
|
||||
{
|
||||
pr_err("Usage: devlink dev show [ DEV ]\n");
|
||||
pr_err(" devlink dev eswitch set DEV [ mode { legacy | switchdev } ]\n");
|
||||
pr_err(" [ inline-mode { none | link | network | transport } ]\n");
|
||||
pr_err(" devlink dev eswitch show DEV\n");
|
||||
}
|
||||
|
||||
static bool cmp_arr_last_handle(struct dl *dl, const char *bus_name,
|
||||
|
|
@ -1201,6 +1253,22 @@ static const char *eswitch_mode_name(uint32_t mode)
|
|||
}
|
||||
}
|
||||
|
||||
static const char *eswitch_inline_mode_name(uint32_t mode)
|
||||
{
|
||||
switch (mode) {
|
||||
case DEVLINK_ESWITCH_INLINE_MODE_NONE:
|
||||
return ESWITCH_INLINE_MODE_NONE;
|
||||
case DEVLINK_ESWITCH_INLINE_MODE_LINK:
|
||||
return ESWITCH_INLINE_MODE_LINK;
|
||||
case DEVLINK_ESWITCH_INLINE_MODE_NETWORK:
|
||||
return ESWITCH_INLINE_MODE_NETWORK;
|
||||
case DEVLINK_ESWITCH_INLINE_MODE_TRANSPORT:
|
||||
return ESWITCH_INLINE_MODE_TRANSPORT;
|
||||
default:
|
||||
return "<unknown mode>";
|
||||
}
|
||||
}
|
||||
|
||||
static void pr_out_eswitch(struct dl *dl, struct nlattr **tb)
|
||||
{
|
||||
__pr_out_handle_start(dl, tb, true, false);
|
||||
|
|
@ -1208,6 +1276,12 @@ static void pr_out_eswitch(struct dl *dl, struct nlattr **tb)
|
|||
if (tb[DEVLINK_ATTR_ESWITCH_MODE])
|
||||
pr_out_str(dl, "mode",
|
||||
eswitch_mode_name(mnl_attr_get_u16(tb[DEVLINK_ATTR_ESWITCH_MODE])));
|
||||
|
||||
if (tb[DEVLINK_ATTR_ESWITCH_INLINE_MODE])
|
||||
pr_out_str(dl, "inline-mode",
|
||||
eswitch_inline_mode_name(mnl_attr_get_u8(
|
||||
tb[DEVLINK_ATTR_ESWITCH_INLINE_MODE])));
|
||||
|
||||
pr_out_handle_end(dl);
|
||||
}
|
||||
|
||||
|
|
@ -1250,16 +1324,27 @@ static int cmd_dev_eswitch_set(struct dl *dl)
|
|||
nlh = mnlg_msg_prepare(dl->nlg, DEVLINK_CMD_ESWITCH_MODE_SET,
|
||||
NLM_F_REQUEST | NLM_F_ACK);
|
||||
|
||||
err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLE | DL_OPT_ESWITCH_MODE, 0);
|
||||
err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLE,
|
||||
DL_OPT_ESWITCH_MODE |
|
||||
DL_OPT_ESWITCH_INLINE_MODE);
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (dl->opts.present == 1) {
|
||||
pr_err("Need to set at least one option\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
return _mnlg_socket_sndrcv(dl->nlg, nlh, NULL, NULL);
|
||||
}
|
||||
|
||||
static int cmd_dev_eswitch(struct dl *dl)
|
||||
{
|
||||
if (dl_argv_match(dl, "set")) {
|
||||
if (dl_argv_match(dl, "help") || dl_no_arg(dl)) {
|
||||
cmd_dev_help();
|
||||
return 0;
|
||||
} else if (dl_argv_match(dl, "set")) {
|
||||
dl_arg_inc(dl);
|
||||
return cmd_dev_eswitch_set(dl);
|
||||
} else if (dl_argv_match(dl, "show")) {
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -322,10 +322,7 @@ static void print_vfinfo(FILE *fp, struct rtattr *vfinfo)
|
|||
{
|
||||
struct ifla_vf_mac *vf_mac;
|
||||
struct ifla_vf_tx_rate *vf_tx_rate;
|
||||
struct ifla_vf_spoofchk *vf_spoofchk;
|
||||
struct ifla_vf_link_state *vf_linkstate;
|
||||
struct rtattr *vf[IFLA_VF_MAX + 1] = {};
|
||||
struct rtattr *tmp;
|
||||
|
||||
SPRINT_BUF(b1);
|
||||
|
||||
|
|
@ -339,31 +336,6 @@ static void print_vfinfo(FILE *fp, struct rtattr *vfinfo)
|
|||
vf_mac = RTA_DATA(vf[IFLA_VF_MAC]);
|
||||
vf_tx_rate = RTA_DATA(vf[IFLA_VF_TX_RATE]);
|
||||
|
||||
/* Check if the spoof checking vf info type is supported by
|
||||
* this kernel.
|
||||
*/
|
||||
tmp = (struct rtattr *)((char *)vf[IFLA_VF_TX_RATE] +
|
||||
vf[IFLA_VF_TX_RATE]->rta_len);
|
||||
|
||||
if (tmp->rta_type != IFLA_VF_SPOOFCHK)
|
||||
vf_spoofchk = NULL;
|
||||
else
|
||||
vf_spoofchk = RTA_DATA(vf[IFLA_VF_SPOOFCHK]);
|
||||
|
||||
if (vf_spoofchk) {
|
||||
/* Check if the link state vf info type is supported by
|
||||
* this kernel.
|
||||
*/
|
||||
tmp = (struct rtattr *)((char *)vf[IFLA_VF_SPOOFCHK] +
|
||||
vf[IFLA_VF_SPOOFCHK]->rta_len);
|
||||
|
||||
if (tmp->rta_type != IFLA_VF_LINK_STATE)
|
||||
vf_linkstate = NULL;
|
||||
else
|
||||
vf_linkstate = RTA_DATA(vf[IFLA_VF_LINK_STATE]);
|
||||
} else
|
||||
vf_linkstate = NULL;
|
||||
|
||||
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)));
|
||||
|
|
@ -407,14 +379,18 @@ static void print_vfinfo(FILE *fp, struct rtattr *vfinfo)
|
|||
if (vf_rate->min_tx_rate)
|
||||
fprintf(fp, ", min_tx_rate %dMbps", vf_rate->min_tx_rate);
|
||||
}
|
||||
if (vf[IFLA_VF_SPOOFCHK]) {
|
||||
struct ifla_vf_spoofchk *vf_spoofchk =
|
||||
RTA_DATA(vf[IFLA_VF_SPOOFCHK]);
|
||||
|
||||
if (vf_spoofchk && vf_spoofchk->setting != -1) {
|
||||
if (vf_spoofchk->setting)
|
||||
fprintf(fp, ", spoof checking on");
|
||||
else
|
||||
fprintf(fp, ", spoof checking off");
|
||||
if (vf_spoofchk->setting != -1)
|
||||
fprintf(fp, ", spoof checking %s",
|
||||
vf_spoofchk->setting ? "on" : "off");
|
||||
}
|
||||
if (vf_linkstate) {
|
||||
if (vf[IFLA_VF_LINK_STATE]) {
|
||||
struct ifla_vf_link_state *vf_linkstate =
|
||||
RTA_DATA(vf[IFLA_VF_LINK_STATE]);
|
||||
|
||||
if (vf_linkstate->link_state == IFLA_VF_LINK_STATE_AUTO)
|
||||
fprintf(fp, ", link-state auto");
|
||||
else if (vf_linkstate->link_state == IFLA_VF_LINK_STATE_ENABLE)
|
||||
|
|
@ -429,6 +405,22 @@ static void print_vfinfo(FILE *fp, struct rtattr *vfinfo)
|
|||
fprintf(fp, ", trust %s",
|
||||
vf_trust->setting ? "on" : "off");
|
||||
}
|
||||
if (vf[IFLA_VF_RSS_QUERY_EN]) {
|
||||
struct ifla_vf_rss_query_en *rss_query =
|
||||
RTA_DATA(vf[IFLA_VF_RSS_QUERY_EN]);
|
||||
|
||||
if (rss_query->setting != -1)
|
||||
fprintf(fp, ", query_rss %s",
|
||||
rss_query->setting ? "on" : "off");
|
||||
}
|
||||
if (vf[IFLA_VF_RSS_QUERY_EN]) {
|
||||
struct ifla_vf_rss_query_en *rss_query =
|
||||
RTA_DATA(vf[IFLA_VF_RSS_QUERY_EN]);
|
||||
|
||||
if (rss_query->setting != -1)
|
||||
fprintf(fp, ", query_rss %s",
|
||||
rss_query->setting ? "on" : "off");
|
||||
}
|
||||
if (vf[IFLA_VF_STATS] && show_stats)
|
||||
print_vf_stats64(fp, vf[IFLA_VF_STATS]);
|
||||
}
|
||||
|
|
@ -448,7 +440,8 @@ static void print_num(FILE *fp, unsigned int width, uint64_t count)
|
|||
}
|
||||
|
||||
/* increase value by a factor of 1000/1024 and print
|
||||
* if result is something a human can read */
|
||||
* if result is something a human can read
|
||||
*/
|
||||
for (;;) {
|
||||
powi *= base;
|
||||
if (count / base < powi)
|
||||
|
|
@ -691,9 +684,9 @@ int print_linkinfo_brief(const struct sockaddr_nl *who,
|
|||
return -1;
|
||||
|
||||
parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
|
||||
if (tb[IFLA_IFNAME] == NULL) {
|
||||
if (tb[IFLA_IFNAME] == NULL)
|
||||
fprintf(stderr, "BUG: device with ifindex %d has nil ifname\n", ifi->ifi_index);
|
||||
}
|
||||
|
||||
if (filter.label &&
|
||||
(!filter.family || filter.family == AF_PACKET) &&
|
||||
fnmatch(filter.label, RTA_DATA(tb[IFLA_IFNAME]), 0))
|
||||
|
|
@ -787,9 +780,9 @@ int print_linkinfo(const struct sockaddr_nl *who,
|
|||
return 0;
|
||||
|
||||
parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
|
||||
if (tb[IFLA_IFNAME] == NULL) {
|
||||
if (tb[IFLA_IFNAME] == NULL)
|
||||
fprintf(stderr, "BUG: device with ifindex %d has nil ifname\n", ifi->ifi_index);
|
||||
}
|
||||
|
||||
if (filter.label &&
|
||||
(!filter.family || filter.family == AF_PACKET) &&
|
||||
fnmatch(filter.label, RTA_DATA(tb[IFLA_IFNAME]), 0))
|
||||
|
|
@ -1184,9 +1177,9 @@ int print_addrinfo(const struct sockaddr_nl *who, struct nlmsghdr *n,
|
|||
ifa_flags &= ~IFA_F_MCAUTOJOIN;
|
||||
fprintf(fp, "autojoin ");
|
||||
}
|
||||
if (!(ifa_flags & IFA_F_PERMANENT)) {
|
||||
if (!(ifa_flags & IFA_F_PERMANENT))
|
||||
fprintf(fp, "dynamic ");
|
||||
} else
|
||||
else
|
||||
ifa_flags &= ~IFA_F_PERMANENT;
|
||||
if (ifa_flags & IFA_F_DADFAILED) {
|
||||
ifa_flags &= ~IFA_F_DADFAILED;
|
||||
|
|
@ -1672,9 +1665,9 @@ static int ipaddr_list_flush_or_save(int argc, char **argv, int action)
|
|||
filter.kind = *argv;
|
||||
}
|
||||
} else {
|
||||
if (strcmp(*argv, "dev") == 0) {
|
||||
if (strcmp(*argv, "dev") == 0)
|
||||
NEXT_ARG();
|
||||
} else if (matches(*argv, "help") == 0)
|
||||
else if (matches(*argv, "help") == 0)
|
||||
usage();
|
||||
if (filter_dev)
|
||||
duparg2("dev", *argv);
|
||||
|
|
@ -1979,9 +1972,8 @@ static int ipaddr_modify(int cmd, int flags, int argc, char **argv)
|
|||
} else if (strcmp(*argv, "autojoin") == 0) {
|
||||
ifa_flags |= IFA_F_MCAUTOJOIN;
|
||||
} else {
|
||||
if (strcmp(*argv, "local") == 0) {
|
||||
if (strcmp(*argv, "local") == 0)
|
||||
NEXT_ARG();
|
||||
}
|
||||
if (matches(*argv, "help") == 0)
|
||||
usage();
|
||||
if (local_len)
|
||||
|
|
@ -2012,9 +2004,9 @@ static int ipaddr_modify(int cmd, int flags, int argc, char **argv)
|
|||
if (peer_len == 0 && local_len) {
|
||||
if (cmd == RTM_DELADDR && lcl.family == AF_INET && !(lcl.flags & PREFIXLEN_SPECIFIED)) {
|
||||
fprintf(stderr,
|
||||
"Warning: Executing wildcard deletion to stay compatible with old scripts.\n" \
|
||||
" Explicitly specify the prefix length (%s/%d) to avoid this warning.\n" \
|
||||
" This special behaviour is likely to disappear in further releases,\n" \
|
||||
"Warning: Executing wildcard deletion to stay compatible with old scripts.\n"
|
||||
" Explicitly specify the prefix length (%s/%d) to avoid this warning.\n"
|
||||
" This special behaviour is likely to disappear in further releases,\n"
|
||||
" fix your scripts!\n", lcl_arg, local_len*8);
|
||||
} else {
|
||||
peer = lcl;
|
||||
|
|
|
|||
198
ip/ipl2tp.c
198
ip/ipl2tp.c
|
|
@ -56,15 +56,15 @@ struct l2tp_parm {
|
|||
|
||||
uint16_t pw_type;
|
||||
uint16_t mtu;
|
||||
int udp6_csum_tx:1;
|
||||
int udp6_csum_rx:1;
|
||||
int udp_csum:1;
|
||||
int recv_seq:1;
|
||||
int send_seq:1;
|
||||
int lns_mode:1;
|
||||
int data_seq:2;
|
||||
int tunnel:1;
|
||||
int session:1;
|
||||
unsigned int udp6_csum_tx:1;
|
||||
unsigned int udp6_csum_rx:1;
|
||||
unsigned int udp_csum:1;
|
||||
unsigned int recv_seq:1;
|
||||
unsigned int send_seq:1;
|
||||
unsigned int lns_mode:1;
|
||||
unsigned int data_seq:2;
|
||||
unsigned int tunnel:1;
|
||||
unsigned int session:1;
|
||||
int reorder_timeout;
|
||||
const char *ifname;
|
||||
uint8_t l2spec_type;
|
||||
|
|
@ -110,17 +110,19 @@ static int create_tunnel(struct l2tp_parm *p)
|
|||
|
||||
if (p->local_ip.family == AF_INET6)
|
||||
local_attr = L2TP_ATTR_IP6_SADDR;
|
||||
addattr_l(&req.n, 1024, local_attr, &p->local_ip.data, p->local_ip.bytelen);
|
||||
addattr_l(&req.n, 1024, local_attr, &p->local_ip.data,
|
||||
p->local_ip.bytelen);
|
||||
|
||||
if (p->peer_ip.family == AF_INET6)
|
||||
peer_attr = L2TP_ATTR_IP6_DADDR;
|
||||
addattr_l(&req.n, 1024, peer_attr, &p->peer_ip.data, p->peer_ip.bytelen);
|
||||
addattr_l(&req.n, 1024, peer_attr, &p->peer_ip.data,
|
||||
p->peer_ip.bytelen);
|
||||
|
||||
if (p->encap == L2TP_ENCAPTYPE_UDP) {
|
||||
addattr16(&req.n, 1024, L2TP_ATTR_UDP_SPORT, p->local_udp_port);
|
||||
addattr16(&req.n, 1024, L2TP_ATTR_UDP_DPORT, p->peer_udp_port);
|
||||
if (p->udp_csum)
|
||||
addattr(&req.n, 1024, L2TP_ATTR_UDP_CSUM);
|
||||
addattr8(&req.n, 1024, L2TP_ATTR_UDP_CSUM, 1);
|
||||
if (!p->udp6_csum_tx)
|
||||
addattr(&req.n, 1024, L2TP_ATTR_UDP_ZERO_CSUM6_TX);
|
||||
if (!p->udp6_csum_rx)
|
||||
|
|
@ -159,17 +161,26 @@ static int create_session(struct l2tp_parm *p)
|
|||
addattr8(&req.n, 1024, L2TP_ATTR_L2SPEC_TYPE, p->l2spec_type);
|
||||
addattr8(&req.n, 1024, L2TP_ATTR_L2SPEC_LEN, p->l2spec_len);
|
||||
|
||||
if (p->mtu) addattr16(&req.n, 1024, L2TP_ATTR_MTU, p->mtu);
|
||||
if (p->recv_seq) addattr(&req.n, 1024, L2TP_ATTR_RECV_SEQ);
|
||||
if (p->send_seq) addattr(&req.n, 1024, L2TP_ATTR_SEND_SEQ);
|
||||
if (p->lns_mode) addattr(&req.n, 1024, L2TP_ATTR_LNS_MODE);
|
||||
if (p->data_seq) addattr8(&req.n, 1024, L2TP_ATTR_DATA_SEQ, p->data_seq);
|
||||
if (p->reorder_timeout) addattr64(&req.n, 1024, L2TP_ATTR_RECV_TIMEOUT,
|
||||
if (p->mtu)
|
||||
addattr16(&req.n, 1024, L2TP_ATTR_MTU, p->mtu);
|
||||
if (p->recv_seq)
|
||||
addattr8(&req.n, 1024, L2TP_ATTR_RECV_SEQ, 1);
|
||||
if (p->send_seq)
|
||||
addattr8(&req.n, 1024, L2TP_ATTR_SEND_SEQ, 1);
|
||||
if (p->lns_mode)
|
||||
addattr(&req.n, 1024, L2TP_ATTR_LNS_MODE);
|
||||
if (p->data_seq)
|
||||
addattr8(&req.n, 1024, L2TP_ATTR_DATA_SEQ, p->data_seq);
|
||||
if (p->reorder_timeout)
|
||||
addattr64(&req.n, 1024, L2TP_ATTR_RECV_TIMEOUT,
|
||||
p->reorder_timeout);
|
||||
if (p->offset) addattr16(&req.n, 1024, L2TP_ATTR_OFFSET, p->offset);
|
||||
if (p->cookie_len) addattr_l(&req.n, 1024, L2TP_ATTR_COOKIE,
|
||||
if (p->offset)
|
||||
addattr16(&req.n, 1024, L2TP_ATTR_OFFSET, p->offset);
|
||||
if (p->cookie_len)
|
||||
addattr_l(&req.n, 1024, L2TP_ATTR_COOKIE,
|
||||
p->cookie, p->cookie_len);
|
||||
if (p->peer_cookie_len) addattr_l(&req.n, 1024, L2TP_ATTR_PEER_COOKIE,
|
||||
if (p->peer_cookie_len)
|
||||
addattr_l(&req.n, 1024, L2TP_ATTR_PEER_COOKIE,
|
||||
p->peer_cookie, p->peer_cookie_len);
|
||||
if (p->ifname && p->ifname[0])
|
||||
addattrstrz(&req.n, 1024, L2TP_ATTR_IFNAME, p->ifname);
|
||||
|
|
@ -213,14 +224,37 @@ static void print_tunnel(const struct l2tp_data *data)
|
|||
p->tunnel_id,
|
||||
p->encap == L2TP_ENCAPTYPE_UDP ? "UDP" :
|
||||
p->encap == L2TP_ENCAPTYPE_IP ? "IP" : "??");
|
||||
printf(" From %s ", inet_ntop(p->local_ip.family, p->local_ip.data, buf, sizeof(buf)));
|
||||
printf("to %s\n", inet_ntop(p->peer_ip.family, p->peer_ip.data, buf, sizeof(buf)));
|
||||
printf(" From %s ",
|
||||
inet_ntop(p->local_ip.family, p->local_ip.data,
|
||||
buf, sizeof(buf)));
|
||||
printf("to %s\n",
|
||||
inet_ntop(p->peer_ip.family, p->peer_ip.data,
|
||||
buf, sizeof(buf)));
|
||||
printf(" Peer tunnel %u\n",
|
||||
p->peer_tunnel_id);
|
||||
|
||||
if (p->encap == L2TP_ENCAPTYPE_UDP)
|
||||
if (p->encap == L2TP_ENCAPTYPE_UDP) {
|
||||
printf(" UDP source / dest ports: %hu/%hu\n",
|
||||
p->local_udp_port, p->peer_udp_port);
|
||||
|
||||
switch (p->local_ip.family) {
|
||||
case AF_INET:
|
||||
printf(" UDP checksum: %s\n",
|
||||
p->udp_csum ? "enabled" : "disabled");
|
||||
break;
|
||||
case AF_INET6:
|
||||
printf(" UDP checksum: %s%s%s%s\n",
|
||||
p->udp6_csum_tx && p->udp6_csum_rx
|
||||
? "enabled" : "",
|
||||
p->udp6_csum_tx && !p->udp6_csum_rx
|
||||
? "tx" : "",
|
||||
!p->udp6_csum_tx && p->udp6_csum_rx
|
||||
? "rx" : "",
|
||||
!p->udp6_csum_tx && !p->udp6_csum_rx
|
||||
? "disabled" : "");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void print_session(struct l2tp_data *data)
|
||||
|
|
@ -232,9 +266,9 @@ static void print_session(struct l2tp_data *data)
|
|||
printf(" Peer session %u, tunnel %u\n",
|
||||
p->peer_session_id, p->peer_tunnel_id);
|
||||
|
||||
if (p->ifname != NULL) {
|
||||
if (p->ifname != NULL)
|
||||
printf(" interface name: %s\n", p->ifname);
|
||||
}
|
||||
|
||||
printf(" offset %u, peer offset %u\n",
|
||||
p->offset, p->peer_offset);
|
||||
if (p->cookie_len > 0)
|
||||
|
|
@ -246,6 +280,14 @@ static void print_session(struct l2tp_data *data)
|
|||
printf(" reorder timeout: %u\n", p->reorder_timeout);
|
||||
else
|
||||
printf("\n");
|
||||
if (p->send_seq || p->recv_seq) {
|
||||
printf(" sequence numbering:");
|
||||
if (p->send_seq)
|
||||
printf(" send");
|
||||
if (p->recv_seq)
|
||||
printf(" recv");
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
static int get_response(struct nlmsghdr *n, void *arg)
|
||||
|
|
@ -289,13 +331,12 @@ static int get_response(struct nlmsghdr *n, void *arg)
|
|||
if (attrs[L2TP_ATTR_L2SPEC_LEN])
|
||||
p->l2spec_len = rta_getattr_u8(attrs[L2TP_ATTR_L2SPEC_LEN]);
|
||||
|
||||
p->udp_csum = !!attrs[L2TP_ATTR_UDP_CSUM];
|
||||
/*
|
||||
* Not fetching from L2TP_ATTR_UDP_ZERO_CSUM6_{T,R}X because the
|
||||
* kernel doesn't send it so just leave it as default value.
|
||||
*/
|
||||
p->udp6_csum_tx = 1;
|
||||
p->udp6_csum_rx = 1;
|
||||
if (attrs[L2TP_ATTR_UDP_CSUM])
|
||||
p->udp_csum = !!rta_getattr_u8(attrs[L2TP_ATTR_UDP_CSUM]);
|
||||
|
||||
p->udp6_csum_tx = !attrs[L2TP_ATTR_UDP_ZERO_CSUM6_TX];
|
||||
p->udp6_csum_rx = !attrs[L2TP_ATTR_UDP_ZERO_CSUM6_RX];
|
||||
|
||||
if (attrs[L2TP_ATTR_COOKIE])
|
||||
memcpy(p->cookie, RTA_DATA(attrs[L2TP_ATTR_COOKIE]),
|
||||
p->cookie_len = RTA_PAYLOAD(attrs[L2TP_ATTR_COOKIE]));
|
||||
|
|
@ -304,8 +345,10 @@ static int get_response(struct nlmsghdr *n, void *arg)
|
|||
memcpy(p->peer_cookie, RTA_DATA(attrs[L2TP_ATTR_PEER_COOKIE]),
|
||||
p->peer_cookie_len = RTA_PAYLOAD(attrs[L2TP_ATTR_PEER_COOKIE]));
|
||||
|
||||
p->recv_seq = !!attrs[L2TP_ATTR_RECV_SEQ];
|
||||
p->send_seq = !!attrs[L2TP_ATTR_SEND_SEQ];
|
||||
if (attrs[L2TP_ATTR_RECV_SEQ])
|
||||
p->recv_seq = !!rta_getattr_u8(attrs[L2TP_ATTR_RECV_SEQ]);
|
||||
if (attrs[L2TP_ATTR_SEND_SEQ])
|
||||
p->send_seq = !!rta_getattr_u8(attrs[L2TP_ATTR_SEND_SEQ]);
|
||||
|
||||
if (attrs[L2TP_ATTR_RECV_TIMEOUT])
|
||||
p->reorder_timeout = rta_getattr_u64(attrs[L2TP_ATTR_RECV_TIMEOUT]);
|
||||
|
|
@ -369,7 +412,8 @@ static int get_response(struct nlmsghdr *n, void *arg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int session_nlmsg(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
|
||||
static int session_nlmsg(const struct sockaddr_nl *who,
|
||||
struct nlmsghdr *n, void *arg)
|
||||
{
|
||||
int ret = get_response(n, arg);
|
||||
|
||||
|
|
@ -389,7 +433,8 @@ static int get_session(struct l2tp_data *p)
|
|||
|
||||
if (p->config.tunnel_id && p->config.session_id) {
|
||||
addattr32(&req.n, 128, L2TP_ATTR_CONN_ID, p->config.tunnel_id);
|
||||
addattr32(&req.n, 128, L2TP_ATTR_SESSION_ID, p->config.session_id);
|
||||
addattr32(&req.n, 128, L2TP_ATTR_SESSION_ID,
|
||||
p->config.session_id);
|
||||
}
|
||||
|
||||
if (rtnl_send(&genl_rth, &req, req.n.nlmsg_len) < 0)
|
||||
|
|
@ -403,7 +448,8 @@ static int get_session(struct l2tp_data *p)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int tunnel_nlmsg(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
|
||||
static int tunnel_nlmsg(const struct sockaddr_nl *who,
|
||||
struct nlmsghdr *n, void *arg)
|
||||
{
|
||||
int ret = get_response(n, arg);
|
||||
|
||||
|
|
@ -468,31 +514,33 @@ static void usage(void) __attribute__((noreturn));
|
|||
|
||||
static void usage(void)
|
||||
{
|
||||
fprintf(stderr, "Usage: ip l2tp add tunnel\n");
|
||||
fprintf(stderr, " remote ADDR local ADDR\n");
|
||||
fprintf(stderr, " tunnel_id ID peer_tunnel_id ID\n");
|
||||
fprintf(stderr, " [ encap { ip | udp } ]\n");
|
||||
fprintf(stderr, " [ udp_sport PORT ] [ udp_dport PORT ]\n");
|
||||
fprintf(stderr, " [ udp_csum { on | off } ]\n");
|
||||
fprintf(stderr, " [ udp6_csum_tx { on | off } ]\n");
|
||||
fprintf(stderr, " [ udp6_csum_rx { on | off } ]\n");
|
||||
fprintf(stderr, "Usage: ip l2tp add session [ name NAME ]\n");
|
||||
fprintf(stderr, " tunnel_id ID\n");
|
||||
fprintf(stderr, " session_id ID peer_session_id ID\n");
|
||||
fprintf(stderr, " [ cookie HEXSTR ] [ peer_cookie HEXSTR ]\n");
|
||||
fprintf(stderr, " [ offset OFFSET ] [ peer_offset OFFSET ]\n");
|
||||
fprintf(stderr, " [ l2spec_type L2SPEC ]\n");
|
||||
fprintf(stderr, " ip l2tp del tunnel tunnel_id ID\n");
|
||||
fprintf(stderr, " ip l2tp del session tunnel_id ID session_id ID\n");
|
||||
fprintf(stderr, " ip l2tp show tunnel [ tunnel_id ID ]\n");
|
||||
fprintf(stderr, " ip l2tp show session [ tunnel_id ID ] [ session_id ID ]\n");
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, "Where: NAME := STRING\n");
|
||||
fprintf(stderr, " ADDR := { IP_ADDRESS | any }\n");
|
||||
fprintf(stderr, " PORT := { 0..65535 }\n");
|
||||
fprintf(stderr, " ID := { 1..4294967295 }\n");
|
||||
fprintf(stderr, " HEXSTR := { 8 or 16 hex digits (4 / 8 bytes) }\n");
|
||||
fprintf(stderr, " L2SPEC := { none | default }\n");
|
||||
fprintf(stderr, "Usage: ip l2tp add tunnel\n"
|
||||
" remote ADDR local ADDR\n"
|
||||
" tunnel_id ID peer_tunnel_id ID\n"
|
||||
" [ encap { ip | udp } ]\n"
|
||||
" [ udp_sport PORT ] [ udp_dport PORT ]\n"
|
||||
" [ udp_csum { on | off } ]\n"
|
||||
" [ udp6_csum_tx { on | off } ]\n"
|
||||
" [ udp6_csum_rx { on | off } ]\n"
|
||||
"Usage: ip l2tp add session [ name NAME ]\n"
|
||||
" tunnel_id ID\n"
|
||||
" session_id ID peer_session_id ID\n"
|
||||
" [ cookie HEXSTR ] [ peer_cookie HEXSTR ]\n"
|
||||
" [ offset OFFSET ] [ peer_offset OFFSET ]\n"
|
||||
" [ seq { none | send | recv | both } ]\n"
|
||||
" [ l2spec_type L2SPEC ]\n"
|
||||
" ip l2tp del tunnel tunnel_id ID\n"
|
||||
" ip l2tp del session tunnel_id ID session_id ID\n"
|
||||
" ip l2tp show tunnel [ tunnel_id ID ]\n"
|
||||
" ip l2tp show session [ tunnel_id ID ] [ session_id ID ]\n"
|
||||
"\n"
|
||||
"Where: NAME := STRING\n"
|
||||
" ADDR := { IP_ADDRESS | any }\n"
|
||||
" PORT := { 0..65535 }\n"
|
||||
" ID := { 1..4294967295 }\n"
|
||||
" HEXSTR := { 8 or 16 hex digits (4 / 8 bytes) }\n"
|
||||
" L2SPEC := { none | default }\n");
|
||||
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
|
|
@ -648,7 +696,26 @@ static int parse_args(int argc, char **argv, int cmd, struct l2tp_parm *p)
|
|||
p->l2spec_type = L2TP_L2SPECTYPE_NONE;
|
||||
p->l2spec_len = 0;
|
||||
} else {
|
||||
fprintf(stderr, "Unknown layer2specific header type \"%s\"\n", *argv);
|
||||
fprintf(stderr,
|
||||
"Unknown layer2specific header type \"%s\"\n",
|
||||
*argv);
|
||||
exit(-1);
|
||||
}
|
||||
} else if (strcmp(*argv, "seq") == 0) {
|
||||
NEXT_ARG();
|
||||
if (strcasecmp(*argv, "both") == 0) {
|
||||
p->recv_seq = 1;
|
||||
p->send_seq = 1;
|
||||
} else if (strcasecmp(*argv, "recv") == 0) {
|
||||
p->recv_seq = 1;
|
||||
} else if (strcasecmp(*argv, "send") == 0) {
|
||||
p->send_seq = 1;
|
||||
} else if (strcasecmp(*argv, "none") == 0) {
|
||||
p->recv_seq = 0;
|
||||
p->send_seq = 0;
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"Unknown seq value \"%s\"\n", *argv);
|
||||
exit(-1);
|
||||
}
|
||||
} else if (strcmp(*argv, "tunnel") == 0) {
|
||||
|
|
@ -779,6 +846,7 @@ int do_ipl2tp(int argc, char **argv)
|
|||
matches(*argv, "list") == 0)
|
||||
return do_show(argc-1, argv+1);
|
||||
|
||||
fprintf(stderr, "Command \"%s\" is unknown, try \"ip l2tp help\".\n", *argv);
|
||||
fprintf(stderr,
|
||||
"Command \"%s\" is unknown, try \"ip l2tp help\".\n", *argv);
|
||||
exit(-1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -98,8 +98,8 @@ void iplink_usage(void)
|
|||
fprintf(stderr,
|
||||
" ip link help [ TYPE ]\n\n"
|
||||
"TYPE := { vlan | veth | vcan | dummy | ifb | macvlan | macvtap |\n"
|
||||
" bridge | bond | ipoib | ip6tnl | ipip | sit | vxlan |\n"
|
||||
" gre | gretap | ip6gre | ip6gretap | vti | nlmon |\n"
|
||||
" bridge | bond | team | ipoib | ip6tnl | ipip | sit | vxlan |\n"
|
||||
" gre | gretap | ip6gre | ip6gretap | vti | nlmon | team_slave |\n"
|
||||
" bond_slave | ipvlan | geneve | bridge_slave | vrf | macsec }\n");
|
||||
}
|
||||
exit(-1);
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <linux/if_link.h>
|
||||
#include <linux/if_ether.h>
|
||||
|
||||
#include "rt_names.h"
|
||||
#include "utils.h"
|
||||
|
|
@ -29,7 +30,11 @@
|
|||
static void print_explain(struct link_util *lu, FILE *f)
|
||||
{
|
||||
fprintf(f,
|
||||
"Usage: ... %s mode { private | vepa | bridge | passthru [nopromisc] }\n",
|
||||
"Usage: ... %s mode MODE [flag MODE_FLAG] MODE_OPTS\n"
|
||||
"MODE: private | vepa | bridge | passthru | source\n"
|
||||
"MODE_FLAG: null | nopromisc\n"
|
||||
"MODE_OPTS: for mode \"source\":\n"
|
||||
"\tmacaddr { { add | del } <macaddr> | set [ <macaddr> [ <macaddr> ... ] ] | flush }\n",
|
||||
lu->id
|
||||
);
|
||||
}
|
||||
|
|
@ -43,7 +48,15 @@ static void explain(struct link_util *lu)
|
|||
static int mode_arg(const char *arg)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Error: argument of \"mode\" must be \"private\", \"vepa\", \"bridge\" or \"passthru\", not \"%s\"\n",
|
||||
"Error: argument of \"mode\" must be \"private\", \"vepa\", \"bridge\", \"passthru\" or \"source\", not \"%s\"\n",
|
||||
arg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int flag_arg(const char *arg)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Error: argument of \"flag\" must be \"nopromisc\" or \"null\", not \"%s\"\n",
|
||||
arg);
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -53,6 +66,10 @@ static int macvlan_parse_opt(struct link_util *lu, int argc, char **argv,
|
|||
{
|
||||
__u32 mode = 0;
|
||||
__u16 flags = 0;
|
||||
__u32 mac_mode = 0;
|
||||
int has_flags = 0;
|
||||
char mac[ETH_ALEN];
|
||||
struct rtattr *nmac;
|
||||
|
||||
while (argc > 0) {
|
||||
if (matches(*argv, "mode") == 0) {
|
||||
|
|
@ -66,10 +83,72 @@ static int macvlan_parse_opt(struct link_util *lu, int argc, char **argv,
|
|||
mode = MACVLAN_MODE_BRIDGE;
|
||||
else if (strcmp(*argv, "passthru") == 0)
|
||||
mode = MACVLAN_MODE_PASSTHRU;
|
||||
else if (strcmp(*argv, "source") == 0)
|
||||
mode = MACVLAN_MODE_SOURCE;
|
||||
else
|
||||
return mode_arg(*argv);
|
||||
} else if (matches(*argv, "flag") == 0) {
|
||||
NEXT_ARG();
|
||||
|
||||
if (strcmp(*argv, "nopromisc") == 0)
|
||||
flags |= MACVLAN_FLAG_NOPROMISC;
|
||||
else if (strcmp(*argv, "null") == 0)
|
||||
flags |= 0;
|
||||
else
|
||||
return flag_arg(*argv);
|
||||
|
||||
has_flags = 1;
|
||||
|
||||
} else if (matches(*argv, "macaddr") == 0) {
|
||||
NEXT_ARG();
|
||||
|
||||
if (strcmp(*argv, "add") == 0) {
|
||||
mac_mode = MACVLAN_MACADDR_ADD;
|
||||
} else if (strcmp(*argv, "del") == 0) {
|
||||
mac_mode = MACVLAN_MACADDR_DEL;
|
||||
} else if (strcmp(*argv, "set") == 0) {
|
||||
mac_mode = MACVLAN_MACADDR_SET;
|
||||
} else if (strcmp(*argv, "flush") == 0) {
|
||||
mac_mode = MACVLAN_MACADDR_FLUSH;
|
||||
} else {
|
||||
explain(lu);
|
||||
return -1;
|
||||
}
|
||||
|
||||
addattr32(n, 1024, IFLA_MACVLAN_MACADDR_MODE, mac_mode);
|
||||
|
||||
if (mac_mode == MACVLAN_MACADDR_ADD ||
|
||||
mac_mode == MACVLAN_MACADDR_DEL) {
|
||||
NEXT_ARG();
|
||||
|
||||
if (ll_addr_a2n(mac, sizeof(mac),
|
||||
*argv) != ETH_ALEN)
|
||||
return -1;
|
||||
|
||||
addattr_l(n, 1024, IFLA_MACVLAN_MACADDR, &mac,
|
||||
ETH_ALEN);
|
||||
}
|
||||
|
||||
if (mac_mode == MACVLAN_MACADDR_SET) {
|
||||
nmac = addattr_nest(n, 1024,
|
||||
IFLA_MACVLAN_MACADDR_DATA);
|
||||
while (NEXT_ARG_OK()) {
|
||||
NEXT_ARG_FWD();
|
||||
|
||||
if (ll_addr_a2n(mac, sizeof(mac),
|
||||
*argv) != ETH_ALEN) {
|
||||
PREV_ARG();
|
||||
break;
|
||||
}
|
||||
|
||||
addattr_l(n, 1024, IFLA_MACVLAN_MACADDR,
|
||||
&mac, ETH_ALEN);
|
||||
}
|
||||
addattr_nest_end(n, nmac);
|
||||
}
|
||||
} else if (matches(*argv, "nopromisc") == 0) {
|
||||
flags |= MACVLAN_FLAG_NOPROMISC;
|
||||
has_flags = 1;
|
||||
} else if (matches(*argv, "help") == 0) {
|
||||
explain(lu);
|
||||
return -1;
|
||||
|
|
@ -84,7 +163,7 @@ static int macvlan_parse_opt(struct link_util *lu, int argc, char **argv,
|
|||
if (mode)
|
||||
addattr32(n, 1024, IFLA_MACVLAN_MODE, mode);
|
||||
|
||||
if (flags) {
|
||||
if (has_flags) {
|
||||
if (flags & MACVLAN_FLAG_NOPROMISC &&
|
||||
mode != MACVLAN_MODE_PASSTHRU) {
|
||||
pfx_err(lu, "nopromisc flag only valid in passthru mode");
|
||||
|
|
@ -100,6 +179,10 @@ static void macvlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]
|
|||
{
|
||||
__u32 mode;
|
||||
__u16 flags;
|
||||
__u32 count;
|
||||
unsigned char *addr;
|
||||
int len;
|
||||
struct rtattr *rta;
|
||||
|
||||
if (!tb)
|
||||
return;
|
||||
|
|
@ -114,15 +197,44 @@ static void macvlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]
|
|||
: mode == MACVLAN_MODE_VEPA ? "vepa"
|
||||
: mode == MACVLAN_MODE_BRIDGE ? "bridge"
|
||||
: mode == MACVLAN_MODE_PASSTHRU ? "passthru"
|
||||
: mode == MACVLAN_MODE_SOURCE ? "source"
|
||||
: "unknown");
|
||||
|
||||
if (!tb[IFLA_MACVLAN_FLAGS] ||
|
||||
RTA_PAYLOAD(tb[IFLA_MACVLAN_FLAGS]) < sizeof(__u16))
|
||||
return;
|
||||
|
||||
flags = 0;
|
||||
else
|
||||
flags = rta_getattr_u16(tb[IFLA_MACVLAN_FLAGS]);
|
||||
|
||||
if (flags & MACVLAN_FLAG_NOPROMISC)
|
||||
fprintf(f, "nopromisc ");
|
||||
|
||||
/* in source mode, there are more options to print */
|
||||
|
||||
if (mode != MACVLAN_MODE_SOURCE)
|
||||
return;
|
||||
|
||||
if (!tb[IFLA_MACVLAN_MACADDR_COUNT] ||
|
||||
RTA_PAYLOAD(tb[IFLA_MACVLAN_MACADDR_COUNT]) < sizeof(__u32))
|
||||
return;
|
||||
|
||||
count = rta_getattr_u32(tb[IFLA_MACVLAN_MACADDR_COUNT]);
|
||||
fprintf(f, "remotes (%d) ", count);
|
||||
|
||||
if (!tb[IFLA_MACVLAN_MACADDR_DATA])
|
||||
return;
|
||||
|
||||
rta = RTA_DATA(tb[IFLA_MACVLAN_MACADDR_DATA]);
|
||||
len = RTA_PAYLOAD(tb[IFLA_MACVLAN_MACADDR_DATA]);
|
||||
|
||||
for (; RTA_OK(rta, len); rta = RTA_NEXT(rta, len)) {
|
||||
if (rta->rta_type != IFLA_MACVLAN_MACADDR ||
|
||||
RTA_PAYLOAD(rta) < 6)
|
||||
continue;
|
||||
addr = RTA_DATA(rta);
|
||||
fprintf(f, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x ", addr[0],
|
||||
addr[1], addr[2], addr[3], addr[4], addr[5]);
|
||||
}
|
||||
}
|
||||
|
||||
static void macvlan_print_help(struct link_util *lu, int argc, char **argv,
|
||||
|
|
|
|||
|
|
@ -634,10 +634,10 @@ static void print_one_stat(const char **names, struct rtattr **attr, int idx,
|
|||
}
|
||||
|
||||
static const char *txsc_stats_names[NUM_MACSEC_TXSC_STATS_ATTR] = {
|
||||
[MACSEC_TXSC_STATS_ATTR_OUT_PKTS_PROTECTED] = "OutOctetsProtected",
|
||||
[MACSEC_TXSC_STATS_ATTR_OUT_PKTS_ENCRYPTED] = "OutOctetsEncrypted",
|
||||
[MACSEC_TXSC_STATS_ATTR_OUT_OCTETS_PROTECTED] = "OutPktsProtected",
|
||||
[MACSEC_TXSC_STATS_ATTR_OUT_OCTETS_ENCRYPTED] = "OutPktsEncrypted",
|
||||
[MACSEC_TXSC_STATS_ATTR_OUT_PKTS_PROTECTED] = "OutPktsProtected",
|
||||
[MACSEC_TXSC_STATS_ATTR_OUT_PKTS_ENCRYPTED] = "OutPktsEncrypted",
|
||||
[MACSEC_TXSC_STATS_ATTR_OUT_OCTETS_PROTECTED] = "OutOctetsProtected",
|
||||
[MACSEC_TXSC_STATS_ATTR_OUT_OCTETS_ENCRYPTED] = "OutOctetsEncrypted",
|
||||
};
|
||||
|
||||
static void print_txsc_stats(const char *prefix, struct rtattr *attr)
|
||||
|
|
|
|||
|
|
@ -321,7 +321,7 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
|
|||
if (n->nlmsg_type != RTM_NEWROUTE && n->nlmsg_type != RTM_DELROUTE) {
|
||||
fprintf(stderr, "Not a route: %08x %08x %08x\n",
|
||||
n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags);
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
if (filter.flushb && n->nlmsg_type != RTM_NEWROUTE)
|
||||
return 0;
|
||||
|
|
@ -1755,7 +1755,7 @@ static int iproute_get(int argc, char **argv)
|
|||
|
||||
if (print_route(NULL, &req.n, (void *)stdout) < 0) {
|
||||
fprintf(stderr, "An error :-)\n");
|
||||
exit(1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (req.n.nlmsg_type != RTM_NEWROUTE) {
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ void rtnl_close(struct rtnl_handle *rth)
|
|||
}
|
||||
}
|
||||
|
||||
int rtnl_open_byproto(struct rtnl_handle *rth, unsigned subscriptions,
|
||||
int rtnl_open_byproto(struct rtnl_handle *rth, unsigned int subscriptions,
|
||||
int protocol)
|
||||
{
|
||||
socklen_t addr_len;
|
||||
|
|
@ -58,12 +58,14 @@ int rtnl_open_byproto(struct rtnl_handle *rth, unsigned subscriptions,
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (setsockopt(rth->fd,SOL_SOCKET,SO_SNDBUF,&sndbuf,sizeof(sndbuf)) < 0) {
|
||||
if (setsockopt(rth->fd, SOL_SOCKET, SO_SNDBUF,
|
||||
&sndbuf, sizeof(sndbuf)) < 0) {
|
||||
perror("SO_SNDBUF");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (setsockopt(rth->fd,SOL_SOCKET,SO_RCVBUF,&rcvbuf,sizeof(rcvbuf)) < 0) {
|
||||
if (setsockopt(rth->fd, SOL_SOCKET, SO_RCVBUF,
|
||||
&rcvbuf, sizeof(rcvbuf)) < 0) {
|
||||
perror("SO_RCVBUF");
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -72,12 +74,14 @@ int rtnl_open_byproto(struct rtnl_handle *rth, unsigned subscriptions,
|
|||
rth->local.nl_family = AF_NETLINK;
|
||||
rth->local.nl_groups = subscriptions;
|
||||
|
||||
if (bind(rth->fd, (struct sockaddr*)&rth->local, sizeof(rth->local)) < 0) {
|
||||
if (bind(rth->fd, (struct sockaddr *)&rth->local,
|
||||
sizeof(rth->local)) < 0) {
|
||||
perror("Cannot bind netlink socket");
|
||||
return -1;
|
||||
}
|
||||
addr_len = sizeof(rth->local);
|
||||
if (getsockname(rth->fd, (struct sockaddr*)&rth->local, &addr_len) < 0) {
|
||||
if (getsockname(rth->fd, (struct sockaddr *)&rth->local,
|
||||
&addr_len) < 0) {
|
||||
perror("Cannot getsockname");
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -86,14 +90,15 @@ int rtnl_open_byproto(struct rtnl_handle *rth, unsigned subscriptions,
|
|||
return -1;
|
||||
}
|
||||
if (rth->local.nl_family != AF_NETLINK) {
|
||||
fprintf(stderr, "Wrong address family %d\n", rth->local.nl_family);
|
||||
fprintf(stderr, "Wrong address family %d\n",
|
||||
rth->local.nl_family);
|
||||
return -1;
|
||||
}
|
||||
rth->seq = time(NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rtnl_open(struct rtnl_handle *rth, unsigned subscriptions)
|
||||
int rtnl_open(struct rtnl_handle *rth, unsigned int subscriptions)
|
||||
{
|
||||
return rtnl_open_byproto(rth, subscriptions, NETLINK_ROUTE);
|
||||
}
|
||||
|
|
@ -123,7 +128,7 @@ int rtnl_wilddump_req_filter(struct rtnl_handle *rth, int family, int type,
|
|||
.ext_filter_mask = filt_mask,
|
||||
};
|
||||
|
||||
return send(rth->fd, (void*)&req, sizeof(req), 0);
|
||||
return send(rth->fd, &req, sizeof(req), 0);
|
||||
}
|
||||
|
||||
int rtnl_wilddump_req_filter_fn(struct rtnl_handle *rth, int family, int type,
|
||||
|
|
@ -149,7 +154,7 @@ int rtnl_wilddump_req_filter_fn(struct rtnl_handle *rth, int family, int type,
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
return send(rth->fd, (void*)&req, sizeof(req), 0);
|
||||
return send(rth->fd, &req, req.nlh.nlmsg_len, 0);
|
||||
}
|
||||
|
||||
int rtnl_wilddump_stats_req_filter(struct rtnl_handle *rth, int fam, int type,
|
||||
|
|
@ -169,7 +174,7 @@ int rtnl_wilddump_stats_req_filter(struct rtnl_handle *rth, int fam, int type,
|
|||
req.ifsm.family = fam;
|
||||
req.ifsm.filter_mask = filt_mask;
|
||||
|
||||
return send(rth->fd, (void *)&req, sizeof(req), 0);
|
||||
return send(rth->fd, &req, sizeof(req), 0);
|
||||
}
|
||||
|
||||
int rtnl_send(struct rtnl_handle *rth, const void *buf, int len)
|
||||
|
|
@ -199,6 +204,7 @@ int rtnl_send_check(struct rtnl_handle *rth, const void *buf, int len)
|
|||
h = NLMSG_NEXT(h, status)) {
|
||||
if (h->nlmsg_type == NLMSG_ERROR) {
|
||||
struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(h);
|
||||
|
||||
if (h->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr)))
|
||||
fprintf(stderr, "ERROR truncated\n");
|
||||
else
|
||||
|
|
@ -237,7 +243,7 @@ int rtnl_dump_request_n(struct rtnl_handle *rth, struct nlmsghdr *n)
|
|||
{
|
||||
struct sockaddr_nl nladdr = { .nl_family = AF_NETLINK };
|
||||
struct iovec iov = {
|
||||
.iov_base = (void*) n,
|
||||
.iov_base = n,
|
||||
.iov_len = n->nlmsg_len
|
||||
};
|
||||
struct msghdr msg = {
|
||||
|
|
@ -296,6 +302,7 @@ int rtnl_dump_filter_l(struct rtnl_handle *rth,
|
|||
|
||||
for (a = arg; a->filter; a++) {
|
||||
struct nlmsghdr *h = (struct nlmsghdr *)buf;
|
||||
|
||||
msglen = status;
|
||||
|
||||
while (NLMSG_OK(h, msglen)) {
|
||||
|
|
@ -317,6 +324,7 @@ int rtnl_dump_filter_l(struct rtnl_handle *rth,
|
|||
}
|
||||
if (h->nlmsg_type == NLMSG_ERROR) {
|
||||
struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(h);
|
||||
|
||||
if (h->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr))) {
|
||||
fprintf(stderr,
|
||||
"ERROR truncated\n");
|
||||
|
|
@ -377,11 +385,11 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n,
|
|||
struct nlmsghdr *answer, size_t maxlen)
|
||||
{
|
||||
int status;
|
||||
unsigned seq;
|
||||
unsigned int seq;
|
||||
struct nlmsghdr *h;
|
||||
struct sockaddr_nl nladdr = { .nl_family = AF_NETLINK };
|
||||
struct iovec iov = {
|
||||
.iov_base = (void*) n,
|
||||
.iov_base = n,
|
||||
.iov_len = n->nlmsg_len
|
||||
};
|
||||
struct msghdr msg = {
|
||||
|
|
@ -420,7 +428,9 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n,
|
|||
return -1;
|
||||
}
|
||||
if (msg.msg_namelen != sizeof(nladdr)) {
|
||||
fprintf(stderr, "sender address length == %d\n", msg.msg_namelen);
|
||||
fprintf(stderr,
|
||||
"sender address length == %d\n",
|
||||
msg.msg_namelen);
|
||||
exit(1);
|
||||
}
|
||||
for (h = (struct nlmsghdr *)buf; status >= sizeof(*h); ) {
|
||||
|
|
@ -432,7 +442,9 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n,
|
|||
fprintf(stderr, "Truncated message\n");
|
||||
return -1;
|
||||
}
|
||||
fprintf(stderr, "!!!malformed message: len=%d\n", len);
|
||||
fprintf(stderr,
|
||||
"!!!malformed message: len=%d\n",
|
||||
len);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
|
@ -447,6 +459,7 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n,
|
|||
|
||||
if (h->nlmsg_type == NLMSG_ERROR) {
|
||||
struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(h);
|
||||
|
||||
if (l < sizeof(struct nlmsgerr)) {
|
||||
fprintf(stderr, "ERROR truncated\n");
|
||||
} else if (!err->error) {
|
||||
|
|
@ -545,7 +558,9 @@ int rtnl_listen(struct rtnl_handle *rtnl,
|
|||
return -1;
|
||||
}
|
||||
if (msg.msg_namelen != sizeof(nladdr)) {
|
||||
fprintf(stderr, "Sender address length == %d\n", msg.msg_namelen);
|
||||
fprintf(stderr,
|
||||
"Sender address length == %d\n",
|
||||
msg.msg_namelen);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
|
@ -573,7 +588,9 @@ int rtnl_listen(struct rtnl_handle *rtnl,
|
|||
fprintf(stderr, "Truncated message\n");
|
||||
return -1;
|
||||
}
|
||||
fprintf(stderr, "!!!malformed message: len=%d\n", len);
|
||||
fprintf(stderr,
|
||||
"!!!malformed message: len=%d\n",
|
||||
len);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
|
@ -601,7 +618,7 @@ int rtnl_from_file(FILE *rtnl, rtnl_listen_filter_t handler,
|
|||
int status;
|
||||
struct sockaddr_nl nladdr = { .nl_family = AF_NETLINK };
|
||||
char buf[16384];
|
||||
struct nlmsghdr *h = (void*)buf;
|
||||
struct nlmsghdr *h = (struct nlmsghdr *)buf;
|
||||
|
||||
while (1) {
|
||||
int err, len;
|
||||
|
|
@ -681,7 +698,9 @@ int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data,
|
|||
struct rtattr *rta;
|
||||
|
||||
if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) {
|
||||
fprintf(stderr, "addattr_l ERROR: message exceeded bound of %d\n",maxlen);
|
||||
fprintf(stderr,
|
||||
"addattr_l ERROR: message exceeded bound of %d\n",
|
||||
maxlen);
|
||||
return -1;
|
||||
}
|
||||
rta = NLMSG_TAIL(n);
|
||||
|
|
@ -695,7 +714,9 @@ int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data,
|
|||
int addraw_l(struct nlmsghdr *n, int maxlen, const void *data, int len)
|
||||
{
|
||||
if (NLMSG_ALIGN(n->nlmsg_len) + NLMSG_ALIGN(len) > maxlen) {
|
||||
fprintf(stderr, "addraw_l ERROR: message exceeded bound of %d\n",maxlen);
|
||||
fprintf(stderr,
|
||||
"addraw_l ERROR: message exceeded bound of %d\n",
|
||||
maxlen);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -744,7 +765,9 @@ int rta_addattr32(struct rtattr *rta, int maxlen, int type, __u32 data)
|
|||
struct rtattr *subrta;
|
||||
|
||||
if (RTA_ALIGN(rta->rta_len) + len > maxlen) {
|
||||
fprintf(stderr,"rta_addattr32: Error! max allowed bound %d exceeded\n",maxlen);
|
||||
fprintf(stderr,
|
||||
"rta_addattr32: Error! max allowed bound %d exceeded\n",
|
||||
maxlen);
|
||||
return -1;
|
||||
}
|
||||
subrta = (struct rtattr *)(((char *)rta) + RTA_ALIGN(rta->rta_len));
|
||||
|
|
@ -762,7 +785,9 @@ int rta_addattr_l(struct rtattr *rta, int maxlen, int type,
|
|||
int len = RTA_LENGTH(alen);
|
||||
|
||||
if (RTA_ALIGN(rta->rta_len) + RTA_ALIGN(len) > maxlen) {
|
||||
fprintf(stderr,"rta_addattr_l: Error! max allowed bound %d exceeded\n",maxlen);
|
||||
fprintf(stderr,
|
||||
"rta_addattr_l: Error! max allowed bound %d exceeded\n",
|
||||
maxlen);
|
||||
return -1;
|
||||
}
|
||||
subrta = (struct rtattr *)(((char *)rta) + RTA_ALIGN(rta->rta_len));
|
||||
|
|
@ -822,11 +847,13 @@ int parse_rtattr_flags(struct rtattr *tb[], int max, struct rtattr *rta,
|
|||
rta = RTA_NEXT(rta, len);
|
||||
}
|
||||
if (len)
|
||||
fprintf(stderr, "!!!Deficit %d, rta_len=%d\n", len, rta->rta_len);
|
||||
fprintf(stderr, "!!!Deficit %d, rta_len=%d\n",
|
||||
len, rta->rta_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int parse_rtattr_byindex(struct rtattr *tb[], int max, struct rtattr *rta, int len)
|
||||
int parse_rtattr_byindex(struct rtattr *tb[], int max,
|
||||
struct rtattr *rta, int len)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
|
|
@ -837,7 +864,8 @@ int parse_rtattr_byindex(struct rtattr *tb[], int max, struct rtattr *rta, int l
|
|||
rta = RTA_NEXT(rta, len);
|
||||
}
|
||||
if (len)
|
||||
fprintf(stderr, "!!!Deficit %d, rta_len=%d\n", len, rta->rta_len);
|
||||
fprintf(stderr, "!!!Deficit %d, rta_len=%d\n",
|
||||
len, rta->rta_len);
|
||||
return i;
|
||||
}
|
||||
|
||||
|
|
@ -848,12 +876,15 @@ struct rtattr *parse_rtattr_one(int type, struct rtattr *rta, int len)
|
|||
return rta;
|
||||
rta = RTA_NEXT(rta, len);
|
||||
}
|
||||
|
||||
if (len)
|
||||
fprintf(stderr, "!!!Deficit %d, rta_len=%d\n", len, rta->rta_len);
|
||||
fprintf(stderr, "!!!Deficit %d, rta_len=%d\n",
|
||||
len, rta->rta_len);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int __parse_rtattr_nested_compat(struct rtattr *tb[], int max, struct rtattr *rta,
|
||||
int __parse_rtattr_nested_compat(struct rtattr *tb[], int max,
|
||||
struct rtattr *rta,
|
||||
int len)
|
||||
{
|
||||
if (RTA_PAYLOAD(rta) < len)
|
||||
|
|
|
|||
|
|
@ -100,11 +100,13 @@ __PF(IEEE80211,ieee802.11)
|
|||
__PF(IEEE80211_PRISM,ieee802.11/prism)
|
||||
__PF(IEEE80211_RADIOTAP,ieee802.11/radiotap)
|
||||
__PF(IEEE802154, ieee802.15.4)
|
||||
__PF(IEEE802154_MONITOR, ieee802.15.4/monitor)
|
||||
__PF(PHONET, phonet)
|
||||
__PF(PHONET_PIPE, phonet_pipe)
|
||||
__PF(CAIF, caif)
|
||||
__PF(IP6GRE, gre6)
|
||||
__PF(NETLINK, netlink)
|
||||
__PF(6LOWPAN, 6lowpan)
|
||||
|
||||
__PF(NONE, none)
|
||||
__PF(VOID,void)
|
||||
|
|
|
|||
|
|
@ -559,8 +559,12 @@ const char *rtnl_group_n2a(int id, char *buf, int len)
|
|||
|
||||
for (i = 0; i < 256; i++) {
|
||||
entry = rtnl_group_hash[i];
|
||||
if (entry && entry->id == id)
|
||||
|
||||
while (entry) {
|
||||
if (entry->id == id)
|
||||
return entry->name;
|
||||
entry = entry->next;
|
||||
}
|
||||
}
|
||||
|
||||
snprintf(buf, len, "%d", id);
|
||||
|
|
|
|||
|
|
@ -31,6 +31,9 @@ devlink-dev \- devlink device configuration
|
|||
.RI "[ "
|
||||
.BR mode " { " legacy " | " switchdev " } "
|
||||
.RI "]"
|
||||
.RI "[ "
|
||||
.BR inline-mode " { " none " | " link " | " network " | " transport " } "
|
||||
.RI "]"
|
||||
|
||||
.ti -8
|
||||
.BR "devlink dev eswitch show"
|
||||
|
|
@ -54,7 +57,7 @@ BUS_NAME/BUS_ADDRESS
|
|||
|
||||
.TP
|
||||
.BR mode " { " legacy " | " switchdev " } "
|
||||
set eswitch mode
|
||||
Set eswitch mode
|
||||
|
||||
.I legacy
|
||||
- Legacy SRIOV
|
||||
|
|
@ -62,6 +65,22 @@ set eswitch mode
|
|||
.I switchdev
|
||||
- SRIOV switchdev offloads
|
||||
|
||||
.TP
|
||||
.BR inline-mode " { " none " | " link " | " network " | " transport " } "
|
||||
Some HWs need the VF driver to put part of the packet headers on the TX descriptor so the e-switch can do proper matching and steering.
|
||||
|
||||
.I none
|
||||
- None
|
||||
|
||||
.I link
|
||||
- L2 mode
|
||||
|
||||
.I network
|
||||
- L3 mode
|
||||
|
||||
.I transport
|
||||
- L4 mode
|
||||
|
||||
.SH "EXAMPLES"
|
||||
.PP
|
||||
devlink dev show
|
||||
|
|
|
|||
|
|
@ -30,6 +30,12 @@ ip-l2tp - L2TPv3 static unmanaged tunnel configuration
|
|||
.IR PORT
|
||||
.RB " ]"
|
||||
.br
|
||||
.RB "[ " udp_csum " { " on " | " off " } ]"
|
||||
.br
|
||||
.RB "[ " udp6_csum_tx " { " on " | " off " } ]"
|
||||
.br
|
||||
.RB "[ " udp6_csum_rx " { " on " | " off " } ]"
|
||||
.br
|
||||
.ti -8
|
||||
.BR "ip l2tp add session"
|
||||
.RB "[ " name
|
||||
|
|
@ -51,6 +57,8 @@ ip-l2tp - L2TPv3 static unmanaged tunnel configuration
|
|||
.br
|
||||
.RB "[ " l2spec_type " { " none " | " default " } ]"
|
||||
.br
|
||||
.RB "[ " seq " { " none " | " send " | " recv " | " both " } ]"
|
||||
.br
|
||||
.RB "[ " offset
|
||||
.IR OFFSET
|
||||
.RB " ] [ " peer_offset
|
||||
|
|
@ -154,9 +162,6 @@ tunnels and sessions to be established and provides for detecting and
|
|||
acting upon network failures.
|
||||
.SS ip l2tp add tunnel - add a new tunnel
|
||||
.TP
|
||||
.BI name " NAME "
|
||||
sets the session network interface name. Default is l2tpethN.
|
||||
.TP
|
||||
.BI tunnel_id " ID"
|
||||
set the tunnel id, which is a 32-bit integer value. Uniquely
|
||||
identifies the tunnel. The value used must match the peer_tunnel_id
|
||||
|
|
@ -191,6 +196,33 @@ selected.
|
|||
set the UDP destination port to be used for the tunnel. Must be
|
||||
present when udp encapsulation is selected. Ignored when ip
|
||||
encapsulation is selected.
|
||||
.TP
|
||||
.BI udp_csum " STATE"
|
||||
(IPv4 only) control if IPv4 UDP checksums should be calculated and checked for the
|
||||
encapsulating UDP packets, when UDP encapsulating is selected.
|
||||
Default is
|
||||
.BR off "."
|
||||
.br
|
||||
Valid values are:
|
||||
.BR on ", " off "."
|
||||
.TP
|
||||
.BI udp6_csum_tx " STATE"
|
||||
(IPv6 only) control if IPv6 UDP checksums should be calculated for encapsulating
|
||||
UDP packets, when UDP encapsulating is selected.
|
||||
Default is
|
||||
.BR on "."
|
||||
.br
|
||||
Valid values are:
|
||||
.BR on ", " off "."
|
||||
.TP
|
||||
.BI udp6_csum_rx " STATE"
|
||||
(IPv6 only) control if IPv6 UDP checksums should be checked for the encapsulating
|
||||
UDP packets, when UDP encapsulating is selected.
|
||||
Default is
|
||||
.BR on "."
|
||||
.br
|
||||
Valid values are:
|
||||
.BR on ", " off "."
|
||||
.SS ip l2tp del tunnel - destroy a tunnel
|
||||
.TP
|
||||
.BI tunnel_id " ID"
|
||||
|
|
@ -239,7 +271,20 @@ find in received L2TP packets. Default is to use no cookie.
|
|||
set the layer2specific header type of the session.
|
||||
.br
|
||||
Valid values are:
|
||||
.BR none ", " udp "."
|
||||
.BR none ", " default "."
|
||||
.TP
|
||||
.BI seq " SEQ"
|
||||
controls sequence numbering to prevent or detect out of order packets.
|
||||
.B send
|
||||
puts a sequence number in the default layer2specific header of each
|
||||
outgoing packet.
|
||||
.B recv
|
||||
reorder packets if they are received out of order.
|
||||
Default is
|
||||
.BR none "."
|
||||
.br
|
||||
Valid values are:
|
||||
.BR none ", " send ", " recv ", " both "."
|
||||
.TP
|
||||
.BI offset " OFFSET"
|
||||
sets the byte offset from the L2TP header where user data starts in
|
||||
|
|
|
|||
|
|
@ -135,7 +135,12 @@ ip-link \- network device configuration
|
|||
.IR NAME " ]"
|
||||
.br
|
||||
.RB "[ " addrgenmode " { " eui64 " | " none " | " stable_secret " | " random " } ]"
|
||||
|
||||
.br
|
||||
.RB "[ " macaddr " { " flush " | { " add " | " del " } "
|
||||
.IR MACADDR " | set [ "
|
||||
.IR MACADDR " [ "
|
||||
.IR MACADDR " [ ... ] ] ] } ]"
|
||||
.br
|
||||
|
||||
.ti -8
|
||||
.B ip link show
|
||||
|
|
@ -882,7 +887,7 @@ the following additional arguments are supported:
|
|||
.BI "ip link add link " DEVICE " name " NAME
|
||||
.BR type " { " macvlan " | " macvtap " } "
|
||||
.BR mode " { " private " | " vepa " | " bridge " | " passthru
|
||||
.RB " [ " nopromisc " ] } "
|
||||
.RB " [ " nopromisc " ] | " source " } "
|
||||
|
||||
.in +8
|
||||
.sp
|
||||
|
|
@ -919,6 +924,13 @@ the interface or create vlan interfaces on top of it. By default, this mode
|
|||
forces the underlying interface into promiscuous mode. Passing the
|
||||
.BR nopromisc " flag prevents this, so the promisc flag may be controlled "
|
||||
using standard tools.
|
||||
|
||||
.B mode source
|
||||
- allows one to set a list of allowed mac address, which is used to match
|
||||
against source mac address from received frames on underlying interface. This
|
||||
allows creating mac based VLAN associations, instead of standard port or tag
|
||||
based. The feature is useful to deploy 802.1x mac based behavior,
|
||||
where drivers of underlying interfaces doesn't allows that.
|
||||
.in -8
|
||||
|
||||
.TP
|
||||
|
|
@ -1468,6 +1480,32 @@ the following additional arguments are supported:
|
|||
|
||||
.in -8
|
||||
|
||||
.TP
|
||||
MACVLAN and MACVTAP Support
|
||||
Modify list of allowed macaddr for link in source mode.
|
||||
|
||||
.B "ip link set type { macvlan | macvap } "
|
||||
[
|
||||
.BI macaddr " " "" COMMAND " " MACADDR " ..."
|
||||
]
|
||||
|
||||
Commands:
|
||||
.in +8
|
||||
.B add
|
||||
- add MACADDR to allowed list
|
||||
.sp
|
||||
.B set
|
||||
- replace allowed list
|
||||
.sp
|
||||
.B del
|
||||
- remove MACADDR from allowed list
|
||||
.sp
|
||||
.B flush
|
||||
- flush whole allowed list
|
||||
.sp
|
||||
.in -8
|
||||
|
||||
|
||||
.SS ip link show - display device attributes
|
||||
|
||||
.TP
|
||||
|
|
|
|||
|
|
@ -122,6 +122,9 @@ Display RAW sockets.
|
|||
.B \-x, \-\-unix
|
||||
Display Unix domain sockets (alias for -f unix).
|
||||
.TP
|
||||
.B \-S, \-\-sctp
|
||||
Display SCTP sockets.
|
||||
.TP
|
||||
.B \-f FAMILY, \-\-family=FAMILY
|
||||
Display sockets of type FAMILY.
|
||||
Currently the following families are supported: unix, inet, inet6, link, netlink.
|
||||
|
|
|
|||
|
|
@ -23,8 +23,6 @@ flower \- flow based traffic control filter
|
|||
.R " | { "
|
||||
.BR dst_mac " | " src_mac " } "
|
||||
.IR mac_address " | "
|
||||
.BR eth_type " { " ipv4 " | " ipv6 " | " 802.1Q " | "
|
||||
.IR ETH_TYPE " } | "
|
||||
.B vlan_id
|
||||
.IR VID " | "
|
||||
.B vlan_prio
|
||||
|
|
@ -75,13 +73,6 @@ Do not process filter by hardware.
|
|||
.BI src_mac " mac_address"
|
||||
Match on source or destination MAC address.
|
||||
.TP
|
||||
.BI eth_type " ETH_TYPE"
|
||||
Match on the next protocol.
|
||||
.I ETH_TYPE
|
||||
may be either
|
||||
.BR ipv4 , ipv6 , 802.1Q ,
|
||||
or an unsigned 16bit value in hexadecimal format.
|
||||
.TP
|
||||
.BI vlan_id " VID"
|
||||
Match on vlan tag id.
|
||||
.I VID
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ class-id ] qdisc
|
|||
|
||||
.B tc
|
||||
.RI "[ " OPTIONS " ]"
|
||||
.B filter [ add | change | replace | delete ] dev
|
||||
.B filter [ add | change | replace | delete | get ] dev
|
||||
DEV
|
||||
.B [ parent
|
||||
qdisc-id
|
||||
|
|
@ -575,6 +575,14 @@ replace
|
|||
Performs a nearly atomic remove/add on an existing node id. If the node does not exist yet
|
||||
it is created.
|
||||
|
||||
.TP
|
||||
get
|
||||
Displays a single filter given the interface, parent ID, priority, protocol and handle ID.
|
||||
|
||||
.TP
|
||||
show
|
||||
Displays all filters attached to the given interface. A valid parent ID must be passed.
|
||||
|
||||
.TP
|
||||
link
|
||||
Only available for qdiscs and performs a replace where the node
|
||||
|
|
|
|||
|
|
@ -670,7 +670,7 @@ static void usage(void)
|
|||
" -n, --nooutput do history only\n"
|
||||
" -p, --pretty pretty print\n"
|
||||
" -r, --reset reset history\n"
|
||||
" -s, --noupdate don\'t update history\n"
|
||||
" -s, --noupdate don't update history\n"
|
||||
" -t, --interval=SECS report average over the last SECS\n"
|
||||
" -V, --version output version information\n"
|
||||
" -z, --zeros show entries with zero activity\n");
|
||||
|
|
|
|||
|
|
@ -533,7 +533,7 @@ static void usage(void)
|
|||
" -n, --nooutput do history only\n"
|
||||
" -p, --pretty pretty print\n"
|
||||
" -r, --reset reset history\n"
|
||||
" -s, --noupdate don\'t update history\n"
|
||||
" -s, --noupdate don't update history\n"
|
||||
" -t, --interval=SECS report average over the last SECS\n"
|
||||
" -V, --version output version information\n"
|
||||
" -z, --zeros show entries with zero activity\n");
|
||||
|
|
|
|||
213
misc/ss.c
213
misc/ss.c
|
|
@ -43,6 +43,7 @@
|
|||
#include <linux/filter.h>
|
||||
#include <linux/packet_diag.h>
|
||||
#include <linux/netlink_diag.h>
|
||||
#include <linux/sctp.h>
|
||||
|
||||
#define MAGIC_SEQ 123456
|
||||
|
||||
|
|
@ -102,6 +103,7 @@ int show_header = 1;
|
|||
/* If show_users & show_proc_ctx only do user_ent_hash_build() once */
|
||||
int user_ent_hash_build_init;
|
||||
int follow_events;
|
||||
int sctp_ino;
|
||||
|
||||
int netid_width;
|
||||
int state_width;
|
||||
|
|
@ -111,6 +113,7 @@ int serv_width;
|
|||
int screen_width;
|
||||
|
||||
static const char *TCP_PROTO = "tcp";
|
||||
static const char *SCTP_PROTO = "sctp";
|
||||
static const char *UDP_PROTO = "udp";
|
||||
static const char *RAW_PROTO = "raw";
|
||||
static const char *dg_proto;
|
||||
|
|
@ -126,13 +129,15 @@ enum {
|
|||
PACKET_DG_DB,
|
||||
PACKET_R_DB,
|
||||
NETLINK_DB,
|
||||
SCTP_DB,
|
||||
MAX_DB
|
||||
};
|
||||
|
||||
#define PACKET_DBM ((1<<PACKET_DG_DB)|(1<<PACKET_R_DB))
|
||||
#define UNIX_DBM ((1<<UNIX_DG_DB)|(1<<UNIX_ST_DB)|(1<<UNIX_SQ_DB))
|
||||
#define ALL_DB ((1<<MAX_DB)-1)
|
||||
#define INET_DBM ((1<<TCP_DB)|(1<<UDP_DB)|(1<<DCCP_DB)|(1<<RAW_DB))
|
||||
#define INET_L4_DBM ((1<<TCP_DB)|(1<<UDP_DB)|(1<<DCCP_DB)|(1<<SCTP_DB))
|
||||
#define INET_DBM (INET_L4_DBM | (1<<RAW_DB))
|
||||
|
||||
enum {
|
||||
SS_UNKNOWN,
|
||||
|
|
@ -150,6 +155,17 @@ enum {
|
|||
SS_MAX
|
||||
};
|
||||
|
||||
enum {
|
||||
SCTP_STATE_CLOSED = 0,
|
||||
SCTP_STATE_COOKIE_WAIT = 1,
|
||||
SCTP_STATE_COOKIE_ECHOED = 2,
|
||||
SCTP_STATE_ESTABLISHED = 3,
|
||||
SCTP_STATE_SHUTDOWN_PENDING = 4,
|
||||
SCTP_STATE_SHUTDOWN_SENT = 5,
|
||||
SCTP_STATE_SHUTDOWN_RECEIVED = 6,
|
||||
SCTP_STATE_SHUTDOWN_ACK_SENT = 7,
|
||||
};
|
||||
|
||||
#define SS_ALL ((1 << SS_MAX) - 1)
|
||||
#define SS_CONN (SS_ALL & ~((1<<SS_LISTEN)|(1<<SS_CLOSE)|(1<<SS_TIME_WAIT)|(1<<SS_SYN_RECV)))
|
||||
|
||||
|
|
@ -204,6 +220,10 @@ static const struct filter default_dbs[MAX_DB] = {
|
|||
.states = (1 << SS_CLOSE),
|
||||
.families = (1 << AF_NETLINK),
|
||||
},
|
||||
[SCTP_DB] = {
|
||||
.states = SS_CONN,
|
||||
.families = (1 << AF_INET) | (1 << AF_INET6),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct filter default_afs[AF_MAX] = {
|
||||
|
|
@ -264,6 +284,7 @@ static void filter_default_dbs(struct filter *f)
|
|||
filter_db_set(f, PACKET_R_DB);
|
||||
filter_db_set(f, PACKET_DG_DB);
|
||||
filter_db_set(f, NETLINK_DB);
|
||||
filter_db_set(f, SCTP_DB);
|
||||
}
|
||||
|
||||
static void filter_states_set(struct filter *f, int states)
|
||||
|
|
@ -705,6 +726,17 @@ static const char *sstate_name[] = {
|
|||
[SS_CLOSING] = "CLOSING",
|
||||
};
|
||||
|
||||
static const char *sctp_sstate_name[] = {
|
||||
[SCTP_STATE_CLOSED] = "CLOSED",
|
||||
[SCTP_STATE_COOKIE_WAIT] = "COOKIE_WAIT",
|
||||
[SCTP_STATE_COOKIE_ECHOED] = "COOKIE_ECHOED",
|
||||
[SCTP_STATE_ESTABLISHED] = "ESTAB",
|
||||
[SCTP_STATE_SHUTDOWN_PENDING] = "SHUTDOWN_PENDING",
|
||||
[SCTP_STATE_SHUTDOWN_SENT] = "SHUTDOWN_SENT",
|
||||
[SCTP_STATE_SHUTDOWN_RECEIVED] = "SHUTDOWN_RECEIVED",
|
||||
[SCTP_STATE_SHUTDOWN_ACK_SENT] = "ACK_SENT",
|
||||
};
|
||||
|
||||
static const char *sstate_namel[] = {
|
||||
"UNKNOWN",
|
||||
[SS_ESTABLISHED] = "established",
|
||||
|
|
@ -793,12 +825,30 @@ struct tcpstat {
|
|||
struct tcp_bbr_info *bbr_info;
|
||||
};
|
||||
|
||||
/* SCTP assocs share the same inode number with their parent endpoint. So if we
|
||||
* have seen the inode number before, it must be an assoc instead of the next
|
||||
* endpoint. */
|
||||
static bool is_sctp_assoc(struct sockstat *s, const char *sock_name)
|
||||
{
|
||||
if (strcmp(sock_name, "sctp"))
|
||||
return false;
|
||||
if (!sctp_ino || sctp_ino != s->ino)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void sock_state_print(struct sockstat *s, const char *sock_name)
|
||||
{
|
||||
if (netid_width)
|
||||
printf("%-*s ", netid_width, sock_name);
|
||||
if (state_width)
|
||||
printf("%-*s ", netid_width,
|
||||
is_sctp_assoc(s, sock_name) ? "" : sock_name);
|
||||
if (state_width) {
|
||||
if (is_sctp_assoc(s, sock_name))
|
||||
printf("`- %-*s ", state_width - 3,
|
||||
sctp_sstate_name[s->state]);
|
||||
else
|
||||
printf("%-*s ", state_width, sstate_name[s->state]);
|
||||
}
|
||||
|
||||
printf("%-6d %-6d ", s->rq, s->wq);
|
||||
}
|
||||
|
|
@ -908,6 +958,8 @@ static void init_service_resolver(void)
|
|||
c->proto = TCP_PROTO;
|
||||
else if (strcmp(proto, UDP_PROTO) == 0)
|
||||
c->proto = UDP_PROTO;
|
||||
else if (strcmp(proto, SCTP_PROTO) == 0)
|
||||
c->proto = SCTP_PROTO;
|
||||
else
|
||||
c->proto = NULL;
|
||||
c->next = rlist;
|
||||
|
|
@ -1679,6 +1731,8 @@ static char *proto_name(int protocol)
|
|||
return "udp";
|
||||
case IPPROTO_TCP:
|
||||
return "tcp";
|
||||
case IPPROTO_SCTP:
|
||||
return "sctp";
|
||||
case IPPROTO_DCCP:
|
||||
return "dccp";
|
||||
}
|
||||
|
|
@ -1771,6 +1825,56 @@ static char *sprint_bw(char *buf, double bw)
|
|||
return buf;
|
||||
}
|
||||
|
||||
static void sctp_stats_print(struct sctp_info *s)
|
||||
{
|
||||
if (s->sctpi_tag)
|
||||
printf(" tag:%x", s->sctpi_tag);
|
||||
if (s->sctpi_state)
|
||||
printf(" state:%s", sctp_sstate_name[s->sctpi_state]);
|
||||
if (s->sctpi_rwnd)
|
||||
printf(" rwnd:%d", s->sctpi_rwnd);
|
||||
if (s->sctpi_unackdata)
|
||||
printf(" unackdata:%d", s->sctpi_unackdata);
|
||||
if (s->sctpi_penddata)
|
||||
printf(" penddata:%d", s->sctpi_penddata);
|
||||
if (s->sctpi_instrms)
|
||||
printf(" instrms:%d", s->sctpi_instrms);
|
||||
if (s->sctpi_outstrms)
|
||||
printf(" outstrms:%d", s->sctpi_outstrms);
|
||||
if (s->sctpi_inqueue)
|
||||
printf(" inqueue:%d", s->sctpi_inqueue);
|
||||
if (s->sctpi_outqueue)
|
||||
printf(" outqueue:%d", s->sctpi_outqueue);
|
||||
if (s->sctpi_overall_error)
|
||||
printf(" overerr:%d", s->sctpi_overall_error);
|
||||
if (s->sctpi_max_burst)
|
||||
printf(" maxburst:%d", s->sctpi_max_burst);
|
||||
if (s->sctpi_maxseg)
|
||||
printf(" maxseg:%d", s->sctpi_maxseg);
|
||||
if (s->sctpi_peer_rwnd)
|
||||
printf(" prwnd:%d", s->sctpi_peer_rwnd);
|
||||
if (s->sctpi_peer_tag)
|
||||
printf(" ptag:%x", s->sctpi_peer_tag);
|
||||
if (s->sctpi_peer_capable)
|
||||
printf(" pcapable:%d", s->sctpi_peer_capable);
|
||||
if (s->sctpi_peer_sack)
|
||||
printf(" psack:%d", s->sctpi_peer_sack);
|
||||
if (s->sctpi_s_autoclose)
|
||||
printf(" autoclose:%d", s->sctpi_s_autoclose);
|
||||
if (s->sctpi_s_adaptation_ind)
|
||||
printf(" adapind:%d", s->sctpi_s_adaptation_ind);
|
||||
if (s->sctpi_s_pd_point)
|
||||
printf(" pdpoint:%d", s->sctpi_s_pd_point);
|
||||
if (s->sctpi_s_nodelay)
|
||||
printf(" nodealy:%d", s->sctpi_s_nodelay);
|
||||
if (s->sctpi_s_disable_fragments)
|
||||
printf(" nofrag:%d", s->sctpi_s_disable_fragments);
|
||||
if (s->sctpi_s_v4mapped)
|
||||
printf(" v4mapped:%d", s->sctpi_s_v4mapped);
|
||||
if (s->sctpi_s_frag_interleave)
|
||||
printf(" fraginl:%d", s->sctpi_s_frag_interleave);
|
||||
}
|
||||
|
||||
static void tcp_stats_print(struct tcpstat *s)
|
||||
{
|
||||
char b1[64];
|
||||
|
|
@ -1902,6 +2006,13 @@ static void tcp_timer_print(struct tcpstat *s)
|
|||
}
|
||||
}
|
||||
|
||||
static void sctp_timer_print(struct tcpstat *s)
|
||||
{
|
||||
if (s->timer)
|
||||
printf(" timer:(T3_RTX,%s,%d)",
|
||||
print_ms_timer(s->timeout), s->retrans);
|
||||
}
|
||||
|
||||
static int tcp_show_line(char *line, const struct filter *f, int family)
|
||||
{
|
||||
int rto = 0, ato = 0;
|
||||
|
|
@ -2168,6 +2279,64 @@ static void tcp_show_info(const struct nlmsghdr *nlh, struct inet_diag_msg *r,
|
|||
}
|
||||
}
|
||||
|
||||
static const char *format_host_sa(struct sockaddr_storage *sa)
|
||||
{
|
||||
union {
|
||||
struct sockaddr_in sin;
|
||||
struct sockaddr_in6 sin6;
|
||||
} *saddr = (void *)sa;
|
||||
|
||||
switch (sa->ss_family) {
|
||||
case AF_INET:
|
||||
return format_host(AF_INET, 4, &saddr->sin.sin_addr);
|
||||
case AF_INET6:
|
||||
return format_host(AF_INET6, 16, &saddr->sin6.sin6_addr);
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
static void sctp_show_info(const struct nlmsghdr *nlh, struct inet_diag_msg *r,
|
||||
struct rtattr *tb[])
|
||||
{
|
||||
struct sockaddr_storage *sa;
|
||||
int len;
|
||||
|
||||
print_skmeminfo(tb, INET_DIAG_SKMEMINFO);
|
||||
|
||||
if (tb[INET_DIAG_LOCALS]) {
|
||||
len = RTA_PAYLOAD(tb[INET_DIAG_LOCALS]);
|
||||
sa = RTA_DATA(tb[INET_DIAG_LOCALS]);
|
||||
|
||||
printf("locals:%s", format_host_sa(sa));
|
||||
for (sa++, len -= sizeof(*sa); len > 0; sa++, len -= sizeof(*sa))
|
||||
printf(",%s", format_host_sa(sa));
|
||||
|
||||
}
|
||||
if (tb[INET_DIAG_PEERS]) {
|
||||
len = RTA_PAYLOAD(tb[INET_DIAG_PEERS]);
|
||||
sa = RTA_DATA(tb[INET_DIAG_PEERS]);
|
||||
|
||||
printf(" peers:%s", format_host_sa(sa));
|
||||
for (sa++, len -= sizeof(*sa); len > 0; sa++, len -= sizeof(*sa))
|
||||
printf(",%s", format_host_sa(sa));
|
||||
}
|
||||
if (tb[INET_DIAG_INFO]) {
|
||||
struct sctp_info *info;
|
||||
len = RTA_PAYLOAD(tb[INET_DIAG_INFO]);
|
||||
|
||||
/* workaround for older kernels with less fields */
|
||||
if (len < sizeof(*info)) {
|
||||
info = alloca(sizeof(*info));
|
||||
memcpy(info, RTA_DATA(tb[INET_DIAG_INFO]), len);
|
||||
memset((char *)info + len, 0, sizeof(*info) - len);
|
||||
} else
|
||||
info = RTA_DATA(tb[INET_DIAG_INFO]);
|
||||
|
||||
sctp_stats_print(info);
|
||||
}
|
||||
}
|
||||
|
||||
static void parse_diag_msg(struct nlmsghdr *nlh, struct sockstat *s)
|
||||
{
|
||||
struct rtattr *tb[INET_DIAG_MAX+1];
|
||||
|
|
@ -2221,6 +2390,9 @@ static int inet_show_sock(struct nlmsghdr *nlh,
|
|||
t.timer = r->idiag_timer;
|
||||
t.timeout = r->idiag_expires;
|
||||
t.retrans = r->idiag_retrans;
|
||||
if (protocol == IPPROTO_SCTP)
|
||||
sctp_timer_print(&t);
|
||||
else
|
||||
tcp_timer_print(&t);
|
||||
}
|
||||
|
||||
|
|
@ -2242,8 +2414,12 @@ static int inet_show_sock(struct nlmsghdr *nlh,
|
|||
|
||||
if (show_mem || show_tcpinfo) {
|
||||
printf("\n\t");
|
||||
if (protocol == IPPROTO_SCTP)
|
||||
sctp_show_info(nlh, r, tb);
|
||||
else
|
||||
tcp_show_info(nlh, r, tb);
|
||||
}
|
||||
sctp_ino = s->ino;
|
||||
|
||||
printf("\n");
|
||||
return 0;
|
||||
|
|
@ -2627,6 +2803,17 @@ outerr:
|
|||
} while (0);
|
||||
}
|
||||
|
||||
static int sctp_show(struct filter *f)
|
||||
{
|
||||
if (!filter_af_get(f, AF_INET) && !filter_af_get(f, AF_INET6))
|
||||
return 0;
|
||||
|
||||
if (!getenv("PROC_NET_SCTP") && !getenv("PROC_ROOT")
|
||||
&& inet_show_netlink(f, NULL, IPPROTO_SCTP) == 0)
|
||||
return 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dgram_show_line(char *line, const struct filter *f, int family)
|
||||
{
|
||||
|
|
@ -2895,7 +3082,9 @@ static int unix_show_sock(const struct sockaddr_nl *addr, struct nlmsghdr *nlh,
|
|||
memcpy(name, RTA_DATA(tb[UNIX_DIAG_NAME]), len);
|
||||
name[len] = '\0';
|
||||
if (name[0] == '\0')
|
||||
name[0] = '@';
|
||||
for (int i = 0; i < len; i++)
|
||||
if (name[i] == '\0')
|
||||
name[i] = '@';
|
||||
stat.name = &name[0];
|
||||
memcpy(stat.local.data, &stat.name, sizeof(stat.name));
|
||||
}
|
||||
|
|
@ -3738,6 +3927,7 @@ static void _usage(FILE *dest)
|
|||
" -6, --ipv6 display only IP version 6 sockets\n"
|
||||
" -0, --packet display PACKET sockets\n"
|
||||
" -t, --tcp display only TCP sockets\n"
|
||||
" -S, --sctp display only SCTP sockets\n"
|
||||
" -u, --udp display only UDP sockets\n"
|
||||
" -d, --dccp display only DCCP sockets\n"
|
||||
" -w, --raw display only RAW sockets\n"
|
||||
|
|
@ -3820,6 +4010,7 @@ static const struct option long_opts[] = {
|
|||
{ "events", 0, 0, 'E' },
|
||||
{ "dccp", 0, 0, 'd' },
|
||||
{ "tcp", 0, 0, 't' },
|
||||
{ "sctp", 0, 0, 'S' },
|
||||
{ "udp", 0, 0, 'u' },
|
||||
{ "raw", 0, 0, 'w' },
|
||||
{ "unix", 0, 0, 'x' },
|
||||
|
|
@ -3855,7 +4046,8 @@ int main(int argc, char *argv[])
|
|||
int ch;
|
||||
int state_filter = 0;
|
||||
|
||||
while ((ch = getopt_long(argc, argv, "dhaletuwxnro460spbEf:miA:D:F:vVzZN:KH",
|
||||
while ((ch = getopt_long(argc, argv,
|
||||
"dhaletuwxnro460spbEf:miA:D:F:vVzZN:KHS",
|
||||
long_opts, NULL)) != EOF) {
|
||||
switch (ch) {
|
||||
case 'n':
|
||||
|
|
@ -3894,6 +4086,9 @@ int main(int argc, char *argv[])
|
|||
case 't':
|
||||
filter_db_set(¤t_filter, TCP_DB);
|
||||
break;
|
||||
case 'S':
|
||||
filter_db_set(¤t_filter, SCTP_DB);
|
||||
break;
|
||||
case 'u':
|
||||
filter_db_set(¤t_filter, UDP_DB);
|
||||
break;
|
||||
|
|
@ -3958,6 +4153,7 @@ int main(int argc, char *argv[])
|
|||
filter_db_set(¤t_filter, UDP_DB);
|
||||
filter_db_set(¤t_filter, DCCP_DB);
|
||||
filter_db_set(¤t_filter, TCP_DB);
|
||||
filter_db_set(¤t_filter, SCTP_DB);
|
||||
filter_db_set(¤t_filter, RAW_DB);
|
||||
} else if (strcmp(p, "udp") == 0) {
|
||||
filter_db_set(¤t_filter, UDP_DB);
|
||||
|
|
@ -3965,6 +4161,8 @@ int main(int argc, char *argv[])
|
|||
filter_db_set(¤t_filter, DCCP_DB);
|
||||
} else if (strcmp(p, "tcp") == 0) {
|
||||
filter_db_set(¤t_filter, TCP_DB);
|
||||
} else if (strcmp(p, "sctp") == 0) {
|
||||
filter_db_set(¤t_filter, SCTP_DB);
|
||||
} else if (strcmp(p, "raw") == 0) {
|
||||
filter_db_set(¤t_filter, RAW_DB);
|
||||
} else if (strcmp(p, "unix") == 0) {
|
||||
|
|
@ -4089,10 +4287,9 @@ int main(int argc, char *argv[])
|
|||
filter_merge_defaults(¤t_filter);
|
||||
|
||||
if (resolve_services && resolve_hosts &&
|
||||
(current_filter.dbs&(UNIX_DBM|(1<<TCP_DB)|(1<<UDP_DB)|(1<<DCCP_DB))))
|
||||
(current_filter.dbs & (UNIX_DBM|INET_L4_DBM)))
|
||||
init_service_resolver();
|
||||
|
||||
|
||||
if (current_filter.dbs == 0) {
|
||||
fprintf(stderr, "ss: no socket tables to show with such filter.\n");
|
||||
exit(0);
|
||||
|
|
@ -4205,6 +4402,8 @@ int main(int argc, char *argv[])
|
|||
tcp_show(¤t_filter, IPPROTO_TCP);
|
||||
if (current_filter.dbs & (1<<DCCP_DB))
|
||||
tcp_show(¤t_filter, IPPROTO_DCCP);
|
||||
if (current_filter.dbs & (1<<SCTP_DB))
|
||||
sctp_show(¤t_filter);
|
||||
|
||||
if (show_users || show_proc_ctx || show_sock_ctx)
|
||||
user_ent_destroy();
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@ static void explain(void)
|
|||
" vlan_ethtype [ ipv4 | ipv6 | ETH-TYPE ] |\n"
|
||||
" dst_mac MAC-ADDR |\n"
|
||||
" src_mac MAC-ADDR |\n"
|
||||
" [ipv4 | ipv6 ] |\n"
|
||||
" ip_proto [tcp | udp | IP-PROTO ] |\n"
|
||||
" dst_ip [ IPV4-ADDR | IPV6-ADDR ] |\n"
|
||||
" src_ip [ IPV4-ADDR | IPV6-ADDR ] |\n"
|
||||
|
|
@ -46,7 +45,7 @@ static void explain(void)
|
|||
" FILTERID := X:Y:Z\n"
|
||||
" ACTION-SPEC := ... look at individual actions\n"
|
||||
"\n"
|
||||
"NOTE: CLASSID, ETH-TYPE, IP-PROTO are parsed as hexadecimal input.\n"
|
||||
"NOTE: CLASSID, IP-PROTO are parsed as hexadecimal input.\n"
|
||||
"NOTE: There can be only used one mask per one prio. If user needs\n"
|
||||
" to specify different mask, he has to use different prio.\n");
|
||||
}
|
||||
|
|
|
|||
17
tc/f_fw.c
17
tc/f_fw.c
|
|
@ -25,10 +25,19 @@
|
|||
|
||||
static void explain(void)
|
||||
{
|
||||
fprintf(stderr, "Usage: ... fw [ classid CLASSID ] [ action ACTION_SPEC ]\n");
|
||||
fprintf(stderr, " ACTION_SPEC := ... look at individual actions\n");
|
||||
fprintf(stderr, " CLASSID := X:Y\n");
|
||||
fprintf(stderr, "\nNOTE: CLASSID is parsed as hexadecimal input.\n");
|
||||
fprintf(stderr,
|
||||
"Usage: ... fw [ classid CLASSID ] [ indev DEV ] [ action ACTION_SPEC ]\n");
|
||||
fprintf(stderr,
|
||||
" CLASSID := Push matching packets to the class identified by CLASSID with format X:Y\n");
|
||||
fprintf(stderr,
|
||||
" CLASSID is parsed as hexadecimal input.\n");
|
||||
fprintf(stderr,
|
||||
" DEV := specify device for incoming device classification.\n");
|
||||
fprintf(stderr,
|
||||
" ACTION_SPEC := Apply an action on matching packets.\n");
|
||||
fprintf(stderr,
|
||||
" NOTE: handle is represented as HANDLE[/FWMASK].\n");
|
||||
fprintf(stderr, " FWMASK is 0xffffffff by default.\n");
|
||||
}
|
||||
|
||||
static int fw_parse_opt(struct filter_util *qu, char *handle, int argc, char **argv, struct nlmsghdr *n)
|
||||
|
|
|
|||
|
|
@ -226,6 +226,16 @@ int print_filter(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
|
|||
if (n->nlmsg_type == RTM_DELTFILTER)
|
||||
fprintf(fp, "deleted ");
|
||||
|
||||
if (n->nlmsg_type == RTM_NEWTFILTER &&
|
||||
(n->nlmsg_flags & NLM_F_CREATE) &&
|
||||
!(n->nlmsg_flags & NLM_F_EXCL))
|
||||
fprintf(fp, "replaced ");
|
||||
|
||||
if (n->nlmsg_type == RTM_NEWTFILTER &&
|
||||
(n->nlmsg_flags & NLM_F_CREATE) &&
|
||||
(n->nlmsg_flags & NLM_F_EXCL))
|
||||
fprintf(fp, "added ");
|
||||
|
||||
fprintf(fp, "filter ");
|
||||
if (!filter_ifindex || filter_ifindex != t->tcm_ifindex)
|
||||
fprintf(fp, "dev %s ", ll_index_to_name(t->tcm_ifindex));
|
||||
|
|
|
|||
|
|
@ -182,7 +182,8 @@ static int tc_qdisc_modify(int cmd, unsigned int flags, int argc, char **argv)
|
|||
|
||||
ll_init_map(&rth);
|
||||
|
||||
if ((idx = ll_name_to_index(d)) == 0) {
|
||||
idx = ll_name_to_index(d);
|
||||
if (idx == 0) {
|
||||
fprintf(stderr, "Cannot find device \"%s\"\n", d);
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -198,8 +199,7 @@ static int tc_qdisc_modify(int cmd, unsigned int flags, int argc, char **argv)
|
|||
static int filter_ifindex;
|
||||
|
||||
int print_qdisc(const struct sockaddr_nl *who,
|
||||
struct nlmsghdr *n,
|
||||
void *arg)
|
||||
struct nlmsghdr *n, void *arg)
|
||||
{
|
||||
FILE *fp = (FILE *)arg;
|
||||
struct tcmsg *t = NLMSG_DATA(n);
|
||||
|
|
@ -231,21 +231,29 @@ int print_qdisc(const struct sockaddr_nl *who,
|
|||
if (n->nlmsg_type == RTM_DELQDISC)
|
||||
fprintf(fp, "deleted ");
|
||||
|
||||
fprintf(fp, "qdisc %s %x: ", rta_getattr_str(tb[TCA_KIND]), t->tcm_handle>>16);
|
||||
if (show_raw)
|
||||
fprintf(fp, "qdisc %s %x:[%08x] ",
|
||||
rta_getattr_str(tb[TCA_KIND]),
|
||||
t->tcm_handle >> 16, t->tcm_handle);
|
||||
else
|
||||
fprintf(fp, "qdisc %s %x: ", rta_getattr_str(tb[TCA_KIND]),
|
||||
t->tcm_handle >> 16);
|
||||
|
||||
if (filter_ifindex == 0)
|
||||
fprintf(fp, "dev %s ", ll_index_to_name(t->tcm_ifindex));
|
||||
|
||||
if (t->tcm_parent == TC_H_ROOT)
|
||||
fprintf(fp, "root ");
|
||||
else if (t->tcm_parent) {
|
||||
print_tc_classid(abuf, sizeof(abuf), t->tcm_parent);
|
||||
fprintf(fp, "parent %s ", abuf);
|
||||
}
|
||||
if (t->tcm_info != 1) {
|
||||
fprintf(fp, "refcnt %d ", t->tcm_info);
|
||||
}
|
||||
/* pfifo_fast is generic enough to warrant the hardcoding --JHS */
|
||||
|
||||
if (0 == strcmp("pfifo_fast", RTA_DATA(tb[TCA_KIND])))
|
||||
if (t->tcm_info != 1)
|
||||
fprintf(fp, "refcnt %d ", t->tcm_info);
|
||||
|
||||
/* pfifo_fast is generic enough to warrant the hardcoding --JHS */
|
||||
if (strcmp("pfifo_fast", RTA_DATA(tb[TCA_KIND])) == 0)
|
||||
q = get_qdisc_kind("prio");
|
||||
else
|
||||
q = get_qdisc_kind(RTA_DATA(tb[TCA_KIND]));
|
||||
|
|
@ -257,10 +265,12 @@ int print_qdisc(const struct sockaddr_nl *who,
|
|||
fprintf(fp, "[cannot parse qdisc parameters]");
|
||||
}
|
||||
fprintf(fp, "\n");
|
||||
|
||||
if (show_details && tb[TCA_STAB]) {
|
||||
print_size_table(fp, " ", tb[TCA_STAB]);
|
||||
fprintf(fp, "\n");
|
||||
}
|
||||
|
||||
if (show_stats) {
|
||||
struct rtattr *xstats = NULL;
|
||||
|
||||
|
|
@ -307,7 +317,8 @@ static int tc_qdisc_list(int argc, char **argv)
|
|||
ll_init_map(&rth);
|
||||
|
||||
if (d[0]) {
|
||||
if ((t.tcm_ifindex = ll_name_to_index(d)) == 0) {
|
||||
t.tcm_ifindex = ll_name_to_index(d);
|
||||
if (t.tcm_ifindex == 0) {
|
||||
fprintf(stderr, "Cannot find device \"%s\"\n", d);
|
||||
return 1;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue