* [PATCH 2/2] ss: Unify inet sockets output
From: Vadim Kochan @ 2015-01-20 14:14 UTC (permalink / raw)
To: netdev; +Cc: Vadim Kochan
In-Reply-To: <1421763264-8954-1-git-send-email-vadim4j@gmail.com>
From: Vadim Kochan <vadim4j@gmail.com>
Signed-off-by: Vadim Kochan <vadim4j@gmail.com>
---
misc/ss.c | 677 ++++++++++++++++++++++++++++++++------------------------------
1 file changed, 355 insertions(+), 322 deletions(-)
diff --git a/misc/ss.c b/misc/ss.c
index 3764f3a..ef1fc9d 100644
--- a/misc/ss.c
+++ b/misc/ss.c
@@ -689,23 +689,59 @@ static const char *sstate_namel[] = {
[SS_CLOSING] = "closing",
};
+struct dctcpstat
+{
+ unsigned int ce_state;
+ unsigned int alpha;
+ unsigned int ab_ecn;
+ unsigned int ab_tot;
+ bool enabled;
+};
+
struct tcpstat
{
- inet_prefix local;
- inet_prefix remote;
- int lport;
- int rport;
- int state;
- int rq, wq;
- int timer;
- int timeout;
- int retrs;
- unsigned ino;
- int probes;
- unsigned uid;
- int refcnt;
- unsigned long long sk;
- int rto, ato, qack, cwnd, ssthresh;
+ inet_prefix local;
+ inet_prefix remote;
+ int lport;
+ int rport;
+ int state;
+ int rq, wq;
+ unsigned ino;
+ unsigned uid;
+ int refcnt;
+ unsigned int iface;
+ unsigned long long sk;
+ int timer;
+ int timeout;
+ int probes;
+ char *cong_alg;
+ double rto, ato, rtt, rttvar;
+ int qack, cwnd, ssthresh, backoff;
+ double send_bps;
+ int snd_wscale;
+ int rcv_wscale;
+ int mss;
+ unsigned int lastsnd;
+ unsigned int lastrcv;
+ unsigned int lastack;
+ double pacing_rate;
+ double pacing_rate_max;
+ unsigned int unacked;
+ unsigned int retrans;
+ unsigned int retrans_total;
+ unsigned int lost;
+ unsigned int sacked;
+ unsigned int fackets;
+ unsigned int reordering;
+ double rcv_rtt;
+ int rcv_space;
+ bool has_ts_opt;
+ bool has_sack_opt;
+ bool has_ecn_opt;
+ bool has_ecnseen_opt;
+ bool has_fastopen_opt;
+ bool has_wscale_opt;
+ struct dctcpstat *dctcp;
};
static const char *tmr_name[] = {
@@ -744,12 +780,6 @@ static const char *print_ms_timer(int timeout)
return buf;
}
-static const char *print_hz_timer(int timeout)
-{
- int hz = get_user_hz();
- return print_ms_timer(((timeout*1000) + hz-1)/hz);
-}
-
struct scache
{
struct scache *next;
@@ -1439,55 +1469,220 @@ out:
return res;
}
-static int tcp_show_line(char *line, const struct filter *f, int family)
+static char *proto_name(int protocol)
+{
+ switch (protocol) {
+ case IPPROTO_UDP:
+ return "udp";
+ case IPPROTO_TCP:
+ return "tcp";
+ case IPPROTO_DCCP:
+ return "dccp";
+ }
+
+ return "???";
+}
+
+static void inet_stats_print(struct tcpstat *s, int protocol)
+{
+ char *buf = NULL;
+
+ if (netid_width)
+ printf("%-*s ", netid_width, proto_name(protocol));
+ if (state_width)
+ printf("%-*s ", state_width, sstate_name[s->state]);
+
+ printf("%-6d %-6d ", s->rq, s->wq);
+
+ formatted_print(&s->local, s->lport, s->iface);
+ formatted_print(&s->remote, s->rport, 0);
+
+ if (show_options) {
+ if (s->timer) {
+ if (s->timer > 4)
+ s->timer = 5;
+ printf(" timer:(%s,%s,%d)",
+ tmr_name[s->timer],
+ print_ms_timer(s->timeout),
+ s->retrans);
+ }
+ }
+
+ if (show_proc_ctx || show_sock_ctx) {
+ if (find_entry(s->ino, &buf,
+ (show_proc_ctx & show_sock_ctx) ?
+ PROC_SOCK_CTX : PROC_CTX) > 0) {
+ printf(" users:(%s)", buf);
+ free(buf);
+ }
+ } else if (show_users) {
+ if (find_entry(s->ino, &buf, USERS) > 0) {
+ printf(" users:(%s)", buf);
+ free(buf);
+ }
+ }
+}
+
+static int proc_parse_inet_addr(char *loc, char *rem, int family, struct tcpstat *s)
+{
+ s->local.family = s->remote.family = family;
+ if (family == AF_INET) {
+ sscanf(loc, "%x:%x", s->local.data, (unsigned*)&s->lport);
+ sscanf(rem, "%x:%x", s->remote.data, (unsigned*)&s->rport);
+ s->local.bytelen = s->remote.bytelen = 4;
+ return 0;
+ } else {
+ sscanf(loc, "%08x%08x%08x%08x:%x",
+ s->local.data,
+ s->local.data + 1,
+ s->local.data + 2,
+ s->local.data + 3,
+ &s->lport);
+ sscanf(rem, "%08x%08x%08x%08x:%x",
+ s->remote.data,
+ s->remote.data + 1,
+ s->remote.data + 2,
+ s->remote.data + 3,
+ &s->rport);
+ s->local.bytelen = s->remote.bytelen = 16;
+ return 0;
+ }
+ return -1;
+}
+
+static int proc_inet_split_line(char *line, char **loc, char **rem, char **data)
{
- struct tcpstat s;
- char *loc, *rem, *data;
- char opt[256];
- int n;
char *p;
if ((p = strchr(line, ':')) == NULL)
return -1;
- loc = p+2;
- if ((p = strchr(loc, ':')) == NULL)
+ *loc = p+2;
+ if ((p = strchr(*loc, ':')) == NULL)
return -1;
- p[5] = 0;
- rem = p+6;
- if ((p = strchr(rem, ':')) == NULL)
+ p[5] = 0;
+ *rem = p+6;
+ if ((p = strchr(*rem, ':')) == NULL)
return -1;
+
p[5] = 0;
- data = p+6;
+ *data = p+6;
+ return 0;
+}
- do {
- int state = (data[1] >= 'A') ? (data[1] - 'A' + 10) : (data[1] - '0');
+static char *sprint_bw(char *buf, double bw)
+{
+ if (bw > 1000000.)
+ sprintf(buf,"%.1fM", bw / 1000000.);
+ else if (bw > 1000.)
+ sprintf(buf,"%.1fK", bw / 1000.);
+ else
+ sprintf(buf, "%g", bw);
- if (!(f->states & (1<<state)))
- return 0;
- } while (0);
+ return buf;
+}
- s.local.family = s.remote.family = family;
- if (family == AF_INET) {
- sscanf(loc, "%x:%x", s.local.data, (unsigned*)&s.lport);
- sscanf(rem, "%x:%x", s.remote.data, (unsigned*)&s.rport);
- s.local.bytelen = s.remote.bytelen = 4;
- } else {
- sscanf(loc, "%08x%08x%08x%08x:%x",
- s.local.data,
- s.local.data+1,
- s.local.data+2,
- s.local.data+3,
- &s.lport);
- sscanf(rem, "%08x%08x%08x%08x:%x",
- s.remote.data,
- s.remote.data+1,
- s.remote.data+2,
- s.remote.data+3,
- &s.rport);
- s.local.bytelen = s.remote.bytelen = 16;
- }
+static void tcp_stats_print(struct tcpstat *s)
+{
+ char b1[64];
+
+ if (s->has_ts_opt)
+ printf(" ts");
+ if (s->has_sack_opt)
+ printf(" sack");
+ if (s->has_ecn_opt)
+ printf(" ecn");
+ if (s->has_ecnseen_opt)
+ printf(" ecnseen");
+ if (s->has_fastopen_opt)
+ printf(" fastopen");
+ if (s->cong_alg)
+ printf(" %s", s->cong_alg);
+ if (s->has_wscale_opt)
+ printf(" wscale:%d,%d", s->snd_wscale, s->rcv_wscale);
+ if (s->rto)
+ printf(" rto:%g", s->rto);
+ if (s->backoff)
+ printf(" backoff:%u", s->backoff);
+ if (s->rtt)
+ printf(" rtt:%g/%g", s->rtt, s->rttvar);
+ if (s->ato)
+ printf(" ato:%g", s->ato);
+
+ if (s->qack)
+ printf(" qack:%d", s->qack);
+ if (s->qack & 1)
+ printf(" bidir");
+
+ if (s->mss)
+ printf(" mss:%d", s->mss);
+ if (s->cwnd && s->cwnd != 2)
+ printf(" cwnd:%d", s->cwnd);
+ if (s->ssthresh)
+ printf(" ssthresh:%d", s->ssthresh);
+
+ if (s->dctcp && s->dctcp->enabled) {
+ struct dctcpstat *dctcp = s->dctcp;
+
+ printf(" ce_state %u alpha %u ab_ecn %u ab_tot %u",
+ dctcp->ce_state, dctcp->alpha, dctcp->ab_ecn,
+ dctcp->ab_tot);
+ } else if (s->dctcp) {
+ printf(" fallback_mode");
+ }
+
+ if (s->send_bps)
+ printf(" send %sbps", sprint_bw(b1, s->send_bps));
+ if (s->lastsnd)
+ printf(" lastsnd:%u", s->lastsnd);
+ if (s->lastrcv)
+ printf(" lastrcv:%u", s->lastrcv);
+ if (s->lastack)
+ printf(" lastack:%u", s->lastack);
+
+ if (s->pacing_rate) {
+ printf(" pacing_rate %sbps", sprint_bw(b1, s->pacing_rate));
+ if (s->pacing_rate_max)
+ printf("/%sbps", sprint_bw(b1,
+ s->pacing_rate_max));
+ }
+
+ if (s->unacked)
+ printf(" unacked:%u", s->unacked);
+ if (s->retrans || s->retrans_total)
+ printf(" retrans:%u/%u", s->retrans, s->retrans_total);
+ if (s->lost)
+ printf(" lost:%u", s->lost);
+ if (s->sacked && s->state != SS_LISTEN)
+ printf(" sacked:%u", s->sacked);
+ if (s->fackets)
+ printf(" fackets:%u", s->fackets);
+ if (s->reordering != 3)
+ printf(" reordering:%d", s->reordering);
+ if (s->rcv_rtt)
+ printf(" rcv_rtt:%g", s->rcv_rtt);
+ if (s->rcv_space)
+ printf(" rcv_space:%d", s->rcv_space);
+}
+
+static int tcp_show_line(char *line, const struct filter *f, int family)
+{
+ int rto = 0, ato = 0;
+ struct tcpstat s = {};
+ char *loc, *rem, *data;
+ char opt[256];
+ int n;
+ int hz = get_user_hz();
+
+ if (proc_inet_split_line(line, &loc, &rem, &data))
+ return -1;
+
+ int state = (data[1] >= 'A') ? (data[1] - 'A' + 10) : (data[1] - '0');
+ if (!(f->states & (1 << state)))
+ return 0;
+
+ proc_parse_inet_addr(loc, rem, family, &s);
if (f->f && run_ssfilter(f->f, &s) == 0)
return 0;
@@ -1495,69 +1690,29 @@ static int tcp_show_line(char *line, const struct filter *f, int family)
opt[0] = 0;
n = sscanf(data, "%x %x:%x %x:%x %x %d %d %u %d %llx %d %d %d %d %d %[^\n]\n",
&s.state, &s.wq, &s.rq,
- &s.timer, &s.timeout, &s.retrs, &s.uid, &s.probes, &s.ino,
- &s.refcnt, &s.sk, &s.rto, &s.ato, &s.qack,
+ &s.timer, &s.timeout, &s.retrans, &s.uid, &s.probes, &s.ino,
+ &s.refcnt, &s.sk, &rto, &ato, &s.qack,
&s.cwnd, &s.ssthresh, opt);
if (n < 17)
opt[0] = 0;
if (n < 12) {
- s.rto = 0;
+ rto = 0;
s.cwnd = 2;
s.ssthresh = -1;
- s.ato = s.qack = 0;
+ ato = s.qack = 0;
}
- if (netid_width)
- printf("%-*s ", netid_width, "tcp");
- if (state_width)
- printf("%-*s ", state_width, sstate_name[s.state]);
+ s.retrans = s.timer != 1 ? s.probes : s.retrans;
+ s.timeout = (s.timeout * 1000 + hz - 1) / hz;
+ s.ato = (double)ato / hz;
+ s.qack /= 2;
+ s.rto = (double)rto;
+ s.ssthresh = s.ssthresh == -1 ? 0 : s.ssthresh;
+ s.rto = s.rto != 3 * hz ? s.rto / hz : 0;
- printf("%-6d %-6d ", s.rq, s.wq);
-
- formatted_print(&s.local, s.lport, 0);
- formatted_print(&s.remote, s.rport, 0);
-
- if (show_options) {
- if (s.timer) {
- if (s.timer > 4)
- s.timer = 5;
- printf(" timer:(%s,%s,%d)",
- tmr_name[s.timer],
- print_hz_timer(s.timeout),
- s.timer != 1 ? s.probes : s.retrs);
- }
- }
- if (show_tcpinfo) {
- int hz = get_user_hz();
- if (s.rto && s.rto != 3*hz)
- printf(" rto:%g", (double)s.rto/hz);
- if (s.ato)
- printf(" ato:%g", (double)s.ato/hz);
- if (s.cwnd != 2)
- printf(" cwnd:%d", s.cwnd);
- if (s.ssthresh != -1)
- printf(" ssthresh:%d", s.ssthresh);
- if (s.qack/2)
- printf(" qack:%d", s.qack/2);
- if (s.qack&1)
- printf(" bidir");
- }
- char *buf = NULL;
- if (show_proc_ctx || show_sock_ctx) {
- if (find_entry(s.ino, &buf,
- (show_proc_ctx & show_sock_ctx) ?
- PROC_SOCK_CTX : PROC_CTX) > 0) {
- printf(" users:(%s)", buf);
- free(buf);
- }
- } else if (show_users) {
- if (find_entry(s.ino, &buf, USERS) > 0) {
- printf(" users:(%s)", buf);
- free(buf);
- }
- }
+ inet_stats_print(&s, IPPROTO_TCP);
if (show_details) {
if (s.uid)
@@ -1567,8 +1722,11 @@ static int tcp_show_line(char *line, const struct filter *f, int family)
if (opt[0])
printf(" opt:\"%s\"", opt);
}
- printf("\n");
+ if (show_tcpinfo)
+ tcp_stats_print(&s);
+
+ printf("\n");
return 0;
}
@@ -1598,18 +1756,6 @@ outerr:
return ferror(fp) ? -1 : 0;
}
-static char *sprint_bw(char *buf, double bw)
-{
- if (bw > 1000000.)
- sprintf(buf,"%.1fM", bw / 1000000.);
- else if (bw > 1000.)
- sprintf(buf,"%.1fK", bw / 1000.);
- else
- sprintf(buf, "%g", bw);
-
- return buf;
-}
-
static void print_skmeminfo(struct rtattr *tb[], int attrtype)
{
const __u32 *skmeminfo;
@@ -1649,11 +1795,13 @@ static void print_skmeminfo(struct rtattr *tb[], int attrtype)
printf(")");
}
+#define TCPI_HAS_OPT(info, opt) !!(info->tcpi_options & (opt))
+
static void tcp_show_info(const struct nlmsghdr *nlh, struct inet_diag_msg *r,
struct rtattr *tb[])
{
- char b1[64];
double rtt = 0;
+ struct tcpstat s = {};
print_skmeminfo(tb, INET_DIAG_SKMEMINFO);
@@ -1670,39 +1818,49 @@ static void tcp_show_info(const struct nlmsghdr *nlh, struct inet_diag_msg *r,
info = RTA_DATA(tb[INET_DIAG_INFO]);
if (show_options) {
- if (info->tcpi_options & TCPI_OPT_TIMESTAMPS)
- printf(" ts");
- if (info->tcpi_options & TCPI_OPT_SACK)
- printf(" sack");
- if (info->tcpi_options & TCPI_OPT_ECN)
- printf(" ecn");
- if (info->tcpi_options & TCPI_OPT_ECN_SEEN)
- printf(" ecnseen");
- if (info->tcpi_options & TCPI_OPT_SYN_DATA)
- printf(" fastopen");
- }
-
- if (tb[INET_DIAG_CONG])
- printf(" %s", rta_getattr_str(tb[INET_DIAG_CONG]));
-
- if (info->tcpi_options & TCPI_OPT_WSCALE)
- printf(" wscale:%d,%d", info->tcpi_snd_wscale,
- info->tcpi_rcv_wscale);
+ s.has_ts_opt = TCPI_HAS_OPT(info, TCPI_OPT_TIMESTAMPS);
+ s.has_sack_opt = TCPI_HAS_OPT(info, TCPI_OPT_SACK);
+ s.has_ecn_opt = TCPI_HAS_OPT(info, TCPI_OPT_ECN);
+ s.has_ecnseen_opt = TCPI_HAS_OPT(info, TCPI_OPT_ECN_SEEN);
+ s.has_fastopen_opt = TCPI_HAS_OPT(info, TCPI_OPT_SYN_DATA);
+ }
+
+ if (tb[INET_DIAG_CONG]) {
+ const char *cong_attr = rta_getattr_str(tb[INET_DIAG_CONG]);
+ s.cong_alg = malloc(strlen(cong_attr + 1));
+ strcpy(s.cong_alg, cong_attr);
+ }
+
+ if (TCPI_HAS_OPT(info, TCPI_OPT_WSCALE)) {
+ s.has_wscale_opt = true;
+ s.snd_wscale = info->tcpi_snd_wscale;
+ s.rcv_wscale = info->tcpi_rcv_wscale;
+ }
+
if (info->tcpi_rto && info->tcpi_rto != 3000000)
- printf(" rto:%g", (double)info->tcpi_rto/1000);
- if (info->tcpi_backoff)
- printf(" backoff:%u", info->tcpi_backoff);
- if (info->tcpi_rtt)
- printf(" rtt:%g/%g", (double)info->tcpi_rtt/1000,
- (double)info->tcpi_rttvar/1000);
- if (info->tcpi_ato)
- printf(" ato:%g", (double)info->tcpi_ato/1000);
- if (info->tcpi_snd_mss)
- printf(" mss:%d", info->tcpi_snd_mss);
- if (info->tcpi_snd_cwnd != 2)
- printf(" cwnd:%d", info->tcpi_snd_cwnd);
+ s.rto = (double)info->tcpi_rto / 1000;
+
+ s.backoff = info->tcpi_backoff;
+ s.rtt = (double)info->tcpi_rtt / 1000;
+ s.rttvar = (double)info->tcpi_rttvar / 1000;
+ s.ato = (double)info->tcpi_rttvar / 1000;
+ s.mss = info->tcpi_snd_mss;
+ s.rcv_space = info->tcpi_rcv_space;
+ s.rcv_rtt = (double)info->tcpi_rcv_rtt / 1000;
+ s.lastsnd = info->tcpi_last_data_sent;
+ s.lastrcv = info->tcpi_last_data_recv;
+ s.lastack = info->tcpi_last_ack_recv;
+ s.unacked = info->tcpi_unacked;
+ s.retrans = info->tcpi_retrans;
+ s.retrans_total = info->tcpi_total_retrans;
+ s.lost = info->tcpi_lost;
+ s.sacked = info->tcpi_sacked;
+ s.reordering = info->tcpi_reordering;
+ s.rcv_space = info->tcpi_rcv_space;
+ s.cwnd = info->tcpi_snd_cwnd;
+
if (info->tcpi_snd_ssthresh < 0xFFFF)
- printf(" ssthresh:%d", info->tcpi_snd_ssthresh);
+ s.ssthresh = info->tcpi_snd_ssthresh;
rtt = (double) info->tcpi_rtt;
if (tb[INET_DIAG_VEGASINFO]) {
@@ -1710,89 +1868,51 @@ static void tcp_show_info(const struct nlmsghdr *nlh, struct inet_diag_msg *r,
= RTA_DATA(tb[INET_DIAG_VEGASINFO]);
if (vinfo->tcpv_enabled &&
- vinfo->tcpv_rtt && vinfo->tcpv_rtt != 0x7fffffff)
+ vinfo->tcpv_rtt && vinfo->tcpv_rtt != 0x7fffffff)
rtt = vinfo->tcpv_rtt;
}
if (tb[INET_DIAG_DCTCPINFO]) {
+ struct dctcpstat *dctcp = malloc(sizeof(struct
+ dctcpstat));
+
const struct tcp_dctcp_info *dinfo
= RTA_DATA(tb[INET_DIAG_DCTCPINFO]);
- if (dinfo->dctcp_enabled) {
- printf(" ce_state %u alpha %u ab_ecn %u ab_tot %u",
- dinfo->dctcp_ce_state, dinfo->dctcp_alpha,
- dinfo->dctcp_ab_ecn, dinfo->dctcp_ab_tot);
- } else {
- printf(" fallback_mode");
- }
+ dctcp->enabled = !!dinfo->dctcp_enabled;
+ dctcp->ce_state = dinfo->dctcp_ce_state;
+ dctcp->alpha = dinfo->dctcp_alpha;
+ dctcp->ab_ecn = dinfo->dctcp_ab_ecn;
+ dctcp->ab_tot = dinfo->dctcp_ab_tot;
+ s.dctcp = dctcp;
}
if (rtt > 0 && info->tcpi_snd_mss && info->tcpi_snd_cwnd) {
- printf(" send %sbps",
- sprint_bw(b1, (double) info->tcpi_snd_cwnd *
- (double) info->tcpi_snd_mss * 8000000.
- / rtt));
+ s.send_bps = (double) info->tcpi_snd_cwnd *
+ (double)info->tcpi_snd_mss * 8000000. / rtt;
}
- if (info->tcpi_last_data_sent)
- printf(" lastsnd:%u", info->tcpi_last_data_sent);
-
- if (info->tcpi_last_data_recv)
- printf(" lastrcv:%u", info->tcpi_last_data_recv);
-
- if (info->tcpi_last_ack_recv)
- printf(" lastack:%u", info->tcpi_last_ack_recv);
-
if (info->tcpi_pacing_rate &&
- info->tcpi_pacing_rate != ~0ULL) {
- printf(" pacing_rate %sbps",
- sprint_bw(b1, info->tcpi_pacing_rate * 8.));
+ info->tcpi_pacing_rate != ~0ULL) {
+ s.pacing_rate = info->tcpi_pacing_rate * 8.;
if (info->tcpi_max_pacing_rate &&
- info->tcpi_max_pacing_rate != ~0ULL)
- printf("/%sbps",
- sprint_bw(b1, info->tcpi_max_pacing_rate * 8.));
- }
- if (info->tcpi_unacked)
- printf(" unacked:%u", info->tcpi_unacked);
- if (info->tcpi_retrans || info->tcpi_total_retrans)
- printf(" retrans:%u/%u", info->tcpi_retrans,
- info->tcpi_total_retrans);
- if (info->tcpi_lost)
- printf(" lost:%u", info->tcpi_lost);
- if (info->tcpi_sacked && r->idiag_state != SS_LISTEN)
- printf(" sacked:%u", info->tcpi_sacked);
- if (info->tcpi_fackets)
- printf(" fackets:%u", info->tcpi_fackets);
- if (info->tcpi_reordering != 3)
- printf(" reordering:%d", info->tcpi_reordering);
- if (info->tcpi_rcv_rtt)
- printf(" rcv_rtt:%g", (double) info->tcpi_rcv_rtt/1000);
- if (info->tcpi_rcv_space)
- printf(" rcv_space:%d", info->tcpi_rcv_space);
-
- }
-}
-
-static char *proto_name(int protocol)
-{
- switch (protocol) {
- case IPPROTO_UDP:
- return "udp";
- case IPPROTO_TCP:
- return "tcp";
- case IPPROTO_DCCP:
- return "dccp";
+ info->tcpi_max_pacing_rate != ~0ULL)
+ s.pacing_rate_max = info->tcpi_max_pacing_rate * 8.;
+ }
+ tcp_stats_print(&s);
+ if (s.dctcp)
+ free(s.dctcp);
+ if (s.cong_alg)
+ free(s.cong_alg);
}
-
- return "???";
}
static int inet_show_sock(struct nlmsghdr *nlh, struct filter *f, int protocol)
{
struct rtattr * tb[INET_DIAG_MAX+1];
struct inet_diag_msg *r = NLMSG_DATA(nlh);
- struct tcpstat s;
+ struct tcpstat s = {};
parse_rtattr(tb, INET_DIAG_MAX, (struct rtattr*)(r+1),
nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*r)));
@@ -1801,52 +1921,28 @@ static int inet_show_sock(struct nlmsghdr *nlh, struct filter *f, int protocol)
s.local.family = s.remote.family = r->idiag_family;
s.lport = ntohs(r->id.idiag_sport);
s.rport = ntohs(r->id.idiag_dport);
+ s.wq = r->idiag_wqueue;
+ s.rq = r->idiag_rqueue;
+ s.timer = r->idiag_timer;
+ s.timeout = r->idiag_expires;
+ s.retrans = r->idiag_retrans;
+ s.ino = r->idiag_inode;
+ s.uid = r->idiag_uid;
+ s.iface = r->id.idiag_if;
+
if (s.local.family == AF_INET) {
s.local.bytelen = s.remote.bytelen = 4;
} else {
s.local.bytelen = s.remote.bytelen = 16;
}
+
memcpy(s.local.data, r->id.idiag_src, s.local.bytelen);
memcpy(s.remote.data, r->id.idiag_dst, s.local.bytelen);
if (f && f->f && run_ssfilter(f->f, &s) == 0)
return 0;
- if (netid_width)
- printf("%-*s ", netid_width, proto_name(protocol));
- if (state_width)
- printf("%-*s ", state_width, sstate_name[s.state]);
-
- printf("%-6d %-6d ", r->idiag_rqueue, r->idiag_wqueue);
-
- formatted_print(&s.local, s.lport, r->id.idiag_if);
- formatted_print(&s.remote, s.rport, 0);
-
- if (show_options) {
- if (r->idiag_timer) {
- if (r->idiag_timer > 4)
- r->idiag_timer = 5;
- printf(" timer:(%s,%s,%d)",
- tmr_name[r->idiag_timer],
- print_ms_timer(r->idiag_expires),
- r->idiag_retrans);
- }
- }
- char *buf = NULL;
-
- if (show_proc_ctx || show_sock_ctx) {
- if (find_entry(r->idiag_inode, &buf,
- (show_proc_ctx & show_sock_ctx) ?
- PROC_SOCK_CTX : PROC_CTX) > 0) {
- printf(" users:(%s)", buf);
- free(buf);
- }
- } else if (show_users) {
- if (find_entry(r->idiag_inode, &buf, USERS) > 0) {
- printf(" users:(%s)", buf);
- free(buf);
- }
- }
+ inet_stats_print(&s, protocol);
if (show_details) {
if (r->idiag_uid)
@@ -1862,13 +1958,13 @@ static int inet_show_sock(struct nlmsghdr *nlh, struct filter *f, int protocol)
printf(" %c-%c", mask & 1 ? '-' : '<', mask & 2 ? '-' : '>');
}
}
+
if (show_mem || show_tcpinfo) {
printf("\n\t");
tcp_show_info(nlh, r, tb);
}
printf("\n");
-
return 0;
}
@@ -2189,53 +2285,19 @@ outerr:
static int dgram_show_line(char *line, const struct filter *f, int family)
{
- struct tcpstat s;
+ struct tcpstat s = {};
char *loc, *rem, *data;
char opt[256];
int n;
- char *p;
-
- if ((p = strchr(line, ':')) == NULL)
- return -1;
- loc = p+2;
- if ((p = strchr(loc, ':')) == NULL)
+ if (proc_inet_split_line(line, &loc, &rem, &data))
return -1;
- p[5] = 0;
- rem = p+6;
-
- if ((p = strchr(rem, ':')) == NULL)
- return -1;
- p[5] = 0;
- data = p+6;
- do {
- int state = (data[1] >= 'A') ? (data[1] - 'A' + 10) : (data[1] - '0');
+ int state = (data[1] >= 'A') ? (data[1] - 'A' + 10) : (data[1] - '0');
+ if (!(f->states & (1 << state)))
+ return 0;
- if (!(f->states & (1<<state)))
- return 0;
- } while (0);
-
- s.local.family = s.remote.family = family;
- if (family == AF_INET) {
- sscanf(loc, "%x:%x", s.local.data, (unsigned*)&s.lport);
- sscanf(rem, "%x:%x", s.remote.data, (unsigned*)&s.rport);
- s.local.bytelen = s.remote.bytelen = 4;
- } else {
- sscanf(loc, "%08x%08x%08x%08x:%x",
- s.local.data,
- s.local.data+1,
- s.local.data+2,
- s.local.data+3,
- &s.lport);
- sscanf(rem, "%08x%08x%08x%08x:%x",
- s.remote.data,
- s.remote.data+1,
- s.remote.data+2,
- s.remote.data+3,
- &s.rport);
- s.local.bytelen = s.remote.bytelen = 16;
- }
+ proc_parse_inet_addr(loc, rem, family, &s);
if (f->f && run_ssfilter(f->f, &s) == 0)
return 0;
@@ -2249,31 +2311,7 @@ static int dgram_show_line(char *line, const struct filter *f, int family)
if (n < 9)
opt[0] = 0;
- if (netid_width)
- printf("%-*s ", netid_width, dg_proto);
- if (state_width)
- printf("%-*s ", state_width, sstate_name[s.state]);
-
- printf("%-6d %-6d ", s.rq, s.wq);
-
- formatted_print(&s.local, s.lport, 0);
- formatted_print(&s.remote, s.rport, 0);
-
- char *buf = NULL;
-
- if (show_proc_ctx || show_sock_ctx) {
- if (find_entry(s.ino, &buf,
- (show_proc_ctx & show_sock_ctx) ?
- PROC_SOCK_CTX : PROC_CTX) > 0) {
- printf(" users:(%s)", buf);
- free(buf);
- }
- } else if (show_users) {
- if (find_entry(s.ino, &buf, USERS) > 0) {
- printf(" users:(%s)", buf);
- free(buf);
- }
- }
+ inet_stats_print(&s, IPPROTO_UDP);
if (show_details) {
if (s.uid)
@@ -2283,12 +2321,11 @@ static int dgram_show_line(char *line, const struct filter *f, int family)
if (opt[0])
printf(" opt:\"%s\"", opt);
}
- printf("\n");
+ printf("\n");
return 0;
}
-
static int udp_show(struct filter *f)
{
FILE *fp = NULL;
@@ -2357,7 +2394,6 @@ outerr:
} while (0);
}
-
struct unixstat
{
struct unixstat *next;
@@ -2371,12 +2407,9 @@ struct unixstat
char *name;
};
-
-
int unix_state_map[] = { SS_CLOSE, SS_SYN_SENT,
SS_ESTABLISHED, SS_CLOSING };
-
#define MAX_UNIX_REMEMBER (1024*1024/sizeof(struct unixstat))
static void unix_list_free(struct unixstat *list)
--
2.1.3
^ permalink raw reply related
* [PATCH 0/2] Refactoring for meminfo & inet sockets output
From: Vadim Kochan @ 2015-01-20 14:14 UTC (permalink / raw)
To: netdev; +Cc: Vadim Kochan
From: Vadim Kochan <vadim4j@gmail.com>
This is just refactoring to have meminfo and inet stats
output in one place.
Vadim Kochan (2):
ss: Unify meminfo output
ss: Unify inet sockets output
misc/ss.c | 707 +++++++++++++++++++++++++++++++++-----------------------------
1 file changed, 373 insertions(+), 334 deletions(-)
--
2.1.3
^ permalink raw reply
* [PATCH 1/2] ss: Unify meminfo output
From: Vadim Kochan @ 2015-01-20 14:14 UTC (permalink / raw)
To: netdev; +Cc: Vadim Kochan
In-Reply-To: <1421763264-8954-1-git-send-email-vadim4j@gmail.com>
From: Vadim Kochan <vadim4j@gmail.com>
Signed-off-by: Vadim Kochan <vadim4j@gmail.com>
---
misc/ss.c | 30 ++++++++++++++++++------------
1 file changed, 18 insertions(+), 12 deletions(-)
diff --git a/misc/ss.c b/misc/ss.c
index f434f57..3764f3a 100644
--- a/misc/ss.c
+++ b/misc/ss.c
@@ -1613,8 +1613,24 @@ static char *sprint_bw(char *buf, double bw)
static void print_skmeminfo(struct rtattr *tb[], int attrtype)
{
const __u32 *skmeminfo;
- if (!tb[attrtype])
+
+ if (!tb[attrtype]) {
+ if (attrtype == INET_DIAG_SKMEMINFO) {
+ if (!tb[INET_DIAG_MEMINFO])
+ return;
+
+ const struct inet_diag_meminfo *minfo =
+ RTA_DATA(tb[INET_DIAG_MEMINFO]);
+
+ printf(" mem:(r%u,w%u,f%u,t%u)",
+ minfo->idiag_rmem,
+ minfo->idiag_wmem,
+ minfo->idiag_fmem,
+ minfo->idiag_tmem);
+ }
return;
+ }
+
skmeminfo = RTA_DATA(tb[attrtype]);
printf(" skmem:(r%u,rb%u,t%u,tb%u,f%u,w%u,o%u",
@@ -1639,17 +1655,7 @@ static void tcp_show_info(const struct nlmsghdr *nlh, struct inet_diag_msg *r,
char b1[64];
double rtt = 0;
- if (tb[INET_DIAG_SKMEMINFO]) {
- print_skmeminfo(tb, INET_DIAG_SKMEMINFO);
- } else if (tb[INET_DIAG_MEMINFO]) {
- const struct inet_diag_meminfo *minfo
- = RTA_DATA(tb[INET_DIAG_MEMINFO]);
- printf(" mem:(r%u,w%u,f%u,t%u)",
- minfo->idiag_rmem,
- minfo->idiag_wmem,
- minfo->idiag_fmem,
- minfo->idiag_tmem);
- }
+ print_skmeminfo(tb, INET_DIAG_SKMEMINFO);
if (tb[INET_DIAG_INFO]) {
struct tcp_info *info;
--
2.1.3
^ permalink raw reply related
* [PATCH net-next 4/6] macvlan: advertise link netns via netlink
From: Nicolas Dichtel @ 2015-01-20 14:15 UTC (permalink / raw)
To: netdev; +Cc: davem, Nicolas Dichtel
In-Reply-To: <1421763347-4354-1-git-send-email-nicolas.dichtel@6wind.com>
Assign rtnl_link_ops->get_link_net() callback so that IFLA_LINK_NETNSID is
added to rtnetlink messages.
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
drivers/net/macvlan.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 612e0731142d..1df38bdae2ee 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -1471,11 +1471,17 @@ int macvlan_link_register(struct rtnl_link_ops *ops)
};
EXPORT_SYMBOL_GPL(macvlan_link_register);
+static struct net *macvlan_get_link_net(const struct net_device *dev)
+{
+ return dev_net(macvlan_dev_real_dev(dev));
+}
+
static struct rtnl_link_ops macvlan_link_ops = {
.kind = "macvlan",
.setup = macvlan_setup,
.newlink = macvlan_newlink,
.dellink = macvlan_dellink,
+ .get_link_net = macvlan_get_link_net,
};
static int macvlan_device_event(struct notifier_block *unused,
--
2.2.2
^ permalink raw reply related
* [PATCH net-next 6/6] vxlan: advertise netns of vxlan dev in fdb msg
From: Nicolas Dichtel @ 2015-01-20 14:15 UTC (permalink / raw)
To: netdev; +Cc: davem, Nicolas Dichtel
In-Reply-To: <1421763347-4354-1-git-send-email-nicolas.dichtel@6wind.com>
Netlink FDB messages are sent in the link netns. The header of these messages
contains the ifindex (ndm_ifindex) of the netdevice, but this ifindex is
unusable in case of x-netns vxlan.
I named the new attribute NDA_NDM_IFINDEX_NETNSID, to avoid confusion with
NDA_IFINDEX.
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
drivers/net/vxlan.c | 5 +++++
include/uapi/linux/neighbour.h | 1 +
net/core/net_namespace.c | 1 +
3 files changed, 7 insertions(+)
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index 0346eaa6d236..19d3664ab9dd 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -339,6 +339,11 @@ static int vxlan_fdb_info(struct sk_buff *skb, struct vxlan_dev *vxlan,
ndm->ndm_flags = fdb->flags;
ndm->ndm_type = RTN_UNICAST;
+ if (!net_eq(dev_net(vxlan->dev), vxlan->net) &&
+ nla_put_s32(skb, NDA_NDM_IFINDEX_NETNSID,
+ peernet2id(vxlan->net, dev_net(vxlan->dev))))
+ goto nla_put_failure;
+
if (send_eth && nla_put(skb, NDA_LLADDR, ETH_ALEN, &fdb->eth_addr))
goto nla_put_failure;
diff --git a/include/uapi/linux/neighbour.h b/include/uapi/linux/neighbour.h
index f3d77f9f1e0b..38f236853cc0 100644
--- a/include/uapi/linux/neighbour.h
+++ b/include/uapi/linux/neighbour.h
@@ -25,6 +25,7 @@ enum {
NDA_VNI,
NDA_IFINDEX,
NDA_MASTER,
+ NDA_NDM_IFINDEX_NETNSID,
__NDA_MAX
};
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 9d1a4cac83b6..b7bde551ef76 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -202,6 +202,7 @@ int peernet2id(struct net *net, struct net *peer)
return id >= 0 ? id : NETNSA_NSID_NOT_ASSIGNED;
}
+EXPORT_SYMBOL(peernet2id);
struct net *get_net_ns_by_id(struct net *net, int id)
{
--
2.2.2
^ permalink raw reply related
* [PATCH net-next 3/6] vlan: advertise link netns via netlink
From: Nicolas Dichtel @ 2015-01-20 14:15 UTC (permalink / raw)
To: netdev; +Cc: davem, Nicolas Dichtel
In-Reply-To: <1421763347-4354-1-git-send-email-nicolas.dichtel@6wind.com>
Assign rtnl_link_ops->get_link_net() callback so that IFLA_LINK_NETNSID is
added to rtnetlink messages.
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
net/8021q/vlan_netlink.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/net/8021q/vlan_netlink.c b/net/8021q/vlan_netlink.c
index 8ac8a5cc2143..c92b52f37d38 100644
--- a/net/8021q/vlan_netlink.c
+++ b/net/8021q/vlan_netlink.c
@@ -238,6 +238,13 @@ nla_put_failure:
return -EMSGSIZE;
}
+static struct net *vlan_get_link_net(const struct net_device *dev)
+{
+ struct net_device *real_dev = vlan_dev_priv(dev)->real_dev;
+
+ return dev_net(real_dev);
+}
+
struct rtnl_link_ops vlan_link_ops __read_mostly = {
.kind = "vlan",
.maxtype = IFLA_VLAN_MAX,
@@ -250,6 +257,7 @@ struct rtnl_link_ops vlan_link_ops __read_mostly = {
.dellink = unregister_vlan_dev,
.get_size = vlan_get_size,
.fill_info = vlan_fill_info,
+ .get_link_net = vlan_get_link_net,
};
int __init vlan_netlink_init(void)
--
2.2.2
^ permalink raw reply related
* [PATCH net-next 0/6] netns: advertise netns via netlink
From: Nicolas Dichtel @ 2015-01-20 14:15 UTC (permalink / raw)
To: netdev; +Cc: davem
The first patch of the serie fix a bug of the previous serie (present in
net-next only).
The rest of the serie adds an attribute to advertise the peer netns for
rtnetlink messages where this information is needed by userland to be able to
interpret fully the received message.
drivers/net/macvlan.c | 6 ++++++
drivers/net/veth.c | 9 +++++++++
drivers/net/vxlan.c | 5 +++++
include/uapi/linux/neighbour.h | 1 +
net/8021q/vlan_netlink.c | 8 ++++++++
net/core/net_namespace.c | 1 +
net/core/rtnetlink.c | 5 ++++-
net/ipv6/ip6_gre.c | 1 +
8 files changed, 35 insertions(+), 1 deletion(-)
Comments are welcome.
Regards,
Nicolas
^ permalink raw reply
* [PATCH net-next 5/6] veth: advertise link netns via netlink
From: Nicolas Dichtel @ 2015-01-20 14:15 UTC (permalink / raw)
To: netdev; +Cc: davem, Nicolas Dichtel
In-Reply-To: <1421763347-4354-1-git-send-email-nicolas.dichtel@6wind.com>
Assign rtnl_link_ops->get_link_net() callback so that IFLA_LINK_NETNSID is
added to rtnetlink messages.
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
drivers/net/veth.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index 8ad596573d17..4cca36ebc4fb 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -469,6 +469,14 @@ static const struct nla_policy veth_policy[VETH_INFO_MAX + 1] = {
[VETH_INFO_PEER] = { .len = sizeof(struct ifinfomsg) },
};
+static struct net *veth_get_link_net(const struct net_device *dev)
+{
+ struct veth_priv *priv = netdev_priv(dev);
+ struct net_device *peer = rtnl_dereference(priv->peer);
+
+ return peer ? dev_net(peer) : dev_net(dev);
+}
+
static struct rtnl_link_ops veth_link_ops = {
.kind = DRV_NAME,
.priv_size = sizeof(struct veth_priv),
@@ -478,6 +486,7 @@ static struct rtnl_link_ops veth_link_ops = {
.dellink = veth_dellink,
.policy = veth_policy,
.maxtype = VETH_INFO_MAX,
+ .get_link_net = veth_get_link_net,
};
/*
--
2.2.2
^ permalink raw reply related
* [PATCH net-next 2/6] ip6gretap: advertise link netns via netlink
From: Nicolas Dichtel @ 2015-01-20 14:15 UTC (permalink / raw)
To: netdev; +Cc: davem, Nicolas Dichtel
In-Reply-To: <1421763347-4354-1-git-send-email-nicolas.dichtel@6wind.com>
Assign rtnl_link_ops->get_link_net() callback so that IFLA_LINK_NETNSID is
added to rtnetlink messages.
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
net/ipv6/ip6_gre.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index 9306a5ff9149..6dee2a8ca0a9 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -1676,6 +1676,7 @@ static struct rtnl_link_ops ip6gre_tap_ops __read_mostly = {
.changelink = ip6gre_changelink,
.get_size = ip6gre_get_size,
.fill_info = ip6gre_fill_info,
+ .get_link_net = ip6_tnl_get_link_net,
};
/*
--
2.2.2
^ permalink raw reply related
* [PATCH net-next 1/6] rtnl: fix error path when adding an iface with a link net
From: Nicolas Dichtel @ 2015-01-20 14:15 UTC (permalink / raw)
To: netdev; +Cc: davem, Nicolas Dichtel
In-Reply-To: <1421763347-4354-1-git-send-email-nicolas.dichtel@6wind.com>
If an error occurs when the netdevice is moved to the link netns, a full cleanup
must be done.
Fixes: 317f4810e45e ("rtnl: allow to create device with IFLA_LINK_NETNSID set")
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
net/core/rtnetlink.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index a12eecc0f976..07447d1665e6 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -2172,8 +2172,11 @@ replay:
goto out;
}
- if (link_net)
+ if (link_net) {
err = dev_change_net_namespace(dev, dest_net, ifname);
+ if (err < 0)
+ unregister_netdevice(dev);
+ }
out:
if (link_net)
put_net(link_net);
--
2.2.2
^ permalink raw reply related
* Re: [PATCH] ethernet: atheros: Add nss-gmac driver
From: Arnd Bergmann @ 2015-01-20 14:05 UTC (permalink / raw)
To: wstephen
Cc: jcliburn, grant.likely, robh+dt, linux-kernel, netdev, devicetree
In-Reply-To: <3ad19b16fe5c58612479f70c052d0045.squirrel@www.codeaurora.org>
On Monday 19 January 2015 21:58:09 wstephen@codeaurora.org wrote:
> > On Thursday 15 January 2015 08:12:51 wstephen@codeaurora.org wrote:
> >
> >> The nss-gmac driver is designed to work standalone or with the nss-drv
> >> driver so the switchable data plane overlay was implemented. When it
> >> worked standalone, the data plane is running on the ARM core as a
> >> standard
> >> networking driver.
> >
> > How do you decide which way it gets used on a particular system?
> >
>
> By default the GMAC driver uses a native (Host ARM CPU) based data plane.
> If the configuration loads the offload nss-drv driver, the offload driver
> registers an overlay with the GMAC.
Right. For review purposes, I think it would be helpful to split this
huge patch into several steps then:
- add a base driver
- add the overlay interface
- add the nss driver
Ideally more of them.
> >> The nss-drv driver can take over the data plane and
> >> offload it to the NSS cores. The STMicro stmmac driver does not have
> >> this
> >> kind of overlay design so is not suitable for IPQ806x. This is why we
> >> don't based on the stmmac driver
> >
> > Which kind of offload is implemented specifically? 'data plane' sounds
> > fairly generic and could mean anything, and the code isn't readable enough
> > in its current form for me to find out.
>
> The Network Subsystem (NSS core) provides a GMAC pass-through until it is
> given a rule to offload work. Once a rule is given, it is capable of
> performing: bridging, IPv4 NAT/FWD, IPv6 NAT/FWD, IPSec, LAG, and other
> protocols.
>
> Hope this clarify your question!
Thanks for the description, this sounds very interesting indeed. I do
have more questions though: how do you get the rules into the NSS driver?
Does this get handled transparently by the openvswitch driver or
did you have to add new user interfaces for it?
Arnd
^ permalink raw reply
* Re: [RFC PATCH net-next] bridge: ability to disable forwarding on a port
From: roopa @ 2015-01-20 13:59 UTC (permalink / raw)
To: Samudrala, Sridhar
Cc: Scott Feldman, stephen@networkplumber.org, David S. Miller,
Jamal Hadi Salim, Jiří Pírko, Arad, Ronen,
Thomas Graf, john fastabend, vyasevic@redhat.com, Netdev,
Wilson Kok, Andy Gospodarek
In-Reply-To: <54BDFF20.9020909@intel.com>
On 1/19/15, 11:09 PM, Samudrala, Sridhar wrote:
>
> On 1/19/2015 10:20 PM, roopa wrote:
>> On 1/18/15, 11:37 PM, Scott Feldman wrote:
>>
>> <snip..>
>>>
>>> Not sure. I don't know the use case, but I think I might have heard
>>> that
>>> there could be a case
>>> where a switch port could be bridged with a vm's port running on the
>>> switch. (?)
>>>>
>>>> Ignoring the above usecase for a bit. And thinking through this
>>>> again, It
>>>> appears that this check should
>>>> be only on the ingress port, no ?
>>>>
>>>> If the ingress bridge port is an offloaded port, don't flood or
>>>> forward
>>>> because hardware has already done it.
>>>> And this is best done with the offload feature flag on the bridge
>>>> port.
>>> That's assuming hardware did the flood. Maybe your other option to
>>> mark the skb if already flooded by hw is best. That's enough info for
>>> the bridge driver to make a decision to flood or not to the other
>>> ports, and it's an implementation decision for the driver/device to do
>>> the flood offload, if desired, and mark the skb if it did.
>>
>> Still thinking we can just use the offload feature flag here. How
>> about avoid forwarding only if both src and dst ports have
>> forwarding offloaded/accelerated by a switch asic ?. That should
>> cover all cases.
>>>
>>> Btw, you're still saying flood or forward, but in my mind we're
>>> talking about flood only: flood of unknown unicast or flood of
>>> bcast/mcast pkts. Forwarding would be for known-unicast pkts, which
>>> should even involve the bridge driver since that forwarding is
>>> offloaded to the device.
>>
>> I was also taking into account pkts copied to the CPU due to an acl
>> rule such as log.
>> These unicast pkts can come to cpu even if it is already forwarded in
>> hw.
>
> Do you have a switch port netdev that corresponds to CPU port? Or are
> they seen on the bridge device?
No we dont have a netdev for the CPU port. These show up on the netdev
corresponding to the ingress front panel port.
^ permalink raw reply
* Re: Bug: mv643xxx fails with highmem
From: Russell King - ARM Linux @ 2015-01-20 13:41 UTC (permalink / raw)
To: Ezequiel Garcia, David Miller, Linus Torvalds
Cc: Nimrod Andy, Fabio Estevam, netdev, fugang.duan
In-Reply-To: <20141221165106.GN11285@n2100.arm.linux.org.uk>
Ping. What's happening on this?
I guess we don't care about regressions in the Linux kernel?
This bug breaks one of my machines, and I'm having to patch around it
by reverting the first two hunks of 69ad0dd7af22, which is only correct
for platforms where dma_unmap_page and dma_unmap_single result in the
same underlying code being used.
I'm not convinced that it's directly caused by 69ad0dd7af22 though.
On Sun, Dec 21, 2014 at 04:51:06PM +0000, Russell King - ARM Linux wrote:
> On Thu, Dec 18, 2014 at 10:13:19AM -0300, Ezequiel Garcia wrote:
> > On 12/17/2014 09:03 PM, Russell King - ARM Linux wrote:
> > > However, exactly how it occurs, I don't know. My understanding from
> > > reading the various feature flags was that NETIF_F_HIGHDMA was required
> > > for highmem (see illegal_highdma()) so as this isn't set, we shouldn't
> > > be seeing highmem fragments - which is why I asked the question in my
> > > original email.
> > >
> > > If you want me to revert my fix above, and reproduce again, I can
> > > certainly try that - or put a WARN_ON_ONCE(PageHighMem(this_frag->page.p))
> > > in there, but I seem to remember that it wasn't particularly useful as
> > > the backtrace didn't show where the memory actually came from.
> > >
> >
> > No, that's OK. Thanks a lot for all the details. I'll try to come up with a
> > fix soon.
>
> Well, I decided to add the WARN_ON_ONCE() and re-test. This I provoked
> by touching etna_viv/src/etnaviv/etna_bo.c, and re-running make (etnaviv
> is on a shared NFS mount.)
>
> WARNING: CPU: 0 PID: 0 at /home/rmk/git/linux-cubox/drivers/net/ethernet/marvell/mv643xx_eth.c:884 mv643xx_eth_xmit+0x850/0x8dc()
> Modules linked in: bnep rfcomm bluetooth nfsd exportfs ext3 jbd ext2 etnaviv(C)
> snd_soc_spdif_tx orion_wdt snd_soc_kirkwood dove vmeta bmm_dmabuf hwmon snd_soc_kirkwood_spdif
> CPU: 0 PID: 0 Comm: swapper Tainted: G C 3.18.0+ #1056
> Backtrace:
> [<c0011f54>] (dump_backtrace) from [<c0012228>] (show_stack+0x18/0x1c)
> r6:00000374 r5:00000009 r4:00000000 r3:00000000
> [<c0012210>] (show_stack) from [<c04992d8>] (dump_stack+0x20/0x28)
> [<c04992b8>] (dump_stack) from [<c0050be4>] (warn_slowpath_common+0x6c/0x8c)
> [<c0050b78>] (warn_slowpath_common) from [<c0050c28>] (warn_slowpath_null+0x24/0x2c)
> r8:c064ea80 r7:e8a5d880 r6:d00d0d70 r5:e614877c r4:00000001
> [<c0050c04>] (warn_slowpath_null) from [<c02fee9c>] (mv643xx_eth_xmit+0x850/0x8dc)
> [<c02fe64c>] (mv643xx_eth_xmit) from [<c03b94fc>] (dev_hard_start_xmit+0x19c/0x328)
> r10:c0648054 r9:d0261f60 r8:e6148000 r7:d00ec1c0 r6:c0648040 r5:e623ec00
> r4:d013c580
> [<c03b9360>] (dev_hard_start_xmit) from [<c03d2728>] (sch_direct_xmit+0x148/0x24c)
> r10:e623ec00 r9:e63a4580 r8:e6148000 r7:e61f4e00 r6:c063e000 r5:00000000
> r4:00000000
> [<c03d25e0>] (sch_direct_xmit) from [<c03b985c>] (__dev_queue_xmit+0x1d4/0x590)
> r10:e623ec00 r9:00000000 r8:00000000 r7:e6148000 r6:c063e000 r5:e61f4e00
> r4:d0163e70
> [<c03b9688>] (__dev_queue_xmit) from [<c03b9c40>] (dev_queue_xmit+0x14/0x18)
> r10:c063e000 r9:00000000 r8:00000000 r7:d0163e70 r6:0000000e r5:d00caa00
> r4:d00caa94
> [<c03b9c2c>] (dev_queue_xmit) from [<c043c58c>] (ip6_finish_output2+0x1a0/0x524)[<c043c3ec>] (ip6_finish_output2) from [<c043e008>] (ip6_output+0xb4/0x174)
> r10:d0163e70 r9:c063e000 r8:c066f678 r7:00000000 r6:d0163e70 r5:00000000
> r4:000021c0
> [<c043df54>] (ip6_output) from [<c043c114>] (ip6_xmit+0x278/0x550)
> r7:00000000 r6:00000001 r5:00000000 r4:001463b6
> [<c043be9c>] (ip6_xmit) from [<c0466fbc>] (inet6_csk_xmit+0x74/0xa8)
> r10:d0163e70 r9:00000020 r8:d00d2080 r7:d00d25a0 r6:d0163e70 r5:00000000
> r4:d00d2080
> [<c0466f48>] (inet6_csk_xmit) from [<c03f87ac>] (tcp_transmit_skb+0x494/0x990)
> r7:e6094100 r6:c0658910 r5:00000020 r4:ffff5165
> [<c03f8318>] (tcp_transmit_skb) from [<c03f9970>] (tcp_write_xmit+0x138/0xc1c)
> r10:00002178 r9:00000000 r8:00002ca0 r7:00000006 r6:00000594 r5:d0163dc0
> r4:d00d2080
> [<c03f9838>] (tcp_write_xmit) from [<c03fa4d4>] (__tcp_push_pending_frames+0x38/0x98)
> r10:00000002 r9:00000078 r8:d03d7600 r7:d00d25a0 r6:d02841c0 r5:e448f778
> r4:d00d2080
> [<c03fa49c>] (__tcp_push_pending_frames) from [<c03f567c>] (tcp_rcv_established+0x15c/0x600)
> r4:d00d2080
> [<c03f5520>] (tcp_rcv_established) from [<c0461918>] (tcp_v6_do_rcv+0x2bc/0x46c) r10:00000002 r9:00000078 r8:d03d7600 r7:d00d25a0 r6:00000000 r5:d00d2080
> r4:d02841c0
> [<c046165c>] (tcp_v6_do_rcv) from [<c0462828>] (tcp_v6_rcv+0x7f8/0x810)
> r8:00000000 r7:d00d2080 r6:c063e000 r5:c066f678 r4:d02841c0
> [<c0462030>] (tcp_v6_rcv) from [<c043e750>] (ip6_input+0xec/0x424)
> r10:c066f678 r9:c052a75c r8:d02841c0 r7:c0649720 r6:00000006 r5:e6168400
> r4:00000006
> [<c043e664>] (ip6_input) from [<c043e100>] (ip6_rcv_finish+0x38/0xa4)
> r10:e6168400 r9:e6148000 r8:d02841c0 r7:00000001 r6:c066f678 r5:00000000
> r4:d02841c0 r3:c043e664
> [<c043e0c8>] (ip6_rcv_finish) from [<c043e494>] (ipv6_rcv+0x328/0x4f8)
> r4:e448f750 r3:00000000
> [<c043e16c>] (ipv6_rcv) from [<c03b43c0>] (__netif_receive_skb_core+0x2fc/0x5d0) r10:d02841c0 r9:c0649050 r8:c06480c4 r7:e6148000 r6:00000000 r5:0000dd86
> r4:c043e16c
> [<c03b40c4>] (__netif_receive_skb_core) from [<c03b6bac>] (__netif_receive_skb+0x2c/0x88)
> r10:00000001 r9:d02841c0 r8:e61484e0 r7:e8a5b310 r6:2cc7fffe r5:00000003
> r4:d02841c0
> [<c03b6b80>] (__netif_receive_skb) from [<c03b6d30>] (netif_receive_skb_internal+0x2c/0x68)
> r5:00000003 r4:d02841c0
> [<c03b6d04>] (netif_receive_skb_internal) from [<c03b7690>] (napi_gro_receive+0x7c/0xa8)
> r4:d02841c0
> [<c03b7614>] (napi_gro_receive) from [<c0300738>] (mv643xx_eth_poll+0x58c/0x6ac) r5:e6148000 r4:e614864c
> [<c03001ac>] (mv643xx_eth_poll) from [<c03b7370>] (net_rx_action+0xa4/0x1a8)
> r10:c0658910 r9:c0675940 r8:c0675940 r7:0000012c r6:00000040 r5:e61485c0
> r4:c03001ac
> [<c03b72cc>] (net_rx_action) from [<c00533c0>] (__do_softirq+0xf0/0x214)
> r10:00000003 r9:00000101 r8:c063e000 r7:00000003 r6:c0677480 r5:c067748c
> r4:00000000
> [<c00532d0>] (__do_softirq) from [<c005377c>] (irq_exit+0xac/0xfc)
> r10:e6ffcd40 r9:560f5815 r8:00000000 r7:0000001e r6:00000000 r5:00000000
> r4:c063e000
> [<c00536d0>] (irq_exit) from [<c0085330>] (__handle_domain_irq+0x7c/0xc0)
> r4:c065ef68 r3:00010001
> [<c00852b4>] (__handle_domain_irq) from [<c000fb0c>] (handle_IRQ+0x24/0x28)
> r8:00000001 r7:c063ff74 r6:ffffffff r5:600f0013 r4:c0077408 r3:c063ff40
> [<c000fae8>] (handle_IRQ) from [<c0008600>] (dove_legacy_handle_irq+0x34/0x5c)
> [<c00085cc>] (dove_legacy_handle_irq) from [<c0012ce0>] (__irq_svc+0x40/0x74)
> Exception stack(0xc063ff40 to 0xc063ff88)
> ff40: 00000000 0001114c c0658324 c001d940 c063e000 c06470c8 c06759fe c06759fe
> ff60: 00000001 560f5815 e6ffcd40 c063ff9c c063ff88 c063ff88 c000fc38 c0077408
> ff80: 600f0013 ffffffff
> [<c0077354>] (cpu_startup_entry) from [<c04952c4>] (rest_init+0x78/0x90)
> r7:ffffffff r3:c04b0554
> [<c049524c>] (rest_init) from [<c0609ca8>] (start_kernel+0x34c/0x3b0)
> r4:c06479b0 r3:00000001
> [<c060995c>] (start_kernel) from [<00008070>] (0x8070)
>
> Obviously, the useful bit is only down to just above
> __tcp_push_pending_frames(), since that's traces back to the TCP socket's
> send queue.
>
> If I had to guess where the highmem pages were coming from, I'd suggest
> that it was via the page cache and NFS - maybe something like GCC opens
> a new NFS file, writes to it. Pages are allocated to it, which happen
> to be allocated from highmem. NFS eventually sends these pages to the
> NFS server via TCP, which fragments the page and leaves pointers to the
> highmem page in the TCP skbuff. My NFS mounts are IPv6.
>
> For Freescale iMX6 FEC, I haven't yet been able to reproduce this there.
> The FEC has tx-checksum-ipv6 and rx-vlan-offload enabled, which the
> mv643xxx driver doesn't have. The FEC platform has twice the memory of
> the Dove platform (so has much more highmem) so I would've thought it
> would have been easier to reproduce there. Slightly different kernels
> too - Dove runs 3.18 plus additions, iMX6 is running Linus' tip from
> two days ago plus very similar additions (but same GPU and X server
> code.)
>
> Other stuff... Dove memory is 0 - 0x3fffffff. mv643xxx DMA mask
> uninitialised (coherent DMA mask set to 0xffffffff).
>
> iMX6 is 0x10000000 - 0x8fffffff, with the DMA mask defaulting to
> point at the coherent mask (due to being DT based) which is
> 0xffffffff.
>
> Here's the diff of the ethtool -k output:
>
> --- eth0.dove 2014-12-21 16:38:39.000000000 +0000
> +++ eth0.imx6 2014-12-21 16:38:50.792453703 +0000
> @@ -3,7 +3,7 @@
> tx-checksumming: on
> tx-checksum-ipv4: on
> tx-checksum-ip-generic: off [fixed]
> - tx-checksum-ipv6: off [fixed]
> + tx-checksum-ipv6: on
> tx-checksum-fcoe-crc: off [fixed]
> tx-checksum-sctp: off [fixed]
> scatter-gather: on
> @@ -17,7 +17,7 @@
> generic-segmentation-offload: on
> generic-receive-offload: on
> large-receive-offload: off [fixed]
> -rx-vlan-offload: off [fixed]
> +rx-vlan-offload: on
> tx-vlan-offload: off [fixed]
> ntuple-filters: off [fixed]
> receive-hashing: off [fixed]
> @@ -32,7 +32,6 @@
> tx-ipip-segmentation: off [fixed]
> tx-sit-segmentation: off [fixed]
> tx-udp_tnl-segmentation: off [fixed]
> -tx-mpls-segmentation: off [fixed]
> fcoe-mtu: off [fixed]
> tx-nocache-copy: off
> loopback: off [fixed]
>
> Hmm. I'm now wondering about this:
>
> static netdev_features_t harmonize_features(struct sk_buff *skb,
> netdev_features_t features)
> {
> ...
> if (skb->ip_summed != CHECKSUM_NONE &&
> !can_checksum_protocol(features, type)) {
> features &= ~NETIF_F_ALL_CSUM;
> } else if (illegal_highdma(skb->dev, skb)) {
> features &= ~NETIF_F_SG;
> }
>
> For Dove, can_checksum_protocol() would return false for IPv6, which
> would allow the first "if" statement to succeed, hence clearing
> NETIF_F_ALL_CSUM.
>
> This would prevent the second if() being evaluated - which seems to
> remove the check for any fragments in highmem. David - shouldn't these
> two checks be independent?
>
> --
> FTTC broadband for 0.8mile line: currently at 9.5Mbps down 400kbps up
> according to speedtest.net.
--
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.
^ permalink raw reply
* Re: [PATCH 11/11] usb: core: fix a race with usb_queue_reset_device()
From: Oliver Neukum @ 2015-01-20 13:48 UTC (permalink / raw)
To: Olivier Sobrie
Cc: Jan Dumon, Greg Kroah-Hartman, linux-kernel, linux-usb, netdev
In-Reply-To: <1421756978-4093-12-git-send-email-olivier@sobrie.be>
On Tue, 2015-01-20 at 13:29 +0100, Olivier Sobrie wrote:
> When usb_queue_reset() is called it schedules a work in view of
> resetting the usb interface. When the reset work is running, it
> can be scheduled again (e.g. by the usb disconnect method of
> the driver).
>
> Consider that the reset work is queued again while the reset work
> is running and that this work leads to a forced unbinding of the
> usb interface (e.g. because a driver is bound to the interface
> and has no pre/post_reset methods - see usb_reset_device()).
> In such condition, usb_unbind_interface() gets called and this
> function calls usb_cancel_queued_reset() which does nothing
> because the flag "reset_running" is set to 1. The second reset
> work that has been scheduled is therefore not cancelled.
> Later, the usb_reset_device() tries to rebind the interface.
> If it fails, then the usb interface context which contain the
> reset work struct is freed and it most likely crash when the
> second reset work tries to be run.
>
> The following flow shows the problem:
> * usb_queue_reset_device()
> * __usb_queue_reset_device() <- If the reset work is queued after here, then
> reset_running = 1 it will never be cancelled.
> usb_reset_device()
> usb_forced_unbind_intf()
> usb_driver_release_interface()
> usb_unbind_interface()
> driver->disconnect()
> usb_queue_reset_device() <- second reset
That is the sledgehammer approach. Wouldn't it be better to guarantee
that usb_queue_reset_device() be a nop when reset_running==1 ?
> usb_cancel_queued_reset() <- does nothing because
> the flag reset_running
> is set
> usb_unbind_and_rebind_marked_interfaces()
> usb_rebind_intf()
> device_attach()
> driver->probe() <- fails (no more drivers hold a reference to
> the usb interface)
> reset_running = 0
> * hub_event()
> usb_disconnect()
> usb_disable_device()
> kobject_release()
> device_release()
> usb_release_interface()
> kfree(intf) <- usb interface context is released
> while we still have a pending reset
> work that should be run
>
> To avoid this problem, we use a delayed work so that if the reset
> work is currently run, we can avoid further call to
> __usb_queue_reset_device() work by using cancel_delayed_work().
> Unfortunately it increases the size of the usb_interface structure...
Regards
Oliver
--
Oliver Neukum <oneukum@suse.de>
^ permalink raw reply
* Re: Bug: mv643xxx fails with highmem
From: Ezequiel Garcia @ 2015-01-20 13:42 UTC (permalink / raw)
To: Russell King - ARM Linux, David Miller, Linus Torvalds
Cc: Nimrod Andy, Fabio Estevam, netdev, fugang.duan
In-Reply-To: <20150120134104.GA12253@n2100.arm.linux.org.uk>
On 01/20/2015 10:41 AM, Russell King - ARM Linux wrote:
> Ping. What's happening on this?
>
> I guess we don't care about regressions in the Linux kernel?
>
Sorry, a holiday trip got in the middle of this.
I'll try to submit a fix this week.
--
Ezequiel García, Free Electrons
Embedded Linux, Kernel and Android Engineering
http://free-electrons.com
^ permalink raw reply
* PHYless ethernet switch MAC-MAC serdes connection
From: Vijay @ 2015-01-20 13:20 UTC (permalink / raw)
To: netdev
Hello All,
I have a custom board with Marvell 88E6046 ethernet switch which is
connected directly to freescale P1010 processor.
+------------+
| | +------------+
| | SGMII | |----- p0
| eth0 |-------------| p9 |
| | | |----- p1
| | +------------+
| | 88e6086 (Switch)
| |
| |
| | SGMII +-------------+
| eth1 |-------------| |
+--------------+ +-------------+
FS P1010 88E1512 ( PHY)
My dts looks like this,
mii_bus0: mdio@24000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,etsec2-mdio";
reg = <0x24000 0x1000 0xb0030 0x4>;
/* No PHY on external MDIO for 88e6086 Switch,
PHYless direct connection*/
/*------------*/
/* External PHY 88E1512 for eth1 */
phy1: ethernet-phy@1 {
interrupt-parent = <&mpic>;
interrupts = <3 1>;
reg = <0x1>;
};
};
mdio@25000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,etsec2-tbi";
reg = <0x25000 0x1000 0xb1030 0x4>;
tbi0: tbi-phy@11 { /* TBI
needed by gianfar for fixed-link eth0 */
reg = <0x11>;
device_type = "tbi-phy";
};
};
mdio@26000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,etsec2-tbi";
reg = <0x26000 0x1000 0xb1030 0x4>;
tbi1: tbi-phy@12 {
reg = <0x12>;
device_type = "tbi-phy";
};
};
enet1: ethernet@b1000 { /*switch
connected here*/
#address-cells = <1>;
#size-cells = <1>;
device_type = "network";
model = "eTSEC";
compatible = "fsl,etsec2";
reg = <0xb1000 0x1000>;
interrupts = <35 2 36 2 40 2>;
fsl,num_rx_queues = <0x1>;
fsl,num_tx_queues = <0x1>;
local-mac-address = [ 00 00 00 00 00 00 ];
interrupt-parent = <&mpic>;
fixed-link = <0 1 1000 0 0>;
tbi-handle = <&tbi0>;
phy-mode = "sgmii";
queue-group@0 {
#address-cells = <1>;
#size-cells = <1>;
reg = <0xb1000 0x1000>;
rx-bit-map = <0xff>;
tx-bit-map = <0xff>;
interrupts = <35 2 36 2 40 2>;
};
};
enet2: ethernet@b2000 {
#address-cells = <1>;
#size-cells = <1>;
device_type = "network";
model = "eTSEC";
compatible = "fsl,etsec2";
fsl,num_rx_queues = <0x1>;
fsl,num_tx_queues = <0x1>;
local-mac-address = [ 00 00 00 00 00 00 ];
interrupt-parent = <&mpic>;
phy-handle = <&phy1>;
tbi-handle = <&tbi1>;
phy-connection-type = "sgmii";
ptimer-handle = < &ptp_timer >;
queue-group@0 {
#address-cells = <1>;
#size-cells = <1>;
reg = <0xb2000 0x1000>;
rx-bit-map = <0xff>;
tx-bit-map = <0xff>;
interrupts = <31 2 32 2 33 2>;
};
};
dsa@0 {
compatible = "marvell,dsa";
#address-cells = <2>;
#size-cells = <0>;
dsa,ethernet = <&enet1>;
dsa,mii-bus = <&mii_bus0>;
switch@0 {
#address-cells = <1>;
#size-cells = <0>;
reg = <31 0>; /* Switch at SMI Add 0x1f */
port@0 {
reg = <0>;
label = "lan1";
};
port@1 {
reg = <1>;
label = "lan2";
};
port@9 {
reg = <9>;
label = "cpu";
};
};
};
I have disabled auto-negotiation in gianfar driver for fixed-link eth0
and associated TBI-PHY, so that SGMII link at 1Gb/ps can be forced with
switch port 9 GMII MAC.
Linux DSA driver is able to detect and configure switch. It discover
switch at external MDIO bus, DSA configure 'eth0' as master and 'lan1'
and 'lan2' as slave port.
After assigning IPs to eth0 (Switch) and eth1 ( with external PHY) like,
ifconfig eth0 up
ifconfig lan1 xx.xx.xx.x1 up
ifconfig lan2 xx.xx.xx.x2 up
ifconfig eth1 xx.xx.xx.x3 up
When I ping from any other host on network, only lan1 is able to
respond, because it was configured first. If any other port is pinged it
will be able to respond
only if 'lan1 is connected to network'. If ethernet cable from lan1 is
removed, rest of ports will not be able to respond, though they will be
receiving packets but
their TX counter will not increase.
It seems whichever port is configured first ( lan1 here ) will be able
to transmit packets. If eth1 ( connected to Phy not switch) is
configured first then only this
will be able to respond. All other ports then depends on eth1.
I tried to move 'eth1' to another mdio bus ( mdio@25000 ) by modifying
dts file above. But it seems 'PHY' and 'Switch' will only be detected if
they are on
mdio@24000.
What could be the reason of such strange behaviour ?
Why only one interface is controlling the bus its either eth0/lan0/lan1
or eth1. Rx counter of every interface increments but only one of these
have Tx counter incremented. If I disable switch ports ( lan0/lan1),
strangely eth1 also does not receive any packets ( though its Rx counter
increments but Tx is 0). Is it happening because dsa@0 also controlling
phy1 on same mdio bus ?
^ permalink raw reply
* [PATCH 0/3 net-next] rhashtable: Notify on resize to allow signaling interrupted dumps
From: Thomas Graf @ 2015-01-20 13:20 UTC (permalink / raw)
To: davem, kaber, herbert, paulmck, ying.xue; +Cc: netdev, netfilter-devel
Netlink dumps have a traditional weakness of being interruptible and
non-atomic. Once the message buffer has been filled, all protective
locks must be released and the buffer is handed over to the user to
copy the data. The dumping then continues from the previously stored
offsets in the data structures. Due to dropping of the locks, mutations
can occur.
This first series introduces a new notification mechanism which allows
users of rhashtable to bump a sequence number on resizes and report
an inconsistent dump to user space.
As discussed in the netdev thread ("[PATCH 7/9] rhashtable: Per bucket
locks & deferred expansion/shrinking").
Thomas Graf (3):
rhashtable: Provide notifier for deferred resizes
netlink: Mark dumps as inconsistent which have been interrupted by a
resize
netlink: Lock out table resizes while dumping Netlink sockets
include/linux/rhashtable.h | 10 +++++++++-
lib/rhashtable.c | 13 ++++++++++---
net/netlink/af_netlink.c | 10 ++++++++++
net/netlink/af_netlink.h | 1 +
net/netlink/diag.c | 4 ++++
5 files changed, 34 insertions(+), 4 deletions(-)
--
1.9.3
^ permalink raw reply
* [PATCH 3/3] netlink: Lock out table resizes while dumping Netlink sockets
From: Thomas Graf @ 2015-01-20 13:20 UTC (permalink / raw)
To: davem, kaber, herbert, paulmck, ying.xue; +Cc: netdev, netfilter-devel
In-Reply-To: <cover.1421759056.git.tgraf@suug.ch>
Lock out table resizes while dumping Netlink sockets to user space.
This keeps disruptions to a minimum for readers which don't handle
the NLM_F_DUMP_INTR flag.
Signed-off-by: Thomas Graf <tgraf@suug.ch>
---
net/netlink/diag.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/net/netlink/diag.c b/net/netlink/diag.c
index 50aa385..be4ea6e 100644
--- a/net/netlink/diag.c
+++ b/net/netlink/diag.c
@@ -114,6 +114,8 @@ static int __netlink_diag_dump(struct sk_buff *skb, struct netlink_callback *cb,
req = nlmsg_data(cb->nlh);
cb->seq = atomic_read(&nl_table_seq);
+ mutex_lock(&ht->mutex);
+
for (i = 0; i < htbl->size; i++) {
struct rhash_head *pos;
@@ -161,6 +163,7 @@ static int __netlink_diag_dump(struct sk_buff *skb, struct netlink_callback *cb,
num++;
}
done:
+ mutex_unlock(&ht->mutex);
cb->args[0] = num;
cb->args[1] = protocol;
--
1.9.3
^ permalink raw reply related
* [PATCH 1/3] rhashtable: Provide notifier for deferred resizes
From: Thomas Graf @ 2015-01-20 13:20 UTC (permalink / raw)
To: davem, kaber, herbert, paulmck, ying.xue; +Cc: netdev, netfilter-devel
In-Reply-To: <cover.1421759056.git.tgraf@suug.ch>
Allowing users of rhashtable to bump a sequence counter and invalidate
Netlink dumps which have been interrupted by a deferred resize.
Signed-off-by: Thomas Graf <tgraf@suug.ch>
---
include/linux/rhashtable.h | 10 +++++++++-
lib/rhashtable.c | 13 ++++++++++---
2 files changed, 19 insertions(+), 4 deletions(-)
diff --git a/include/linux/rhashtable.h b/include/linux/rhashtable.h
index a2562ed..b711d16 100644
--- a/include/linux/rhashtable.h
+++ b/include/linux/rhashtable.h
@@ -1,7 +1,7 @@
/*
* Resizable, Scalable, Concurrent Hash Table
*
- * Copyright (c) 2014 Thomas Graf <tgraf@suug.ch>
+ * Copyright (c) 2014-2015 Thomas Graf <tgraf@suug.ch>
* Copyright (c) 2008-2014 Patrick McHardy <kaber@trash.net>
*
* Based on the following paper by Josh Triplett, Paul E. McKenney
@@ -64,6 +64,11 @@ typedef u32 (*rht_obj_hashfn_t)(const void *data, u32 seed);
struct rhashtable;
+enum rht_resize_op {
+ RHT_GROWING,
+ RHT_SHRINKING,
+};
+
/**
* struct rhashtable_params - Hash table construction parameters
* @nelem_hint: Hint on number of elements, should be 75% of desired size
@@ -79,6 +84,7 @@ struct rhashtable;
* @obj_hashfn: Function to hash object
* @grow_decision: If defined, may return true if table should expand
* @shrink_decision: If defined, may return true if table should shrink
+ * @resize_notify: Called when a table resize is scheduled.
*
* Note: when implementing the grow and shrink decision function, min/max
* shift must be enforced, otherwise, resizing watermarks they set may be
@@ -100,6 +106,8 @@ struct rhashtable_params {
size_t new_size);
bool (*shrink_decision)(const struct rhashtable *ht,
size_t new_size);
+ void (*resize_notify)(const struct rhashtable *ht,
+ enum rht_resize_op op);
};
/**
diff --git a/lib/rhashtable.c b/lib/rhashtable.c
index 84a78e3..a4449c4 100644
--- a/lib/rhashtable.c
+++ b/lib/rhashtable.c
@@ -1,7 +1,7 @@
/*
* Resizable, Scalable, Concurrent Hash Table
*
- * Copyright (c) 2014 Thomas Graf <tgraf@suug.ch>
+ * Copyright (c) 2014-2015 Thomas Graf <tgraf@suug.ch>
* Copyright (c) 2008-2014 Patrick McHardy <kaber@trash.net>
*
* Based on the following paper:
@@ -489,10 +489,17 @@ static void rht_deferred_worker(struct work_struct *work)
mutex_lock(&ht->mutex);
tbl = rht_dereference(ht->tbl, ht);
- if (ht->p.grow_decision && ht->p.grow_decision(ht, tbl->size))
+ if (ht->p.grow_decision && ht->p.grow_decision(ht, tbl->size)) {
+ if (ht->p.resize_notify)
+ ht->p.resize_notify(ht, RHT_GROWING);
+
rhashtable_expand(ht);
- else if (ht->p.shrink_decision && ht->p.shrink_decision(ht, tbl->size))
+ } else if (ht->p.shrink_decision && ht->p.shrink_decision(ht, tbl->size)) {
+ if (ht->p.resize_notify)
+ ht->p.resize_notify(ht, RHT_SHRINKING);
+
rhashtable_shrink(ht);
+ }
mutex_unlock(&ht->mutex);
}
--
1.9.3
^ permalink raw reply related
* [PATCH 2/3] netlink: Mark dumps as inconsistent which have been interrupted by a resize
From: Thomas Graf @ 2015-01-20 13:20 UTC (permalink / raw)
To: davem, kaber, herbert, paulmck, ying.xue; +Cc: netdev, netfilter-devel
In-Reply-To: <cover.1421759056.git.tgraf@suug.ch>
A deferred resize of nl_table causes the offsets that Netlink diag keeps
to become inaccurate. Mark the dump as inconsistent and have user space
request a new dump.
Signed-off-by: Thomas Graf <tgraf@suug.ch>
---
net/netlink/af_netlink.c | 10 ++++++++++
net/netlink/af_netlink.h | 1 +
net/netlink/diag.c | 1 +
3 files changed, 12 insertions(+)
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 7a94185..e214557 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -91,6 +91,9 @@ static inline int netlink_is_kernel(struct sock *sk)
struct netlink_table *nl_table;
EXPORT_SYMBOL_GPL(nl_table);
+atomic_t nl_table_seq;
+EXPORT_SYMBOL_GPL(nl_table_seq);
+
static DECLARE_WAIT_QUEUE_HEAD(nl_table_wait);
static int netlink_dump(struct sock *sk);
@@ -3071,6 +3074,12 @@ static const struct net_proto_family netlink_family_ops = {
.owner = THIS_MODULE, /* for consistency 8) */
};
+static void nl_table_resize_notify(const struct rhashtable *ht,
+ enum rht_resize_op op)
+{
+ atomic_inc(&nl_table_seq);
+}
+
static int __net_init netlink_net_init(struct net *net)
{
#ifdef CONFIG_PROC_FS
@@ -3124,6 +3133,7 @@ static int __init netlink_proto_init(void)
.max_shift = 16, /* 64K */
.grow_decision = rht_grow_above_75,
.shrink_decision = rht_shrink_below_30,
+ .resize_notify = nl_table_resize_notify,
};
if (err != 0)
diff --git a/net/netlink/af_netlink.h b/net/netlink/af_netlink.h
index 7518375..51c23c0 100644
--- a/net/netlink/af_netlink.h
+++ b/net/netlink/af_netlink.h
@@ -74,5 +74,6 @@ struct netlink_table {
extern struct netlink_table *nl_table;
extern rwlock_t nl_table_lock;
+extern atomic_t nl_table_seq;
#endif
diff --git a/net/netlink/diag.c b/net/netlink/diag.c
index 3ee63a3..50aa385 100644
--- a/net/netlink/diag.c
+++ b/net/netlink/diag.c
@@ -112,6 +112,7 @@ static int __netlink_diag_dump(struct sk_buff *skb, struct netlink_callback *cb,
int ret = 0, num = 0, i;
req = nlmsg_data(cb->nlh);
+ cb->seq = atomic_read(&nl_table_seq);
for (i = 0; i < htbl->size; i++) {
struct rhash_head *pos;
--
1.9.3
^ permalink raw reply related
* [PATCH net 2/2] bnx2x: fix napi poll return value for repoll
From: Govindarajulu Varadarajan @ 2015-01-20 13:16 UTC (permalink / raw)
To: davem, netdev, ariel.elior; +Cc: ssujith, benve, Govindarajulu Varadarajan
In-Reply-To: <1421759776-376-1-git-send-email-_govind@gmx.com>
With the commit d75b1ade567ffab ("net: less interrupt masking in NAPI") napi repoll
is done only when work_done == budget. When in busy_poll is we return 0 in
napi_poll. We should return budget. Also do not return workdone > budget.
Signed-off-by: Govindarajulu Varadarajan <_govind@gmx.com>
---
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index 1d1147c..ebcbe92 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -3175,7 +3175,7 @@ static int bnx2x_poll(struct napi_struct *napi, int budget)
}
#endif
if (!bnx2x_fp_lock_napi(fp))
- return work_done;
+ return budget;
for_each_cos_in_tx_queue(fp, cos)
if (bnx2x_tx_queue_has_work(fp->txdata_ptr[cos]))
@@ -3187,7 +3187,7 @@ static int bnx2x_poll(struct napi_struct *napi, int budget)
/* must not complete if we consumed full budget */
if (work_done >= budget) {
bnx2x_fp_unlock_napi(fp);
- break;
+ return budget;
}
}
--
2.2.2
^ permalink raw reply related
* [PATCH net 1/2] enic: fix rx napi poll return value
From: Govindarajulu Varadarajan @ 2015-01-20 13:16 UTC (permalink / raw)
To: davem, netdev, ariel.elior; +Cc: ssujith, benve, Govindarajulu Varadarajan
In-Reply-To: <1421759776-376-1-git-send-email-_govind@gmx.com>
With the commit d75b1ade567ffab ("net: less interrupt masking in NAPI") napi repoll
is done only when work_done == budget. When we are in busy_poll we return 0 in
napi_poll. We should return budget.
Signed-off-by: Govindarajulu Varadarajan <_govind@gmx.com>
---
drivers/net/ethernet/cisco/enic/enic_main.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c
index b29e027..e356afa 100644
--- a/drivers/net/ethernet/cisco/enic/enic_main.c
+++ b/drivers/net/ethernet/cisco/enic/enic_main.c
@@ -1335,7 +1335,7 @@ static int enic_poll_msix_rq(struct napi_struct *napi, int budget)
int err;
if (!enic_poll_lock_napi(&enic->rq[rq]))
- return work_done;
+ return budget;
/* Service RQ
*/
--
2.2.2
^ permalink raw reply related
* [PATCH net 0/2] fix napi return value
From: Govindarajulu Varadarajan @ 2015-01-20 13:16 UTC (permalink / raw)
To: davem, netdev, ariel.elior; +Cc: ssujith, benve, Govindarajulu Varadarajan
Since d75b1ade567ffab ("net: less interrupt masking in NAPI") we should return
budget for napi repoll.
In enic, we return 0 when busy_poll is happening. Fix this by returning budget.
Looks like bnx2x needs this fix as well. On bnx2x I performed compile
test only. I do not have hardware.
Govindarajulu Varadarajan (2):
enic: fix rx napi poll return value
bnx2x: fix napi poll return value for repoll
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | 4 ++--
drivers/net/ethernet/cisco/enic/enic_main.c | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
--
2.2.2
^ permalink raw reply
* Re: [PATCH 04/11] hso: fix memory leak in hso_create_rfkill()
From: Oliver Neukum @ 2015-01-20 13:13 UTC (permalink / raw)
To: Olivier Sobrie
Cc: Jan Dumon, Greg Kroah-Hartman, linux-kernel, linux-usb, netdev
In-Reply-To: <1421756978-4093-5-git-send-email-olivier@sobrie.be>
On Tue, 2015-01-20 at 13:29 +0100, Olivier Sobrie wrote:
> When the rfkill interface was created, a buffer containing the name
> of the rfkill node was allocated. This buffer was never freed when the
> device disappears.
>
> To fix the problem, we put the name given to rfkill_alloc() in
> the hso_net structure.
>
> Signed-off-by: Olivier Sobrie <olivier@sobrie.be>
> ---
> drivers/net/usb/hso.c | 12 +++---------
> 1 file changed, 3 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c
> index 470ef9e..a49ac2e 100644
> --- a/drivers/net/usb/hso.c
> +++ b/drivers/net/usb/hso.c
> @@ -153,6 +153,7 @@ struct hso_net {
> struct hso_device *parent;
> struct net_device *net;
> struct rfkill *rfkill;
> + char name[8];
>
> struct usb_endpoint_descriptor *in_endp;
> struct usb_endpoint_descriptor *out_endp;
> @@ -2467,27 +2468,20 @@ static void hso_create_rfkill(struct hso_device *hso_dev,
> {
> struct hso_net *hso_net = dev2net(hso_dev);
> struct device *dev = &hso_net->net->dev;
> - char *rfkn;
>
> - rfkn = kzalloc(20, GFP_KERNEL);
> - if (!rfkn)
> - dev_err(dev, "%s - Out of memory\n", __func__);
> -
> - snprintf(rfkn, 20, "hso-%d",
> + snprintf(hso_net->name, sizeof(hso_net->name), "hso-%d",
> interface->altsetting->desc.bInterfaceNumber);
That number is not unique. Indeed it will be identical for all devices.
Regards
Oliver
--
Oliver Neukum <oneukum@suse.de>
^ permalink raw reply
* [PATCH net-next] act_connmark: Add missing dependency on NF_CONNTRACK_MARK
From: Thomas Graf @ 2015-01-20 12:44 UTC (permalink / raw)
To: davem; +Cc: netdev, Felix Fietkau, Jamal Hadi Salim
Depending on NETFILTER is not sufficient to ensure the presence of the
'mark' field in nf_conn, also needs to depend on NF_CONNTRACK_MARK.
Fixes: 22a5dc ("net: sched: Introduce connmark action")
Cc: Felix Fietkau <nbd@openwrt.org>
Cc: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: Thomas Graf <tgraf@suug.ch>
---
net/sched/Kconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/net/sched/Kconfig b/net/sched/Kconfig
index 475e35e..7a57f66 100644
--- a/net/sched/Kconfig
+++ b/net/sched/Kconfig
@@ -713,6 +713,7 @@ config NET_ACT_BPF
config NET_ACT_CONNMARK
tristate "Netfilter Connection Mark Retriever"
depends on NET_CLS_ACT && NETFILTER && IP_NF_IPTABLES
+ depends on NF_CONNTRACK_MARK
---help---
Say Y here to allow retrieving of conn mark
--
1.9.3
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox