* [PATCHv2 net-next 05/12] sctp: implement assign_number for sctp_stream_interleave
From: Xin Long @ 2017-12-08 13:04 UTC (permalink / raw)
To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem
In-Reply-To: <cover.1512738021.git.lucien.xin@gmail.com>
assign_number is added as a member of sctp_stream_interleave, used
to assign ssn for data or mid (message id) for idata, called in
sctp_packet_append_data. sctp_chunk_assign_ssn is left as it is,
and sctp_chunk_assign_mid is added for sctp_stream_interleave_1.
This procedure is described in section 2.2.2 of RFC8260.
All sizeof(struct sctp_data_chunk) in tx path is replaced with
sctp_datachk_len, to make it right for idata as well. And also
adjust sctp_chunk_is_data for SCTP_CID_I_DATA.
After this patch, idata can be built and sent in tx path.
Note that if sp strm_interleave is set, it has to wait_connect in
sctp_sendmsg, as asoc intl_enable need to be known after 4 shake-
hands, to decide if it should use data or idata later. data and
idata can't be mixed to send in one asoc.
Signed-off-by: Xin Long <lucien.xin@gmail.com>
Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
Acked-by: Neil Horman <nhorman@tuxdriver.com>
---
include/net/sctp/constants.h | 9 +++++----
include/net/sctp/sctp.h | 4 ++--
include/net/sctp/sm.h | 2 +-
include/net/sctp/stream_interleave.h | 1 +
include/net/sctp/structs.h | 18 +++++++++++++++++-
net/sctp/output.c | 5 +++--
net/sctp/socket.c | 17 +++++++++++++++--
net/sctp/stream_interleave.c | 37 ++++++++++++++++++++++++++++++++++++
net/sctp/ulpevent.c | 4 ++--
9 files changed, 83 insertions(+), 14 deletions(-)
diff --git a/include/net/sctp/constants.h b/include/net/sctp/constants.h
index deaafa9..20ff237 100644
--- a/include/net/sctp/constants.h
+++ b/include/net/sctp/constants.h
@@ -145,12 +145,13 @@ SCTP_SUBTYPE_CONSTRUCTOR(OTHER, enum sctp_event_other, other)
SCTP_SUBTYPE_CONSTRUCTOR(PRIMITIVE, enum sctp_event_primitive, primitive)
-#define sctp_chunk_is_data(a) (a->chunk_hdr->type == SCTP_CID_DATA)
+#define sctp_chunk_is_data(a) (a->chunk_hdr->type == SCTP_CID_DATA || \
+ a->chunk_hdr->type == SCTP_CID_I_DATA)
/* Calculate the actual data size in a data chunk */
-#define SCTP_DATA_SNDSIZE(c) ((int)((unsigned long)(c->chunk_end)\
- - (unsigned long)(c->chunk_hdr)\
- - sizeof(struct sctp_data_chunk)))
+#define SCTP_DATA_SNDSIZE(c) ((int)((unsigned long)(c->chunk_end) - \
+ (unsigned long)(c->chunk_hdr) - \
+ sctp_datachk_len(&c->asoc->stream)))
/* Internal error codes */
enum sctp_ierror {
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index 906a9c0..63ac57e 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -444,13 +444,13 @@ static inline int sctp_frag_point(const struct sctp_association *asoc, int pmtu)
int frag = pmtu;
frag -= sp->pf->af->net_header_len;
- frag -= sizeof(struct sctphdr) + sizeof(struct sctp_data_chunk);
+ frag -= sizeof(struct sctphdr) + sctp_datachk_len(&asoc->stream);
if (asoc->user_frag)
frag = min_t(int, frag, asoc->user_frag);
frag = SCTP_TRUNC4(min_t(int, frag, SCTP_MAX_CHUNK_LEN -
- sizeof(struct sctp_data_chunk)));
+ sctp_datachk_len(&asoc->stream)));
return frag;
}
diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
index f950186..ca1db89 100644
--- a/include/net/sctp/sm.h
+++ b/include/net/sctp/sm.h
@@ -343,7 +343,7 @@ static inline __u16 sctp_data_size(struct sctp_chunk *chunk)
__u16 size;
size = ntohs(chunk->chunk_hdr->length);
- size -= sizeof(struct sctp_data_chunk);
+ size -= sctp_datahdr_len(&chunk->asoc->stream);
return size;
}
diff --git a/include/net/sctp/stream_interleave.h b/include/net/sctp/stream_interleave.h
index 7b9fa8d..99f399e 100644
--- a/include/net/sctp/stream_interleave.h
+++ b/include/net/sctp/stream_interleave.h
@@ -37,6 +37,7 @@ struct sctp_stream_interleave {
struct sctp_chunk *(*make_datafrag)(const struct sctp_association *asoc,
const struct sctp_sndrcvinfo *sinfo,
int len, __u8 flags, gfp_t gfp);
+ void (*assign_number)(struct sctp_chunk *chunk);
};
void sctp_stream_interleave_init(struct sctp_stream *stream);
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 96cc898..fd93973 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -399,6 +399,18 @@ void sctp_stream_update(struct sctp_stream *stream, struct sctp_stream *new);
#define sctp_ssn_skip(stream, type, sid, ssn) \
((stream)->type[sid].ssn = ssn + 1)
+/* What is the current MID number for this stream? */
+#define sctp_mid_peek(stream, type, sid) \
+ ((stream)->type[sid].mid)
+
+/* Return the next MID number for this stream. */
+#define sctp_mid_next(stream, type, sid) \
+ ((stream)->type[sid].mid++)
+
+/* Skip over this mid and all below. */
+#define sctp_mid_skip(stream, type, sid, mid) \
+ ((stream)->type[sid].mid = mid + 1)
+
/*
* Pointers to address related SCTP functions.
* (i.e. things that depend on the address family.)
@@ -623,6 +635,7 @@ struct sctp_chunk {
__u16 rtt_in_progress:1, /* This chunk used for RTT calc? */
has_tsn:1, /* Does this chunk have a TSN yet? */
has_ssn:1, /* Does this chunk have a SSN yet? */
+#define has_mid has_ssn
singleton:1, /* Only chunk in the packet? */
end_of_packet:1, /* Last chunk in the packet? */
ecn_ce_done:1, /* Have we processed the ECN CE bit? */
@@ -1360,7 +1373,10 @@ struct sctp_stream_out_ext {
};
struct sctp_stream_out {
- __u16 ssn;
+ union {
+ __u32 mid;
+ __u16 ssn;
+ };
__u8 state;
struct sctp_stream_out_ext *ext;
};
diff --git a/net/sctp/output.c b/net/sctp/output.c
index 4a865cd..01a26ee0 100644
--- a/net/sctp/output.c
+++ b/net/sctp/output.c
@@ -313,6 +313,7 @@ static enum sctp_xmit __sctp_packet_append_chunk(struct sctp_packet *packet,
/* We believe that this chunk is OK to add to the packet */
switch (chunk->chunk_hdr->type) {
case SCTP_CID_DATA:
+ case SCTP_CID_I_DATA:
/* Account for the data being in the packet */
sctp_packet_append_data(packet, chunk);
/* Disallow SACK bundling after DATA. */
@@ -724,7 +725,7 @@ static enum sctp_xmit sctp_packet_can_append_data(struct sctp_packet *packet,
* or delay in hopes of bundling a full sized packet.
*/
if (chunk->skb->len + q->out_qlen > transport->pathmtu -
- packet->overhead - sizeof(struct sctp_data_chunk) - 4)
+ packet->overhead - sctp_datachk_len(&chunk->asoc->stream) - 4)
/* Enough data queued to fill a packet */
return SCTP_XMIT_OK;
@@ -759,7 +760,7 @@ static void sctp_packet_append_data(struct sctp_packet *packet,
asoc->peer.rwnd = rwnd;
sctp_chunk_assign_tsn(chunk);
- sctp_chunk_assign_ssn(chunk);
+ asoc->stream.si->assign_number(chunk);
}
static enum sctp_xmit sctp_packet_will_fit(struct sctp_packet *packet,
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 8c33463..036f945 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -2002,7 +2002,20 @@ static int sctp_sendmsg(struct sock *sk, struct msghdr *msg, size_t msg_len)
if (err < 0)
goto out_free;
- wait_connect = true;
+ /* If stream interleave is enabled, wait_connect has to be
+ * done earlier than data enqueue, as it needs to make data
+ * or idata according to asoc->intl_enable which is set
+ * after connection is done.
+ */
+ if (sctp_sk(asoc->base.sk)->strm_interleave) {
+ timeo = sock_sndtimeo(sk, 0);
+ err = sctp_wait_for_connect(asoc, &timeo);
+ if (err)
+ goto out_unlock;
+ } else {
+ wait_connect = true;
+ }
+
pr_debug("%s: we associated primitively\n", __func__);
}
@@ -3180,7 +3193,7 @@ static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned
if (val == 0) {
val = asoc->pathmtu - sp->pf->af->net_header_len;
val -= sizeof(struct sctphdr) +
- sizeof(struct sctp_data_chunk);
+ sctp_datachk_len(&asoc->stream);
}
asoc->user_frag = val;
asoc->frag_point = sctp_frag_point(asoc, asoc->pathmtu);
diff --git a/net/sctp/stream_interleave.c b/net/sctp/stream_interleave.c
index 397c3c1..3ac47e7 100644
--- a/net/sctp/stream_interleave.c
+++ b/net/sctp/stream_interleave.c
@@ -57,16 +57,53 @@ static struct sctp_chunk *sctp_make_idatafrag_empty(
return retval;
}
+static void sctp_chunk_assign_mid(struct sctp_chunk *chunk)
+{
+ struct sctp_stream *stream;
+ struct sctp_chunk *lchunk;
+ __u32 cfsn = 0;
+ __u16 sid;
+
+ if (chunk->has_mid)
+ return;
+
+ sid = sctp_chunk_stream_no(chunk);
+ stream = &chunk->asoc->stream;
+
+ list_for_each_entry(lchunk, &chunk->msg->chunks, frag_list) {
+ struct sctp_idatahdr *hdr;
+
+ lchunk->has_mid = 1;
+
+ if (lchunk->chunk_hdr->flags & SCTP_DATA_UNORDERED)
+ continue;
+
+ hdr = lchunk->subh.idata_hdr;
+
+ if (lchunk->chunk_hdr->flags & SCTP_DATA_FIRST_FRAG)
+ hdr->ppid = lchunk->sinfo.sinfo_ppid;
+ else
+ hdr->fsn = htonl(cfsn++);
+
+ if (lchunk->chunk_hdr->flags & SCTP_DATA_LAST_FRAG)
+ hdr->mid = htonl(sctp_mid_next(stream, out, sid));
+ else
+ hdr->mid = htonl(sctp_mid_peek(stream, out, sid));
+ }
+}
+
static struct sctp_stream_interleave sctp_stream_interleave_0 = {
.data_chunk_len = sizeof(struct sctp_data_chunk),
/* DATA process functions */
.make_datafrag = sctp_make_datafrag_empty,
+ .assign_number = sctp_chunk_assign_ssn,
};
static struct sctp_stream_interleave sctp_stream_interleave_1 = {
.data_chunk_len = sizeof(struct sctp_idata_chunk),
/* I-DATA process functions */
.make_datafrag = sctp_make_idatafrag_empty,
+ .assign_number = sctp_chunk_assign_mid,
};
void sctp_stream_interleave_init(struct sctp_stream *stream)
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c
index 5447228..650b634 100644
--- a/net/sctp/ulpevent.c
+++ b/net/sctp/ulpevent.c
@@ -443,8 +443,8 @@ struct sctp_ulpevent *sctp_ulpevent_make_send_failed(
goto fail;
/* Pull off the common chunk header and DATA header. */
- skb_pull(skb, sizeof(struct sctp_data_chunk));
- len -= sizeof(struct sctp_data_chunk);
+ skb_pull(skb, sctp_datachk_len(&asoc->stream));
+ len -= sctp_datachk_len(&asoc->stream);
/* Embed the event fields inside the cloned skb. */
event = sctp_skb2event(skb);
--
2.1.0
^ permalink raw reply related
* [PATCHv2 net-next 04/12] sctp: implement make_datafrag for sctp_stream_interleave
From: Xin Long @ 2017-12-08 13:04 UTC (permalink / raw)
To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem
In-Reply-To: <cover.1512738021.git.lucien.xin@gmail.com>
To avoid hundreds of checks for the different process on I-DATA chunk,
struct sctp_stream_interleave is defined as a group of functions used
to replace the codes in some place where it needs to do different job
according to if the asoc intl_enabled is set.
With these ops, it only needs to initialize asoc->stream.si with
sctp_stream_interleave_0 for normal data if asoc intl_enable is 0,
or sctp_stream_interleave_1 for idata if asoc intl_enable is set in
sctp_stream_init.
After that, the members in asoc->stream.si can be used directly in
some special places without checking asoc intl_enable.
make_datafrag is the first member for sctp_stream_interleave, it's
used to make data or idata frags, called in sctp_datamsg_from_user.
The old function sctp_make_datafrag_empty needs to be adjust some
to fit in this ops.
Note that as idata and data chunks have different length, it also
defines data_chunk_len for sctp_stream_interleave to describe the
chunk size.
Signed-off-by: Xin Long <lucien.xin@gmail.com>
Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
Acked-by: Neil Horman <nhorman@tuxdriver.com>
---
include/net/sctp/sm.h | 5 +--
include/net/sctp/stream_interleave.h | 44 ++++++++++++++++++++
include/net/sctp/structs.h | 12 ++++++
net/sctp/Makefile | 2 +-
net/sctp/chunk.c | 6 +--
net/sctp/sm_make_chunk.c | 21 ++++------
net/sctp/stream.c | 1 +
net/sctp/stream_interleave.c | 79 ++++++++++++++++++++++++++++++++++++
8 files changed, 149 insertions(+), 21 deletions(-)
create mode 100644 include/net/sctp/stream_interleave.h
create mode 100644 net/sctp/stream_interleave.c
diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
index 5389ae0..f950186 100644
--- a/include/net/sctp/sm.h
+++ b/include/net/sctp/sm.h
@@ -199,10 +199,9 @@ struct sctp_chunk *sctp_make_cwr(const struct sctp_association *asoc,
const struct sctp_chunk *chunk);
struct sctp_chunk *sctp_make_idata(const struct sctp_association *asoc,
__u8 flags, int paylen, gfp_t gfp);
-struct sctp_chunk *sctp_make_datafrag_empty(struct sctp_association *asoc,
+struct sctp_chunk *sctp_make_datafrag_empty(const struct sctp_association *asoc,
const struct sctp_sndrcvinfo *sinfo,
- int len, const __u8 flags,
- __u16 ssn, gfp_t gfp);
+ int len, __u8 flags, gfp_t gfp);
struct sctp_chunk *sctp_make_ecne(const struct sctp_association *asoc,
const __u32 lowest_tsn);
struct sctp_chunk *sctp_make_sack(const struct sctp_association *asoc);
diff --git a/include/net/sctp/stream_interleave.h b/include/net/sctp/stream_interleave.h
new file mode 100644
index 0000000..7b9fa8d
--- /dev/null
+++ b/include/net/sctp/stream_interleave.h
@@ -0,0 +1,44 @@
+/* SCTP kernel implementation
+ * (C) Copyright Red Hat Inc. 2017
+ *
+ * These are definitions used by the stream schedulers, defined in RFC
+ * draft ndata (https://tools.ietf.org/html/draft-ietf-tsvwg-sctp-ndata-11)
+ *
+ * This SCTP implementation is free software;
+ * you can redistribute it and/or modify it under the terms of
+ * the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This SCTP implementation is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * ************************
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU CC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Please send any bug reports or fixes you make to the
+ * email addresses:
+ * lksctp developers <linux-sctp@vger.kernel.org>
+ *
+ * Written or modified by:
+ * Xin Long <lucien.xin@gmail.com>
+ */
+
+#ifndef __sctp_stream_interleave_h__
+#define __sctp_stream_interleave_h__
+
+struct sctp_stream_interleave {
+ __u16 data_chunk_len;
+ /* (I-)DATA process */
+ struct sctp_chunk *(*make_datafrag)(const struct sctp_association *asoc,
+ const struct sctp_sndrcvinfo *sinfo,
+ int len, __u8 flags, gfp_t gfp);
+};
+
+void sctp_stream_interleave_init(struct sctp_stream *stream);
+
+#endif /* __sctp_stream_interleave_h__ */
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 7026a80..96cc898 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -89,6 +89,7 @@ struct sctp_stream;
#include <net/sctp/tsnmap.h>
#include <net/sctp/ulpevent.h>
#include <net/sctp/ulpqueue.h>
+#include <net/sctp/stream_interleave.h>
/* Structures useful for managing bind/connect. */
@@ -1389,11 +1390,22 @@ struct sctp_stream {
struct sctp_stream_out_ext *rr_next;
};
};
+ struct sctp_stream_interleave *si;
};
#define SCTP_STREAM_CLOSED 0x00
#define SCTP_STREAM_OPEN 0x01
+static inline __u16 sctp_datachk_len(const struct sctp_stream *stream)
+{
+ return stream->si->data_chunk_len;
+}
+
+static inline __u16 sctp_datahdr_len(const struct sctp_stream *stream)
+{
+ return stream->si->data_chunk_len - sizeof(struct sctp_chunkhdr);
+}
+
/* SCTP_GET_ASSOC_STATS counters */
struct sctp_priv_assoc_stats {
/* Maximum observed rto in the association during subsequent
diff --git a/net/sctp/Makefile b/net/sctp/Makefile
index 1ca84a2..54bd9c1 100644
--- a/net/sctp/Makefile
+++ b/net/sctp/Makefile
@@ -14,7 +14,7 @@ sctp-y := sm_statetable.o sm_statefuns.o sm_sideeffect.o \
tsnmap.o bind_addr.o socket.o primitive.o \
output.o input.o debug.o stream.o auth.o \
offload.o stream_sched.o stream_sched_prio.o \
- stream_sched_rr.o
+ stream_sched_rr.o stream_interleave.o
sctp_probe-y := probe.o
diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c
index 7f8baa4..62adaaa 100644
--- a/net/sctp/chunk.c
+++ b/net/sctp/chunk.c
@@ -191,7 +191,7 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
*/
max_data = asoc->pathmtu -
sctp_sk(asoc->base.sk)->pf->af->net_header_len -
- sizeof(struct sctphdr) - sizeof(struct sctp_data_chunk);
+ sizeof(struct sctphdr) - sctp_datachk_len(&asoc->stream);
max_data = SCTP_TRUNC4(max_data);
/* If the the peer requested that we authenticate DATA chunks
@@ -264,8 +264,8 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
frag |= SCTP_DATA_SACK_IMM;
}
- chunk = sctp_make_datafrag_empty(asoc, sinfo, len, frag,
- 0, GFP_KERNEL);
+ chunk = asoc->stream.si->make_datafrag(asoc, sinfo, len, frag,
+ GFP_KERNEL);
if (!chunk) {
err = -ENOMEM;
goto errout;
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index b969397..23a7313 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -721,38 +721,31 @@ struct sctp_chunk *sctp_make_ecne(const struct sctp_association *asoc,
/* Make a DATA chunk for the given association from the provided
* parameters. However, do not populate the data payload.
*/
-struct sctp_chunk *sctp_make_datafrag_empty(struct sctp_association *asoc,
+struct sctp_chunk *sctp_make_datafrag_empty(const struct sctp_association *asoc,
const struct sctp_sndrcvinfo *sinfo,
- int data_len, __u8 flags, __u16 ssn,
- gfp_t gfp)
+ int len, __u8 flags, gfp_t gfp)
{
struct sctp_chunk *retval;
struct sctp_datahdr dp;
- int chunk_len;
/* We assign the TSN as LATE as possible, not here when
* creating the chunk.
*/
- dp.tsn = 0;
+ memset(&dp, 0, sizeof(dp));
+ dp.ppid = sinfo->sinfo_ppid;
dp.stream = htons(sinfo->sinfo_stream);
- dp.ppid = sinfo->sinfo_ppid;
/* Set the flags for an unordered send. */
- if (sinfo->sinfo_flags & SCTP_UNORDERED) {
+ if (sinfo->sinfo_flags & SCTP_UNORDERED)
flags |= SCTP_DATA_UNORDERED;
- dp.ssn = 0;
- } else
- dp.ssn = htons(ssn);
- chunk_len = sizeof(dp) + data_len;
- retval = sctp_make_data(asoc, flags, chunk_len, gfp);
+ retval = sctp_make_data(asoc, flags, sizeof(dp) + len, gfp);
if (!retval)
- goto nodata;
+ return NULL;
retval->subh.data_hdr = sctp_addto_chunk(retval, sizeof(dp), &dp);
memcpy(&retval->sinfo, sinfo, sizeof(struct sctp_sndrcvinfo));
-nodata:
return retval;
}
diff --git a/net/sctp/stream.c b/net/sctp/stream.c
index 76ea66b..8370e6c 100644
--- a/net/sctp/stream.c
+++ b/net/sctp/stream.c
@@ -167,6 +167,7 @@ int sctp_stream_init(struct sctp_stream *stream, __u16 outcnt, __u16 incnt,
sched->init(stream);
in:
+ sctp_stream_interleave_init(stream);
if (!incnt)
goto out;
diff --git a/net/sctp/stream_interleave.c b/net/sctp/stream_interleave.c
new file mode 100644
index 0000000..397c3c1
--- /dev/null
+++ b/net/sctp/stream_interleave.c
@@ -0,0 +1,79 @@
+/* SCTP kernel implementation
+ * (C) Copyright Red Hat Inc. 2017
+ *
+ * This file is part of the SCTP kernel implementation
+ *
+ * These functions manipulate sctp stream queue/scheduling.
+ *
+ * This SCTP implementation is free software;
+ * you can redistribute it and/or modify it under the terms of
+ * the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This SCTP implementation is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * ************************
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU CC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Please send any bug reports or fixes you make to the
+ * email addresched(es):
+ * lksctp developers <linux-sctp@vger.kernel.org>
+ *
+ * Written or modified by:
+ * Xin Long <lucien.xin@gmail.com>
+ */
+
+#include <net/sctp/sctp.h>
+#include <net/sctp/sm.h>
+#include <linux/sctp.h>
+
+static struct sctp_chunk *sctp_make_idatafrag_empty(
+ const struct sctp_association *asoc,
+ const struct sctp_sndrcvinfo *sinfo,
+ int len, __u8 flags, gfp_t gfp)
+{
+ struct sctp_chunk *retval;
+ struct sctp_idatahdr dp;
+
+ memset(&dp, 0, sizeof(dp));
+ dp.stream = htons(sinfo->sinfo_stream);
+
+ if (sinfo->sinfo_flags & SCTP_UNORDERED)
+ flags |= SCTP_DATA_UNORDERED;
+
+ retval = sctp_make_idata(asoc, flags, sizeof(dp) + len, gfp);
+ if (!retval)
+ return NULL;
+
+ retval->subh.idata_hdr = sctp_addto_chunk(retval, sizeof(dp), &dp);
+ memcpy(&retval->sinfo, sinfo, sizeof(struct sctp_sndrcvinfo));
+
+ return retval;
+}
+
+static struct sctp_stream_interleave sctp_stream_interleave_0 = {
+ .data_chunk_len = sizeof(struct sctp_data_chunk),
+ /* DATA process functions */
+ .make_datafrag = sctp_make_datafrag_empty,
+};
+
+static struct sctp_stream_interleave sctp_stream_interleave_1 = {
+ .data_chunk_len = sizeof(struct sctp_idata_chunk),
+ /* I-DATA process functions */
+ .make_datafrag = sctp_make_idatafrag_empty,
+};
+
+void sctp_stream_interleave_init(struct sctp_stream *stream)
+{
+ struct sctp_association *asoc;
+
+ asoc = container_of(stream, struct sctp_association, stream);
+ stream->si = asoc->intl_enable ? &sctp_stream_interleave_1
+ : &sctp_stream_interleave_0;
+}
--
2.1.0
^ permalink raw reply related
* [PATCHv2 net-next 03/12] sctp: add basic structures and make chunk function for idata
From: Xin Long @ 2017-12-08 13:04 UTC (permalink / raw)
To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem
In-Reply-To: <cover.1512738021.git.lucien.xin@gmail.com>
sctp_idatahdr and sctp_idata_chunk are used to define and parse
I-DATA chunk format, and sctp_make_idata is a function to build
the chunk.
The I-DATA Chunk Format is defined in section 2.1 of RFC8260.
Signed-off-by: Xin Long <lucien.xin@gmail.com>
Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
Acked-by: Neil Horman <nhorman@tuxdriver.com>
---
include/linux/sctp.h | 17 +++++++++++++++++
include/net/sctp/sm.h | 2 ++
include/net/sctp/structs.h | 1 +
net/sctp/sm_make_chunk.c | 6 ++++++
4 files changed, 26 insertions(+)
diff --git a/include/linux/sctp.h b/include/linux/sctp.h
index 6d2bd64..38e2cf6 100644
--- a/include/linux/sctp.h
+++ b/include/linux/sctp.h
@@ -243,6 +243,23 @@ struct sctp_data_chunk {
struct sctp_datahdr data_hdr;
};
+struct sctp_idatahdr {
+ __be32 tsn;
+ __be16 stream;
+ __be16 reserved;
+ __be32 mid;
+ union {
+ __u32 ppid;
+ __be32 fsn;
+ };
+ __u8 payload[0];
+};
+
+struct sctp_idata_chunk {
+ struct sctp_chunkhdr chunk_hdr;
+ struct sctp_idatahdr data_hdr;
+};
+
/* DATA Chuck Specific Flags */
enum {
SCTP_DATA_MIDDLE_FRAG = 0x00,
diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
index 70fb397..5389ae0 100644
--- a/include/net/sctp/sm.h
+++ b/include/net/sctp/sm.h
@@ -197,6 +197,8 @@ struct sctp_chunk *sctp_make_cookie_ack(const struct sctp_association *asoc,
struct sctp_chunk *sctp_make_cwr(const struct sctp_association *asoc,
const __u32 lowest_tsn,
const struct sctp_chunk *chunk);
+struct sctp_chunk *sctp_make_idata(const struct sctp_association *asoc,
+ __u8 flags, int paylen, gfp_t gfp);
struct sctp_chunk *sctp_make_datafrag_empty(struct sctp_association *asoc,
const struct sctp_sndrcvinfo *sinfo,
int len, const __u8 flags,
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 7030cbe..7026a80 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -575,6 +575,7 @@ struct sctp_chunk {
struct sctp_addiphdr *addip_hdr;
struct sctp_fwdtsn_hdr *fwdtsn_hdr;
struct sctp_authhdr *auth_hdr;
+ struct sctp_idatahdr *idata_hdr;
} subh;
__u8 *chunk_end;
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index da33c85..b969397 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -1425,6 +1425,12 @@ static struct sctp_chunk *sctp_make_data(const struct sctp_association *asoc,
return _sctp_make_chunk(asoc, SCTP_CID_DATA, flags, paylen, gfp);
}
+struct sctp_chunk *sctp_make_idata(const struct sctp_association *asoc,
+ __u8 flags, int paylen, gfp_t gfp)
+{
+ return _sctp_make_chunk(asoc, SCTP_CID_I_DATA, flags, paylen, gfp);
+}
+
static struct sctp_chunk *sctp_make_control(const struct sctp_association *asoc,
__u8 type, __u8 flags, int paylen,
gfp_t gfp)
--
2.1.0
^ permalink raw reply related
* [PATCHv2 net-next 02/12] sctp: add asoc intl_enable negotiation during 4 shakehands
From: Xin Long @ 2017-12-08 13:03 UTC (permalink / raw)
To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem
In-Reply-To: <cover.1512738021.git.lucien.xin@gmail.com>
asoc intl_enable will be set when local sp strm_interleave is set
and there's I-DATA chunk in init and init_ack extensions, as said
in section 2.2.1 of RFC8260.
asoc intl_enable indicates all data will be sent as I-DATA chunks.
Signed-off-by: Xin Long <lucien.xin@gmail.com>
Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
Acked-by: Neil Horman <nhorman@tuxdriver.com>
---
include/linux/sctp.h | 3 +++
net/sctp/sm_make_chunk.c | 18 ++++++++++++++++--
2 files changed, 19 insertions(+), 2 deletions(-)
diff --git a/include/linux/sctp.h b/include/linux/sctp.h
index da803df..6d2bd64 100644
--- a/include/linux/sctp.h
+++ b/include/linux/sctp.h
@@ -102,6 +102,9 @@ enum sctp_cid {
/* AUTH Extension Section 4.1 */
SCTP_CID_AUTH = 0x0F,
+ /* sctp ndata 5.1. I-DATA */
+ SCTP_CID_I_DATA = 0x40,
+
/* PR-SCTP Sec 3.2 */
SCTP_CID_FWD_TSN = 0xC0,
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 9bf575f..da33c85 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -228,7 +228,7 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc,
struct sctp_inithdr init;
union sctp_params addrs;
struct sctp_sock *sp;
- __u8 extensions[4];
+ __u8 extensions[5];
size_t chunksize;
__be16 types[2];
int num_ext = 0;
@@ -278,6 +278,11 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc,
if (sp->adaptation_ind)
chunksize += sizeof(aiparam);
+ if (sp->strm_interleave) {
+ extensions[num_ext] = SCTP_CID_I_DATA;
+ num_ext += 1;
+ }
+
chunksize += vparam_len;
/* Account for AUTH related parameters */
@@ -392,7 +397,7 @@ struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc,
struct sctp_inithdr initack;
union sctp_params addrs;
struct sctp_sock *sp;
- __u8 extensions[4];
+ __u8 extensions[5];
size_t chunksize;
int num_ext = 0;
int cookie_len;
@@ -442,6 +447,11 @@ struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc,
if (sp->adaptation_ind)
chunksize += sizeof(aiparam);
+ if (asoc->intl_enable) {
+ extensions[num_ext] = SCTP_CID_I_DATA;
+ num_ext += 1;
+ }
+
if (asoc->peer.auth_capable) {
auth_random = (struct sctp_paramhdr *)asoc->c.auth_random;
chunksize += ntohs(auth_random->length);
@@ -2032,6 +2042,10 @@ static void sctp_process_ext_param(struct sctp_association *asoc,
if (net->sctp.addip_enable)
asoc->peer.asconf_capable = 1;
break;
+ case SCTP_CID_I_DATA:
+ if (sctp_sk(asoc->base.sk)->strm_interleave)
+ asoc->intl_enable = 1;
+ break;
default:
break;
}
--
2.1.0
^ permalink raw reply related
* [PATCHv2 net-next 01/12] sctp: add stream interleave enable members and sockopt
From: Xin Long @ 2017-12-08 13:03 UTC (permalink / raw)
To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem
In-Reply-To: <cover.1512738021.git.lucien.xin@gmail.com>
This patch adds intl_enable in asoc and netns, and strm_interleave in
sctp_sock to indicate if stream interleave is enabled and supported.
netns intl_enable would be set via procfs, but that is not added yet
until all stream interleave codes are completely implemented; asoc
intl_enable will be set when doing 4-shakehands.
sp strm_interleave can be set by sockopt SCTP_INTERLEAVING_SUPPORTED
which is also added in this patch. This socket option is defined in
section 4.3.1 of RFC8260.
Note that strm_interleave can only be set by sockopt when both netns
intl_enable and sp frag_interleave are set.
Signed-off-by: Xin Long <lucien.xin@gmail.com>
Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
Acked-by: Neil Horman <nhorman@tuxdriver.com>
---
include/net/netns/sctp.h | 5 ++-
include/net/sctp/structs.h | 2 ++
include/uapi/linux/sctp.h | 1 +
net/sctp/socket.c | 88 +++++++++++++++++++++++++++++++++++++++++++++-
4 files changed, 94 insertions(+), 2 deletions(-)
diff --git a/include/net/netns/sctp.h b/include/net/netns/sctp.h
index ebc8132..0db7fb3 100644
--- a/include/net/netns/sctp.h
+++ b/include/net/netns/sctp.h
@@ -122,9 +122,12 @@ struct netns_sctp {
/* Flag to indicate if PR-CONFIG is enabled. */
int reconf_enable;
- /* Flag to idicate if SCTP-AUTH is enabled */
+ /* Flag to indicate if SCTP-AUTH is enabled */
int auth_enable;
+ /* Flag to indicate if stream interleave is enabled */
+ int intl_enable;
+
/*
* Policy to control SCTP IPv4 address scoping
* 0 - Disable IPv4 address scoping
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 2f8f93d..7030cbe 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -217,6 +217,7 @@ struct sctp_sock {
disable_fragments:1,
v4mapped:1,
frag_interleave:1,
+ strm_interleave:1,
recvrcvinfo:1,
recvnxtinfo:1,
data_ready_signalled:1;
@@ -1940,6 +1941,7 @@ struct sctp_association {
__u8 need_ecne:1, /* Need to send an ECNE Chunk? */
temp:1, /* Is it a temporary association? */
force_delay:1,
+ intl_enable:1,
prsctp_enable:1,
reconf_enable:1;
diff --git a/include/uapi/linux/sctp.h b/include/uapi/linux/sctp.h
index d9adab3..6ed934c 100644
--- a/include/uapi/linux/sctp.h
+++ b/include/uapi/linux/sctp.h
@@ -125,6 +125,7 @@ typedef __s32 sctp_assoc_t;
#define SCTP_SOCKOPT_PEELOFF_FLAGS 122
#define SCTP_STREAM_SCHEDULER 123
#define SCTP_STREAM_SCHEDULER_VALUE 124
+#define SCTP_INTERLEAVING_SUPPORTED 125
/* PR-SCTP policies */
#define SCTP_PR_SCTP_NONE 0x0000
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 014847e..8c33463 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -3350,7 +3350,10 @@ static int sctp_setsockopt_fragment_interleave(struct sock *sk,
if (get_user(val, (int __user *)optval))
return -EFAULT;
- sctp_sk(sk)->frag_interleave = (val == 0) ? 0 : 1;
+ sctp_sk(sk)->frag_interleave = !!val;
+
+ if (!sctp_sk(sk)->frag_interleave)
+ sctp_sk(sk)->strm_interleave = 0;
return 0;
}
@@ -4019,6 +4022,40 @@ static int sctp_setsockopt_scheduler_value(struct sock *sk,
return retval;
}
+static int sctp_setsockopt_interleaving_supported(struct sock *sk,
+ char __user *optval,
+ unsigned int optlen)
+{
+ struct sctp_sock *sp = sctp_sk(sk);
+ struct net *net = sock_net(sk);
+ struct sctp_assoc_value params;
+ int retval = -EINVAL;
+
+ if (optlen < sizeof(params))
+ goto out;
+
+ optlen = sizeof(params);
+ if (copy_from_user(¶ms, optval, optlen)) {
+ retval = -EFAULT;
+ goto out;
+ }
+
+ if (params.assoc_id)
+ goto out;
+
+ if (!net->sctp.intl_enable || !sp->frag_interleave) {
+ retval = -EPERM;
+ goto out;
+ }
+
+ sp->strm_interleave = !!params.assoc_value;
+
+ retval = 0;
+
+out:
+ return retval;
+}
+
/* API 6.2 setsockopt(), getsockopt()
*
* Applications use setsockopt() and getsockopt() to set or retrieve
@@ -4206,6 +4243,10 @@ static int sctp_setsockopt(struct sock *sk, int level, int optname,
case SCTP_STREAM_SCHEDULER_VALUE:
retval = sctp_setsockopt_scheduler_value(sk, optval, optlen);
break;
+ case SCTP_INTERLEAVING_SUPPORTED:
+ retval = sctp_setsockopt_interleaving_supported(sk, optval,
+ optlen);
+ break;
default:
retval = -ENOPROTOOPT;
break;
@@ -6981,6 +7022,47 @@ static int sctp_getsockopt_scheduler_value(struct sock *sk, int len,
return retval;
}
+static int sctp_getsockopt_interleaving_supported(struct sock *sk, int len,
+ char __user *optval,
+ int __user *optlen)
+{
+ struct sctp_assoc_value params;
+ struct sctp_association *asoc;
+ int retval = -EFAULT;
+
+ if (len < sizeof(params)) {
+ retval = -EINVAL;
+ goto out;
+ }
+
+ len = sizeof(params);
+ if (copy_from_user(¶ms, optval, len))
+ goto out;
+
+ asoc = sctp_id2assoc(sk, params.assoc_id);
+ if (asoc) {
+ params.assoc_value = asoc->intl_enable;
+ } else if (!params.assoc_id) {
+ struct sctp_sock *sp = sctp_sk(sk);
+
+ params.assoc_value = sp->strm_interleave;
+ } else {
+ retval = -EINVAL;
+ goto out;
+ }
+
+ if (put_user(len, optlen))
+ goto out;
+
+ if (copy_to_user(optval, ¶ms, len))
+ goto out;
+
+ retval = 0;
+
+out:
+ return retval;
+}
+
static int sctp_getsockopt(struct sock *sk, int level, int optname,
char __user *optval, int __user *optlen)
{
@@ -7171,6 +7253,10 @@ static int sctp_getsockopt(struct sock *sk, int level, int optname,
retval = sctp_getsockopt_scheduler_value(sk, len, optval,
optlen);
break;
+ case SCTP_INTERLEAVING_SUPPORTED:
+ retval = sctp_getsockopt_interleaving_supported(sk, len, optval,
+ optlen);
+ break;
default:
retval = -ENOPROTOOPT;
break;
--
2.1.0
^ permalink raw reply related
* [PATCHv2 net-next 00/12] sctp: Implement Stream Interleave: The I-DATA Chunk Supporting User Message Interleaving
From: Xin Long @ 2017-12-08 13:03 UTC (permalink / raw)
To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem
Stream Interleave would be Implemented in two Parts:
1. The I-DATA Chunk Supporting User Message Interleaving
2. Interaction with Other SCTP Extensions
Overview in section 1.1 of RFC8260 for Part 1:
This document describes a new chunk carrying payload data called
I-DATA. This chunk incorporates the properties of the current SCTP
DATA chunk, all the flags and fields except the Stream Sequence
Number (SSN), and also adds two new fields in its chunk header -- the
Fragment Sequence Number (FSN) and the Message Identifier (MID). The
FSN is only used for reassembling all fragments that have the same
MID and the same ordering property. The TSN is only used for the
reliable transfer in combination with Selective Acknowledgment (SACK)
chunks.
In addition, the MID is also used for ensuring ordered delivery
instead of using the stream sequence number (the I-DATA chunk omits
an SSN).
As the 1st part of Stream Interleave Implementation, this patchset adds
an ops framework named sctp_stream_interleave with a bunch of stuff that
does lots of things needed somewhere.
Then it defines sctp_stream_interleave_0 to work for normal DATA chunks
and sctp_stream_interleave_1 for I-DATA chunks.
With these functions, hundreds of if-else checks for the different process
on I-DATA chunks would be avoided. Besides, very few codes could be shared
in these two function sets.
In this patchset, it adds some basic variables, structures and socket
options firstly, then implement these functions one by one to add the
procedures for ordered idata gradually, at last adjusts some codes to
make them work for unordered idata.
To make it safe to be implemented and also not break the normal data
chunk process, this feature can't be enabled to use until all stream
interleave codes are completely accomplished.
v1 -> v2:
- fixed a checkpatch warning that a blank line was missed.
- avoided a kbuild warning reported from gcc-4.9.
Xin Long (12):
sctp: add stream interleave enable members and sockopt
sctp: add asoc intl_enable negotiation during 4 shakehands
sctp: add basic structures and make chunk function for idata
sctp: implement make_datafrag for sctp_stream_interleave
sctp: implement assign_number for sctp_stream_interleave
sctp: implement validate_data for sctp_stream_interleave
sctp: implement ulpevent_data for sctp_stream_interleave
sctp: implement enqueue_event for sctp_stream_interleave
sctp: implement renege_events for sctp_stream_interleave
sctp: implement start_pd for sctp_stream_interleave
sctp: implement abort_pd for sctp_stream_interleave
sctp: add support for the process of unordered idata
include/linux/sctp.h | 20 +
include/net/netns/sctp.h | 5 +-
include/net/sctp/constants.h | 9 +-
include/net/sctp/sctp.h | 4 +-
include/net/sctp/sm.h | 15 +-
include/net/sctp/stream_interleave.h | 54 ++
include/net/sctp/structs.h | 56 +-
include/net/sctp/ulpevent.h | 23 +-
include/net/sctp/ulpqueue.h | 10 +-
include/uapi/linux/sctp.h | 3 +
net/sctp/Makefile | 2 +-
net/sctp/associola.c | 2 +-
net/sctp/chunk.c | 8 +-
net/sctp/output.c | 5 +-
net/sctp/sm_make_chunk.c | 45 +-
net/sctp/sm_sideeffect.c | 23 +-
net/sctp/sm_statefuns.c | 21 +-
net/sctp/sm_statetable.c | 3 +
net/sctp/socket.c | 130 +++-
net/sctp/stream.c | 1 +
net/sctp/stream_interleave.c | 1118 ++++++++++++++++++++++++++++++++++
net/sctp/ulpevent.c | 15 +-
net/sctp/ulpqueue.c | 23 +-
23 files changed, 1501 insertions(+), 94 deletions(-)
create mode 100644 include/net/sctp/stream_interleave.h
create mode 100644 net/sctp/stream_interleave.c
--
2.1.0
^ permalink raw reply
* Re: Linux 4.14 - regression: broken tun/tap / bridge network with virtio - bisected
From: Michal Kubecek @ 2017-12-08 12:58 UTC (permalink / raw)
To: Andreas Hartmann; +Cc: Jason Wang, David Miller, netdev
In-Reply-To: <7bd2baab-56a7-95d1-e63b-74dc92da936b@01019freenet.de>
On Fri, Dec 08, 2017 at 01:45:38PM +0100, Andreas Hartmann wrote:
> On 12/08/2017 at 12:40 PM Michal Kubecek wrote:
> > On Fri, Dec 08, 2017 at 11:31:50AM +0100, Andreas Hartmann wrote:
> >>
> >> When will there be a fix for 4.14? It is clearly a regression. Is
> >> it possible / a good idea to just remove the complete patch series
> >> "Remove UDP Fragmentation Offload support"?
> >
> > I cannot give an exact date but the patch is queued for stable (see
> > http://patchwork.ozlabs.org/bundle/davem/stable/?state=* ) so that
> > it should land in stable-4.14 in near future (weeks at most).
>
> Which one is it? I couldn't find any patch related to this problem at
> first glance.
"[net,v2] net: accept UFO datagrams from tuntap and packet" - the
subject was mentioned in one of my earlier e-mails (with commit id).
Michal Kubecek
^ permalink raw reply
* Re: [PATCH v3 17/33] nds32: VDSO support
From: Greentime Hu @ 2017-12-08 12:46 UTC (permalink / raw)
To: Marc Zyngier
Cc: Mark Rutland, Greentime, Linux Kernel Mailing List, Arnd Bergmann,
linux-arch, Thomas Gleixner, Jason Cooper, Rob Herring, netdev,
Vincent Chen, DTML, Al Viro, David Howells, Will Deacon,
Daniel Lezcano, linux-serial-u79uwXL29TY76Z2rM5mHXA,
Geert Uytterhoeven, Linus Walleij, Greg KH, Vincent Chen
In-Reply-To: <f58c7052-c2fe-5704-a03b-41bf2e3b20b9-5wv7dgnIgG8@public.gmane.org>
Hi, Marc:
2017-12-08 20:29 GMT+08:00 Marc Zyngier <marc.zyngier-5wv7dgnIgG8@public.gmane.org>:
> On 08/12/17 11:54, Greentime Hu wrote:
>> Hi, Mark:
>>
>> 2017-12-08 18:21 GMT+08:00 Mark Rutland <mark.rutland-5wv7dgnIgG8@public.gmane.org>:
>>> On Fri, Dec 08, 2017 at 05:12:00PM +0800, Greentime Hu wrote:
>>>> From: Greentime Hu <greentime-MUIXKm3Oiri1Z/+hSey0Gg@public.gmane.org>
>>>>
>>>> This patch adds VDSO support. The VDSO code is currently used for
>>>> sys_rt_sigreturn() and optimised gettimeofday() (using the SoC timer counter).
>>>
>>> [...]
>>>
>>>> +static int grab_timer_node_info(void)
>>>> +{
>>>> + struct device_node *timer_node;
>>>> +
>>>> + timer_node = of_find_node_by_name(NULL, "timer");
>>>
>>> Please use a compatible string, rather than matching the timer by name.
>>>
>>> It's plausible that you have multiple nodes called "timer" in the DT,
>>> under different parent nodes, and this might not be the device you
>>> think it is. I see your dt in patch 24 has two timer nodes.
>>>
>>> It would be best if your clocksource driver exposed some stuct that you
>>> looked at here, so that you're guaranteed to user the same device.
>>
>> We'd like to use "timer" here because there are 2 different timer IPs
>> and we are sure that they won't be in the same SoC.
>> We think this implementation in VDSO should be platform independent to
>> get cycle-count register.
>> Our customer or other SoC provider who can use "timer" and define
>> cycle-count-offset or cycle-count-down then we can get the correct
>> cycle-count.
>>
>> We sent atcpit100 patch last time along with our arch, however we'd
>> like to send it to its sub system this time and my colleague is still
>> working on it.
>> He may send the timer patch next week.
>>
>>
>>>> + of_property_read_u32(timer_node, "cycle-count-offset",
>>>> + &vdso_data->cycle_count_offset);
>>>> + vdso_data->cycle_count_down =
>>>> + of_property_read_bool(timer_node, "cycle-count-down");
>>>
>>> ... and then you'd only need to parse these in one place, too.
>>>
>>> IIUC these are proeprties for the atcpit device, which has no
>>> documentation or driver in this series.
>>>
>>> So I'm rather confused as to what's going on here.
>>>
>>
>> These properties are defined in dts which can provide the cycle count
>> register offset address of that timer, so that we can get cycle-count.
>>
>>>> + return of_address_to_resource(timer_node, 0, &timer_res);
>>>> +}
>>>
>>>> +int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
>>>> +{
>>>
>>>> + /*Map timer to user space */
>>>> + vdso_base += PAGE_SIZE;
>>>> + prot = __pgprot(_PAGE_V | _PAGE_M_UR_KR | _PAGE_D |
>>>> + _PAGE_G | _PAGE_C_DEV);
>>>> + ret = io_remap_pfn_range(vma, vdso_base, timer_res.start >> PAGE_SHIFT,
>>>> + PAGE_SIZE, prot);
>>>> + if (ret)
>>>> + goto up_fail;
>>>
>>> Maybe this is fine, but it looks a bit suspicious.
>>>
>>> Is it safe to map IO memory to a userspace process like this?
>>>
>>> In general that isn't safe, since userspace could access other registers
>>> (if those exist), perform accesses that change the state of hardware, or
>>> make unsupported access types (e.g. unaligned, atomic) that result in
>>> errors the kernel can't handle.
>>>
>>> Does none of that apply here?
>>
>> We only provide read permission to this page so hareware state won't
>> be chagned. It will trigger exception if we try to write.
>> We will check about the alignment/atomic issue of this region.
>
> It still feels a bit odd. A hostile userspace could potentially find out
> about what the kernel is doing. For example, if the deadline of the next
> timer is accessible by reading that page, userspace could infer a lot of
> things that we'd normally want to keep hidden. Not knowing this HW, I
> cannot answer that question, but maybe you can.
>
> Another question: MMIO accesses can be quite slow. How much do you gain
> by having a vdso compared to executing a system call?
>
I think the rest of the timer registers should be fine to be read.
Anyway we will discuss about the security issue.
Based on our previous experiments.
Decrease 4,519,021 (47%) cycle count for executing gettimeofday()
with: without vDSO(using syscall) = 5,091,342 : 9,610,363
The cycle count was get by CPU performance monitor.
Thanks.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: Linux 4.14 - regression: broken tun/tap / bridge network with virtio - bisected
From: Andreas Hartmann @ 2017-12-08 12:45 UTC (permalink / raw)
To: Michal Kubecek; +Cc: Jason Wang, David Miller, netdev
In-Reply-To: <20171208114025.kjcaratqcveq7zu5@unicorn.suse.cz>
On 12/08/2017 at 12:40 PM Michal Kubecek wrote:
> On Fri, Dec 08, 2017 at 11:31:50AM +0100, Andreas Hartmann wrote:
>> On 12/08/2017 at 09:47 AM Michal Kubecek wrote:
>>> On Fri, Dec 08, 2017 at 08:21:16AM +0100, Andreas Hartmann wrote:
>>>>
>>>> All my VMs are using virtio_net. BTW: I couldn't see the problems
>>>> (sometimes, the VM couldn't be stopped at all) if all my VMs are using
>>>> e1000 as interface instead.
>>>>
>>>> This finding now matches pretty much the responsible UDP-package which
>>>> caused the stall. I already mentioned it here [2].
>>>>
>>>> To prove it, I reverted from the patch series "[PATCH v2 RFC 0/13]
>>>> Remove UDP Fragmentation Offload support" [3]
>>>>
>>>> 11/13 [v2,RFC,11/13] net: Remove all references to SKB_GSO_UDP. [4]
>>>> 12/13 [v2,RFC,12/13] inet: Remove software UFO fragmenting code. [5]
>>>> 13/13 [v2,RFC,13/13] net: Kill NETIF_F_UFO and SKB_GSO_UDP. [6]
>>>>
>>>> and applied it to Linux 4.14.4. It compiled fine and is running fine.
>>>> The vnet doesn't die anymore. Yet, I can't say if the qemu stop hangs
>>>> are gone, too.
>>>>
>>>> Obviously, there is something broken with the new UDP handling. Could
>>>> you please analyze this problem? I could test some more patches ... .
>>>
>>> Any chance your VMs were live migrated from pre-4.14 host kernel?
>>
>> No - the VMs are not live migrated. They are always running on the same
>> host - either with kernel < 4.14 or with kernel 4.14.x.
>
> This is disturbing... unless I'm mistaken, it shouldn't be possible to
> have UFO enabled on a virtio device in a VM booted on a host with 4.14
> kernel.
It is on by default. I have to explicitly switch it off. As described below.
host:
# rebooted to kernel 4.14.x
uname -r
4.14.4-2.1-default
# just checked: bridges on host have disabled ufo w/ 4.14 per default.
guest:
uname -r
4.9.63-1.2-default # same with 3.10.x
lsmod | grep -e e1000 -e virtio_net
virtio_net 32768 0
virtio 16384 4
virtio_net,virtio_balloon,virtio_pci,virtio_scsi
virtio_ring 24576 4
virtio_net,virtio_balloon,virtio_pci,virtio_scsi
lspci -vs 00:03.0
00:03.0 Ethernet controller: Red Hat, Inc Virtio network device
Subsystem: Red Hat, Inc Device 0001
Physical Slot: 3
Flags: bus master, fast devsel, latency 0, IRQ 10
I/O ports at c060 [size=32]
Memory at febf1000 (32-bit, non-prefetchable) [size=4K]
Expansion ROM at feb80000 [disabled] [size=256K]
Capabilities: [40] MSI-X: Enable+ Count=3 Masked-
Kernel driver in use: virtio-pci
Kernel modules: virtio_pci
# after ufo was manually turned off on VM boot:
ethtool -k eth0 | grep fragm
udp-fragmentation-offload: off
ethtool -K eth0 ufo on
ethtool -k eth0 | grep fragm
udp-fragmentation-offload: on
ethtool -K eth0 ufo off
ethtool -k eth0 | grep fragm
udp-fragmentation-offload: off
>
>>> If this is the case, you should try commit 0c19f846d582 ("net:
>>> accept UFO datagrams from tuntap and packet").
>>
>> It doesn't apply to 4.14.4
>>
>>> Or disabling UFO in the guest should
>>> work around the issue.
>>
>> ethtool -K ethX ufo off for each device / bridge in VM.
>>
>> Yes, this seems to work. I'll wait and see if the non stoppable
>> qemu-problem on shutdown will remain.
>>
>> When will there be a fix for 4.14? It is clearly a regression. Is it
>> possible / a good idea to just remove the complete patch series "Remove
>> UDP Fragmentation Offload support"?
>
> I cannot give an exact date but the patch is queued for stable
> (see http://patchwork.ozlabs.org/bundle/davem/stable/?state=* ) so that
> it should land in stable-4.14 in near future (weeks at most).
Which one is it? I couldn't find any patch related to this problem at
first glance.
Thanks,
Andreas
^ permalink raw reply
* Re: [PATCH v3 17/33] nds32: VDSO support
From: Marc Zyngier @ 2017-12-08 12:29 UTC (permalink / raw)
To: Greentime Hu, Mark Rutland
Cc: Greentime, Linux Kernel Mailing List, Arnd Bergmann, linux-arch,
Thomas Gleixner, Jason Cooper, Rob Herring, netdev, Vincent Chen,
DTML, Al Viro, David Howells, Will Deacon, Daniel Lezcano,
linux-serial, Geert Uytterhoeven, Linus Walleij, Greg KH,
Vincent Chen
In-Reply-To: <CAEbi=3e9Ep4_DL4SSwp15as1t7ALvw-s2gqv+NsuRZiebNGFAQ@mail.gmail.com>
On 08/12/17 11:54, Greentime Hu wrote:
> Hi, Mark:
>
> 2017-12-08 18:21 GMT+08:00 Mark Rutland <mark.rutland@arm.com>:
>> On Fri, Dec 08, 2017 at 05:12:00PM +0800, Greentime Hu wrote:
>>> From: Greentime Hu <greentime@andestech.com>
>>>
>>> This patch adds VDSO support. The VDSO code is currently used for
>>> sys_rt_sigreturn() and optimised gettimeofday() (using the SoC timer counter).
>>
>> [...]
>>
>>> +static int grab_timer_node_info(void)
>>> +{
>>> + struct device_node *timer_node;
>>> +
>>> + timer_node = of_find_node_by_name(NULL, "timer");
>>
>> Please use a compatible string, rather than matching the timer by name.
>>
>> It's plausible that you have multiple nodes called "timer" in the DT,
>> under different parent nodes, and this might not be the device you
>> think it is. I see your dt in patch 24 has two timer nodes.
>>
>> It would be best if your clocksource driver exposed some stuct that you
>> looked at here, so that you're guaranteed to user the same device.
>
> We'd like to use "timer" here because there are 2 different timer IPs
> and we are sure that they won't be in the same SoC.
> We think this implementation in VDSO should be platform independent to
> get cycle-count register.
> Our customer or other SoC provider who can use "timer" and define
> cycle-count-offset or cycle-count-down then we can get the correct
> cycle-count.
>
> We sent atcpit100 patch last time along with our arch, however we'd
> like to send it to its sub system this time and my colleague is still
> working on it.
> He may send the timer patch next week.
>
>
>>> + of_property_read_u32(timer_node, "cycle-count-offset",
>>> + &vdso_data->cycle_count_offset);
>>> + vdso_data->cycle_count_down =
>>> + of_property_read_bool(timer_node, "cycle-count-down");
>>
>> ... and then you'd only need to parse these in one place, too.
>>
>> IIUC these are proeprties for the atcpit device, which has no
>> documentation or driver in this series.
>>
>> So I'm rather confused as to what's going on here.
>>
>
> These properties are defined in dts which can provide the cycle count
> register offset address of that timer, so that we can get cycle-count.
>
>>> + return of_address_to_resource(timer_node, 0, &timer_res);
>>> +}
>>
>>> +int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
>>> +{
>>
>>> + /*Map timer to user space */
>>> + vdso_base += PAGE_SIZE;
>>> + prot = __pgprot(_PAGE_V | _PAGE_M_UR_KR | _PAGE_D |
>>> + _PAGE_G | _PAGE_C_DEV);
>>> + ret = io_remap_pfn_range(vma, vdso_base, timer_res.start >> PAGE_SHIFT,
>>> + PAGE_SIZE, prot);
>>> + if (ret)
>>> + goto up_fail;
>>
>> Maybe this is fine, but it looks a bit suspicious.
>>
>> Is it safe to map IO memory to a userspace process like this?
>>
>> In general that isn't safe, since userspace could access other registers
>> (if those exist), perform accesses that change the state of hardware, or
>> make unsupported access types (e.g. unaligned, atomic) that result in
>> errors the kernel can't handle.
>>
>> Does none of that apply here?
>
> We only provide read permission to this page so hareware state won't
> be chagned. It will trigger exception if we try to write.
> We will check about the alignment/atomic issue of this region.
It still feels a bit odd. A hostile userspace could potentially find out
about what the kernel is doing. For example, if the deadline of the next
timer is accessible by reading that page, userspace could infer a lot of
things that we'd normally want to keep hidden. Not knowing this HW, I
cannot answer that question, but maybe you can.
Another question: MMIO accesses can be quite slow. How much do you gain
by having a vdso compared to executing a system call?
Thanks,
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply
* Re: [PATCH v3 17/33] nds32: VDSO support
From: Mark Rutland @ 2017-12-08 12:14 UTC (permalink / raw)
To: Greentime Hu
Cc: Greentime, Linux Kernel Mailing List, Arnd Bergmann, linux-arch,
Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring, netdev,
Vincent Chen, DTML, Al Viro, David Howells, Will Deacon,
Daniel Lezcano, linux-serial, Geert Uytterhoeven, Linus Walleij,
Greg KH, Vincent Chen
In-Reply-To: <CAEbi=3e9Ep4_DL4SSwp15as1t7ALvw-s2gqv+NsuRZiebNGFAQ@mail.gmail.com>
On Fri, Dec 08, 2017 at 07:54:42PM +0800, Greentime Hu wrote:
> 2017-12-08 18:21 GMT+08:00 Mark Rutland <mark.rutland@arm.com>:
> > On Fri, Dec 08, 2017 at 05:12:00PM +0800, Greentime Hu wrote:
> >> +static int grab_timer_node_info(void)
> >> +{
> >> + struct device_node *timer_node;
> >> +
> >> + timer_node = of_find_node_by_name(NULL, "timer");
> >
> > Please use a compatible string, rather than matching the timer by name.
> >
> > It's plausible that you have multiple nodes called "timer" in the DT,
> > under different parent nodes, and this might not be the device you
> > think it is. I see your dt in patch 24 has two timer nodes.
> >
> > It would be best if your clocksource driver exposed some stuct that you
> > looked at here, so that you're guaranteed to user the same device.
>
> We'd like to use "timer" here because there are 2 different timer IPs
> and we are sure that they won't be in the same SoC.
> We think this implementation in VDSO should be platform independent to
> get cycle-count register.
> Our customer or other SoC provider who can use "timer" and define
> cycle-count-offset or cycle-count-down then we can get the correct
> cycle-count.
This is not the right way to do things.
So from a DT perspective, NAK.
You should not add properties to arbitrary DT bindings to handle a Linux
implementation detail.
Please remove this DT code, and have the drivers for those timer blocks
export this information to your vdso code somehow.
> We sent atcpit100 patch last time along with our arch, however we'd
> like to send it to its sub system this time and my colleague is still
> working on it.
> He may send the timer patch next week.
I think that it would make sense for that patch to be part of the arch
port, especially given that (AFAICT) there is no dirver for the other
timer IP that you mention.
[...]
> >> +int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
> >> +{
> >
> >> + /*Map timer to user space */
> >> + vdso_base += PAGE_SIZE;
> >> + prot = __pgprot(_PAGE_V | _PAGE_M_UR_KR | _PAGE_D |
> >> + _PAGE_G | _PAGE_C_DEV);
> >> + ret = io_remap_pfn_range(vma, vdso_base, timer_res.start >> PAGE_SHIFT,
> >> + PAGE_SIZE, prot);
> >> + if (ret)
> >> + goto up_fail;
> >
> > Maybe this is fine, but it looks a bit suspicious.
> >
> > Is it safe to map IO memory to a userspace process like this?
> >
> > In general that isn't safe, since userspace could access other registers
> > (if those exist), perform accesses that change the state of hardware, or
> > make unsupported access types (e.g. unaligned, atomic) that result in
> > errors the kernel can't handle.
> >
> > Does none of that apply here?
>
> We only provide read permission to this page so hareware state won't
> be chagned. It will trigger exception if we try to write.
> We will check about the alignment/atomic issue of this region.
Ok, thanks.
This is another reason to only do this for devices/drivers that we have
drivers for, since we can't know that this is safe in general.
Thanks,
Mark.
^ permalink raw reply
* Re: [PATCH v3 17/33] nds32: VDSO support
From: Greentime Hu @ 2017-12-08 11:54 UTC (permalink / raw)
To: Mark Rutland
Cc: Greentime, Linux Kernel Mailing List, Arnd Bergmann, linux-arch,
Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring, netdev,
Vincent Chen, DTML, Al Viro, David Howells, Will Deacon,
Daniel Lezcano, linux-serial, Geert Uytterhoeven, Linus Walleij,
Greg KH, Vincent Chen
In-Reply-To: <20171208102149.iqiieszktwzorkuw@lakrids.cambridge.arm.com>
Hi, Mark:
2017-12-08 18:21 GMT+08:00 Mark Rutland <mark.rutland@arm.com>:
> On Fri, Dec 08, 2017 at 05:12:00PM +0800, Greentime Hu wrote:
>> From: Greentime Hu <greentime@andestech.com>
>>
>> This patch adds VDSO support. The VDSO code is currently used for
>> sys_rt_sigreturn() and optimised gettimeofday() (using the SoC timer counter).
>
> [...]
>
>> +static int grab_timer_node_info(void)
>> +{
>> + struct device_node *timer_node;
>> +
>> + timer_node = of_find_node_by_name(NULL, "timer");
>
> Please use a compatible string, rather than matching the timer by name.
>
> It's plausible that you have multiple nodes called "timer" in the DT,
> under different parent nodes, and this might not be the device you
> think it is. I see your dt in patch 24 has two timer nodes.
>
> It would be best if your clocksource driver exposed some stuct that you
> looked at here, so that you're guaranteed to user the same device.
We'd like to use "timer" here because there are 2 different timer IPs
and we are sure that they won't be in the same SoC.
We think this implementation in VDSO should be platform independent to
get cycle-count register.
Our customer or other SoC provider who can use "timer" and define
cycle-count-offset or cycle-count-down then we can get the correct
cycle-count.
We sent atcpit100 patch last time along with our arch, however we'd
like to send it to its sub system this time and my colleague is still
working on it.
He may send the timer patch next week.
>> + of_property_read_u32(timer_node, "cycle-count-offset",
>> + &vdso_data->cycle_count_offset);
>> + vdso_data->cycle_count_down =
>> + of_property_read_bool(timer_node, "cycle-count-down");
>
> ... and then you'd only need to parse these in one place, too.
>
> IIUC these are proeprties for the atcpit device, which has no
> documentation or driver in this series.
>
> So I'm rather confused as to what's going on here.
>
These properties are defined in dts which can provide the cycle count
register offset address of that timer, so that we can get cycle-count.
>> + return of_address_to_resource(timer_node, 0, &timer_res);
>> +}
>
>> +int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
>> +{
>
>> + /*Map timer to user space */
>> + vdso_base += PAGE_SIZE;
>> + prot = __pgprot(_PAGE_V | _PAGE_M_UR_KR | _PAGE_D |
>> + _PAGE_G | _PAGE_C_DEV);
>> + ret = io_remap_pfn_range(vma, vdso_base, timer_res.start >> PAGE_SHIFT,
>> + PAGE_SIZE, prot);
>> + if (ret)
>> + goto up_fail;
>
> Maybe this is fine, but it looks a bit suspicious.
>
> Is it safe to map IO memory to a userspace process like this?
>
> In general that isn't safe, since userspace could access other registers
> (if those exist), perform accesses that change the state of hardware, or
> make unsupported access types (e.g. unaligned, atomic) that result in
> errors the kernel can't handle.
>
> Does none of that apply here?
We only provide read permission to this page so hareware state won't
be chagned. It will trigger exception if we try to write.
We will check about the alignment/atomic issue of this region.
Thanks.
^ permalink raw reply
* Re: [PATCH net-next] ip6_vti: adjust vti mtu according to mtu of output device
From: Alexey Kodanev @ 2017-12-08 11:54 UTC (permalink / raw)
To: Steffen Klassert; +Cc: netdev, David Miller, Petr Vorel
In-Reply-To: <20171208070215.nycywbhkd4u7twh7@gauss3.secunet.de>
On 12/08/2017 10:02 AM, Steffen Klassert wrote:
> On Wed, Dec 06, 2017 at 07:38:19PM +0300, Alexey Kodanev wrote:
>> LTP/udp6_ipsec_vti tests fail when sending large UDP datagrams
>> that require fragmentation and underlying device MTU <= 1500.
>> This happens because ip6_vti sets mtu to ETH_DATA_LEN and not
>> updating it depending on a destiantion address.
>>
>> Futhure attempts to send UDP packets may succeed because pmtu
>> get updated on ICMPV6_PKT_TOOBIG in vti6_err().
>>
>> Here is the example when output device MTU set to 9000:
>>
>> # ip a sh ltp_ns_veth2
>> ltp_ns_veth2@if7: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9000 ...
>> inet 10.0.0.2/24 scope global ltp_ns_veth2
>> inet6 fd00::2/64 scope global
>> ...
>> # ip li add vti6 type vti6 local fd00::2 remote fd00::1
>> # ip li show vti6
>> vti6@NONE: <POINTOPOINT,NOARP> mtu 1500 ...
>> link/tunnel6 fd00::2 peer fd00::1
>>
>> After the patch:
>>
>> # ip li add vti6 type vti6 local fd00::2 remote fd00::1
>> # ip li show vti6
>> vti6@NONE: <POINTOPOINT,NOARP> mtu 8832 ...
>> link/tunnel6 fd00::2 peer fd00::1
>>
>> Regarding ip_vti, it already tunes mtu with ip_tunnel_bind_dev():
>>
>> # ip li add vti4 type vti local 10.0.0.2 remote 10.0.0.1
>> # ip li sh vti4
>> vti4@NONE: <POINTOPOINT,NOARP> mtu 8832 ...
>> link/ipip 10.0.0.2 peer 10.0.0.1
>>
>> Reported-by: Petr Vorel <pvorel@suse.cz>
>> Signed-off-by: Alexey Kodanev <alexey.kodanev@oracle.com>
>> ---
>>
>> ip6_vti mtu offset is the same (168) as in ip_vti because ip_vti
>> offset includes two sizes of struct iphdr: in dev->hard_header_len
>> and in t_hlen in ip_tunnel_bind_dev(). I'm not sure if it's correct.
>>
>> net/ipv6/ip6_vti.c | 18 ++++++++++++++++++
>> 1 files changed, 18 insertions(+), 0 deletions(-)
>>
>> diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c
>> index dbb74f3..47e6464 100644
>> --- a/net/ipv6/ip6_vti.c
>> +++ b/net/ipv6/ip6_vti.c
>> @@ -638,6 +638,24 @@ static void vti6_link_config(struct ip6_tnl *t)
>> dev->flags |= IFF_POINTOPOINT;
>> else
>> dev->flags &= ~IFF_POINTOPOINT;
>> +
>> + if (p->flags & IP6_TNL_F_CAP_XMIT) {
>> + int strict = (ipv6_addr_type(&p->raddr) &
>> + (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL));
>> +
>> + struct rt6_info *rt = rt6_lookup(t->net,
>> + &p->raddr, &p->laddr,
>> + p->link, strict);
>> +
>> + if (!rt)
>> + return;
>> +
>> + if (rt->dst.dev) {
>> + dev->mtu = max(rt->dst.dev->mtu - dev->hard_header_len,
>> + IPV6_MIN_MTU);
>
> Hm, I'm gettting this when compiling with your patch:
>
> In file included from /home/klassert/git/ipsec-next/include/linux/list.h:9:0,
> from /home/klassert/git/ipsec-next/include/linux/module.h:9,
> from /home/klassert/git/ipsec-next/net/ipv6/ip6_vti.c:18:
> /home/klassert/git/ipsec-next/net/ipv6/ip6_vti.c: In function ‘vti6_link_config’:
> /home/klassert/git/ipsec-next/include/linux/kernel.h:808:16: warning: comparison of distinct pointer types lacks a cast
> (void) (&max1 == &max2); \
> ^
> /home/klassert/git/ipsec-next/include/linux/kernel.h:817:2: note: in expansion of macro ‘__max’
> __max(typeof(x), typeof(y), \
> ^~~~~
> /home/klassert/git/ipsec-next/net/ipv6/ip6_vti.c:654:15: note: in expansion of macro ‘max’
> dev->mtu = max(rt->dst.dev->mtu - dev->hard_header_len,
>
rt->dst.dev->mtu and dev->hard_header_len are both unsigned and
IPV6_MIN_MTU considered as int, I guess IPV6_MIN_MTU can be changed
to dev->min_mtu as it is set to the same value in setup, but checking
in the way it is done in ip6_tnl_link_config() looks better.
I'll send 2nd version.
Thanks,
Alexey
^ permalink raw reply
* Re: Linux 4.14 - regression: broken tun/tap / bridge network with virtio - bisected
From: Michal Kubecek @ 2017-12-08 11:40 UTC (permalink / raw)
To: Andreas Hartmann; +Cc: Jason Wang, David Miller, netdev
In-Reply-To: <b0e85abe-7c69-3f86-7bf0-3c13cfdfc4cb@01019freenet.de>
On Fri, Dec 08, 2017 at 11:31:50AM +0100, Andreas Hartmann wrote:
> On 12/08/2017 at 09:47 AM Michal Kubecek wrote:
> > On Fri, Dec 08, 2017 at 08:21:16AM +0100, Andreas Hartmann wrote:
> >>
> >> All my VMs are using virtio_net. BTW: I couldn't see the problems
> >> (sometimes, the VM couldn't be stopped at all) if all my VMs are using
> >> e1000 as interface instead.
> >>
> >> This finding now matches pretty much the responsible UDP-package which
> >> caused the stall. I already mentioned it here [2].
> >>
> >> To prove it, I reverted from the patch series "[PATCH v2 RFC 0/13]
> >> Remove UDP Fragmentation Offload support" [3]
> >>
> >> 11/13 [v2,RFC,11/13] net: Remove all references to SKB_GSO_UDP. [4]
> >> 12/13 [v2,RFC,12/13] inet: Remove software UFO fragmenting code. [5]
> >> 13/13 [v2,RFC,13/13] net: Kill NETIF_F_UFO and SKB_GSO_UDP. [6]
> >>
> >> and applied it to Linux 4.14.4. It compiled fine and is running fine.
> >> The vnet doesn't die anymore. Yet, I can't say if the qemu stop hangs
> >> are gone, too.
> >>
> >> Obviously, there is something broken with the new UDP handling. Could
> >> you please analyze this problem? I could test some more patches ... .
> >
> > Any chance your VMs were live migrated from pre-4.14 host kernel?
>
> No - the VMs are not live migrated. They are always running on the same
> host - either with kernel < 4.14 or with kernel 4.14.x.
This is disturbing... unless I'm mistaken, it shouldn't be possible to
have UFO enabled on a virtio device in a VM booted on a host with 4.14
kernel.
> > If this is the case, you should try commit 0c19f846d582 ("net:
> > accept UFO datagrams from tuntap and packet").
>
> It doesn't apply to 4.14.4
>
> > Or disabling UFO in the guest should
> > work around the issue.
>
> ethtool -K ethX ufo off for each device / bridge in VM.
>
> Yes, this seems to work. I'll wait and see if the non stoppable
> qemu-problem on shutdown will remain.
>
> When will there be a fix for 4.14? It is clearly a regression. Is it
> possible / a good idea to just remove the complete patch series "Remove
> UDP Fragmentation Offload support"?
I cannot give an exact date but the patch is queued for stable
(see http://patchwork.ozlabs.org/bundle/davem/stable/?state=* ) so that
it should land in stable-4.14 in near future (weeks at most).
Michal Kubecek
^ permalink raw reply
* Re: [PATCH v5 2/2] sock: Move the socket inuse to namespace.
From: Tonghao Zhang @ 2017-12-08 11:29 UTC (permalink / raw)
To: Eric Dumazet
Cc: David Miller, Cong Wang, Eric Dumazet, Willem de Bruijn,
Linux Kernel Network Developers
In-Reply-To: <CAMDZJNXoW1zPV6czAZiS1XN7Reb3w49whEnt25j8hPOQzdRJRg@mail.gmail.com>
hi all. we can add synchronize_rcu and rcu_barrier in sock_inuse_exit_net to
ensure there are no outstanding rcu callbacks using this network namespace.
we will not have to test if net->core.sock_inuse is NULL or not from
sock_inuse_add(). :)
static void __net_exit sock_inuse_exit_net(struct net *net)
{
free_percpu(net->core.prot_inuse);
+
+ synchronize_rcu();
+ rcu_barrier();
+
+ free_percpu(net->core.sock_inuse);
}
On Fri, Dec 8, 2017 at 5:52 PM, Tonghao Zhang <xiangxia.m.yue@gmail.com> wrote:
> On Fri, Dec 8, 2017 at 1:40 PM, Eric Dumazet <eric.dumazet@gmail.com> wrote:
>> On Fri, 2017-12-08 at 13:28 +0800, Tonghao Zhang wrote:
>>> On Fri, Dec 8, 2017 at 1:20 AM, Eric Dumazet <eric.dumazet@gmail.com>
>>> wrote:
>>> > On Thu, 2017-12-07 at 08:45 -0800, Tonghao Zhang wrote:
>>> > > In some case, we want to know how many sockets are in use in
>>> > > different _net_ namespaces. It's a key resource metric.
>>> > >
>>> >
>>> > ...
>>> >
>>> > > +static void sock_inuse_add(struct net *net, int val)
>>> > > +{
>>> > > + if (net->core.prot_inuse)
>>> > > + this_cpu_add(*net->core.sock_inuse, val);
>>> > > +}
>>> >
>>> > This is very confusing.
>>> >
>>> > Why testing net->core.prot_inuse for NULL is needed at all ?
>>> >
>>> > Why not testing net->core.sock_inuse instead ?
>>> >
>>>
>>> Hi Eric and Cong, oh it's a typo. it's net->core.sock_inuse there.
>>> Why
>>> we should check the net->core.sock_inuse
>>> Now show you the code:
>>>
>>> cleanup_net will call all of the network namespace exit methods,
>>> rcu_barrier, and then remove the _net_ namespace.
>>>
>>> cleanup_net:
>>> list_for_each_entry_reverse(ops, &pernet_list, list)
>>> ops_exit_list(ops, &net_exit_list);
>>>
>>> rcu_barrier(); /* for netlink sock, the ‘deferred_put_nlk_sk’
>>> will
>>> be called. But sock_inuse has been released. */
>>
>>
>> Thats would be a bug.
>>
>> Please find another way, but we want ultimately to check that before
>> net->core.sock_inuse is freed, folding the inuse count on all cpus is
>> 0, to make sure we do not have a bug somewhere.
>
> Yes, I am aware of this issue even we will destroy the network namespace.
> By the way, we can counter the socket-inuse in sock_alloc or sock_release.
> In this way, we have to hold the network namespace again(via
> get_net()) while sock
> may hold it.
>
> what do you think of this idea?
>
>> We should not have to test if net->core.sock_inuse is NULL or not from
>> sock_inuse_add(). Pointer must be there all the time.
>>
>> The freeing should only happen once we are sure sock_inuse_add() can
>> not be called anymore.
>>
>>>
>>>
>>> /* Finally it is safe to free my network namespace structure */
>>> list_for_each_entry_safe(net, tmp, &net_exit_list, exit_list) {}
>>>
>>>
>>>
>>> Release the netlink sock created in kernel(not hold the _net_
>>> namespace):
>>>
>>> netlink_release
>>> call_rcu(&nlk->rcu, deferred_put_nlk_sk);
>>>
>>> deferred_put_nlk_sk
>>> sk_free(sk);
>>>
>>>
>>> I may add a comment for sock_inuse_add in v6.
>>
>>
^ permalink raw reply
* Re: [PATCH] slip: sl_alloc(): remove unused parameter "dev_t line"
From: Marc Kleine-Budde @ 2017-12-08 11:22 UTC (permalink / raw)
To: netdev; +Cc: kernel, linux-can, Oliver Hartkopp
In-Reply-To: <20171208111859.6090-1-mkl@pengutronix.de>
[-- Attachment #1.1: Type: text/plain, Size: 1385 bytes --]
Hello Oliver,
I've the corresponding slcan patch already in my queue.
Marc
On 12/08/2017 12:18 PM, Marc Kleine-Budde wrote:
> The first and only parameter of sl_alloc() is unused, so remove it.
>
> Fixes: 5342b77c4123 slip: ("Clean up create and destroy")
> Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
> ---
> drivers/net/slip/slip.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/slip/slip.c b/drivers/net/slip/slip.c
> index cc63102ca96e..8940417c30e5 100644
> --- a/drivers/net/slip/slip.c
> +++ b/drivers/net/slip/slip.c
> @@ -731,7 +731,7 @@ static void sl_sync(void)
>
>
> /* Find a free SLIP channel, and link in this `tty' line. */
> -static struct slip *sl_alloc(dev_t line)
> +static struct slip *sl_alloc(void)
> {
> int i;
> char name[IFNAMSIZ];
> @@ -809,7 +809,7 @@ static int slip_open(struct tty_struct *tty)
>
> /* OK. Find a free SLIP channel to use. */
> err = -ENFILE;
> - sl = sl_alloc(tty_devnum(tty));
> + sl = sl_alloc();
> if (sl == NULL)
> goto err_exit;
>
>
--
Pengutronix e.K. | Marc Kleine-Budde |
Industrial Linux Solutions | Phone: +49-231-2826-924 |
Vertretung West/Dortmund | Fax: +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de |
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply
* [PATCH] slip: sl_alloc(): remove unused parameter "dev_t line"
From: Marc Kleine-Budde @ 2017-12-08 11:18 UTC (permalink / raw)
To: netdev; +Cc: kernel, David Miller, Marc Kleine-Budde
The first and only parameter of sl_alloc() is unused, so remove it.
Fixes: 5342b77c4123 slip: ("Clean up create and destroy")
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
drivers/net/slip/slip.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/slip/slip.c b/drivers/net/slip/slip.c
index cc63102ca96e..8940417c30e5 100644
--- a/drivers/net/slip/slip.c
+++ b/drivers/net/slip/slip.c
@@ -731,7 +731,7 @@ static void sl_sync(void)
/* Find a free SLIP channel, and link in this `tty' line. */
-static struct slip *sl_alloc(dev_t line)
+static struct slip *sl_alloc(void)
{
int i;
char name[IFNAMSIZ];
@@ -809,7 +809,7 @@ static int slip_open(struct tty_struct *tty)
/* OK. Find a free SLIP channel to use. */
err = -ENFILE;
- sl = sl_alloc(tty_devnum(tty));
+ sl = sl_alloc();
if (sl == NULL)
goto err_exit;
--
2.15.0
^ permalink raw reply related
* [PATCH net v3] net: phy: meson-gxl: detect LPA corruption
From: Jerome Brunet @ 2017-12-08 11:08 UTC (permalink / raw)
To: Andrew Lunn, Florian Fainelli
Cc: Jerome Brunet, Kevin Hilman, netdev, linux-arm-kernel,
linux-amlogic, linux-kernel
The purpose of this change is to fix the incorrect detection of the link
partner (LP) advertised capabilities which sometimes happens with this PHY
(roughly 1 time in a dozen)
This issue may cause the link to be negotiated at 10Mbps/Full or
10Mbps/Half when 100MBps/Full is actually possible. In some case, the link
is even completely broken and no communication is possible.
To detect the corruption, we must look for a magic undocumented bit in the
WOL bank (hint given by the SoC vendor kernel) but this is not enough to
cover all cases. We also have to look at the LPA ack. If the LP supports
Aneg but did not ack our base code when aneg is completed, we assume
something went wrong.
The detection of a corrupted LPA triggers a restart of the aneg process.
This solves the problem but may take up to 6 retries to complete.
Fixes: 7334b3e47aee ("net: phy: Add Meson GXL Internal PHY driver")
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
I suppose this patch probably seems a bit hacky, especially the part
about the link partner acknowledge. I'm trying to figure out if the
value in MII_LPA makes sense but I don't have such a deep knowledge
of the ethernet spec.
To me, it does not makes sense for the LP to support ANEG (Bit 1 in
MII_EXPENSION), the aneg to have successfully complete and, at the
same time, LP does not ACK our base code word, which we should have
sent during this aneg.
If you think this may have unintended consequences or if you have
an idea to do this differently, feel free to let me know.
This fix has been tested on the libretech-cc and khadas VIM
The v2 [0] had dependencies on other changes which were not fixes.
This v3 is re-implementation of v2 without the dependencies to be
merged as a fix and easily backportable.
All the ugly phy_write() with hexadecimal values will go away when
then clean-up gets through.
[0]: https://lkml.kernel.org/r/20171207142715.32578-6-jbrunet@baylibre.com
drivers/net/phy/meson-gxl.c | 74 ++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 73 insertions(+), 1 deletion(-)
diff --git a/drivers/net/phy/meson-gxl.c b/drivers/net/phy/meson-gxl.c
index 1ea69b7585d9..700007dd4be5 100644
--- a/drivers/net/phy/meson-gxl.c
+++ b/drivers/net/phy/meson-gxl.c
@@ -22,6 +22,7 @@
#include <linux/ethtool.h>
#include <linux/phy.h>
#include <linux/netdevice.h>
+#include <linux/bitfield.h>
static int meson_gxl_config_init(struct phy_device *phydev)
{
@@ -50,6 +51,77 @@ static int meson_gxl_config_init(struct phy_device *phydev)
return 0;
}
+/* This function is provided to cope with the possible failures of this phy
+ * during aneg process. When aneg fails, the PHY reports that aneg is done
+ * but the value found in MII_LPA is wrong:
+ * - Early failures: MII_LPA is just 0x0001. if MII_EXPANSION reports that
+ * the link partner (LP) supports aneg but the LP never acked our base
+ * code word, it is likely that we never sent it to begin with.
+ * - Late failures: MII_LPA is filled with a value which seems to make sense
+ * but it actually is not what the LP is advertising. It seems that we
+ * can detect this using a magic bit in the WOL bank (reg 12 - bit 12).
+ * If this particular bit is not set when aneg is reported being done,
+ * it means MII_LPA is likely to be wrong.
+ *
+ * In both case, forcing a restart of the aneg process solve the problem.
+ * When this failure happens, the first retry is usually successful but,
+ * in some cases, it may take up to 6 retries to get a decent result
+ */
+int meson_gxl_read_status(struct phy_device *phydev)
+{
+ int ret, wol, lpa, exp;
+
+ if (phydev->autoneg == AUTONEG_ENABLE) {
+ ret = genphy_aneg_done(phydev);
+ if (ret < 0)
+ return ret;
+ else if (!ret)
+ goto read_status_continue;
+
+ /* Need to access WOL bank, make sure the access is open */
+ ret = phy_write(phydev, 0x14, 0x0000);
+ if (ret)
+ return ret;
+ ret = phy_write(phydev, 0x14, 0x0400);
+ if (ret)
+ return ret;
+ ret = phy_write(phydev, 0x14, 0x0000);
+ if (ret)
+ return ret;
+ ret = phy_write(phydev, 0x14, 0x0400);
+ if (ret)
+ return ret;
+
+ /* Request LPI_STATUS WOL register */
+ ret = phy_write(phydev, 0x14, 0x8D80);
+ if (ret)
+ return ret;
+
+ /* Read LPI_STATUS value */
+ wol = phy_read(phydev, 0x15);
+ if (wol < 0)
+ return wol;
+
+ lpa = phy_read(phydev, MII_LPA);
+ if (lpa < 0)
+ return lpa;
+
+ exp = phy_read(phydev, MII_EXPANSION);
+ if (exp < 0)
+ return exp;
+
+ if (!(wol & BIT(12)) ||
+ ((exp & EXPANSION_NWAY) && !(lpa & LPA_LPACK))) {
+ /* Looks like aneg failed after all */
+ phydev_dbg(phydev, "LPA corruption - aneg restart\n");
+ return genphy_restart_aneg(phydev);
+ }
+ }
+
+read_status_continue:
+ return genphy_read_status(phydev);
+}
+
static struct phy_driver meson_gxl_phy[] = {
{
.phy_id = 0x01814400,
@@ -60,7 +132,7 @@ static struct phy_driver meson_gxl_phy[] = {
.config_init = meson_gxl_config_init,
.config_aneg = genphy_config_aneg,
.aneg_done = genphy_aneg_done,
- .read_status = genphy_read_status,
+ .read_status = meson_gxl_read_status,
.suspend = genphy_suspend,
.resume = genphy_resume,
},
--
2.14.3
^ permalink raw reply related
* Re: [PATCH v5 net-next] net/tcp: trace all TCP/IP state transition with tcp_set_state tracepoint
From: Marcelo Ricardo Leitner @ 2017-12-08 11:03 UTC (permalink / raw)
To: Yafang Shao
Cc: David Miller, Song Liu, Alexey Kuznetsov, yoshfuji,
Steven Rostedt, Brendan Gregg, netdev, LKML
In-Reply-To: <CALOAHbBbo+ueVt7Wu=wAvgrfFjg7LVHfo4W_hhv_d7pQzeY9+Q@mail.gmail.com>
On Fri, Dec 08, 2017 at 11:40:23AM +0800, Yafang Shao wrote:
> It will looks like these,
>
> if (sk->sk_protocol == IPPROTO_TCP)
> __tcp_set_state(newsk, TCP_SYN_RECV);
> else
> newsk->sk_state = TCP_SYN_RECV;
>
>
> if (sk->sk_protocol == IPPROTO_TCP)
> __tcp_set_state(sk, TCP_CLOSE);
> else
> sk->sk_state = TCP_CLOSE;
>
> if (sk->sk_protocol == IPPROTO_TCP)
> tcp_state_store(sk, state);
> else
> sk_state_store(sk, state);
>
>
> Some redundant code.
>
> IMO, put these similar code into a wrapper is more nice.
Agreed. Hmpf, looks like one way or another, we have to add the sk_
functions to do such check, and then the tcp_* won't help much.
I'm okay with this v5 then, can't see a better way around it.
Marcelo
^ permalink raw reply
* Re: [PATCH net 3/3] hv_netvsc: Fix the default receive buffer size
From: Dan Carpenter @ 2017-12-08 10:44 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: devel, haiyangz, sthemmin, netdev
In-Reply-To: <20171208001055.24670-4-sthemmin@microsoft.com>
On Thu, Dec 07, 2017 at 04:10:55PM -0800, Stephen Hemminger wrote:
> From: Haiyang Zhang <haiyangz@microsoft.com>
>
> The intended size is 16 MB, and the default slot size is 1728.
> So, NETVSC_DEFAULT_RX should be 16*1024*1024 / 1728 = 9709.
>
> Fixes: 5023a6db73196 ("netvsc: increase default receive buffer size")
> Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
> Signed-off-by: Stephen Hemminger <sthemmin@microsoft.com>
> ---
> drivers/net/hyperv/netvsc_drv.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
> index dc70de674ca9..edfcde5d3621 100644
> --- a/drivers/net/hyperv/netvsc_drv.c
> +++ b/drivers/net/hyperv/netvsc_drv.c
> @@ -50,7 +50,7 @@
> #define NETVSC_MIN_TX_SECTIONS 10
> #define NETVSC_DEFAULT_TX 192 /* ~1M */
> #define NETVSC_MIN_RX_SECTIONS 10 /* ~64K */
> -#define NETVSC_DEFAULT_RX 10485 /* Max ~16M */
> +#define NETVSC_DEFAULT_RX 9709 /* ~16M */
How does this bug look like to the user? Memory corruption?
It's weird to me reviewing this code that the default sizes are
stored in netvsc_drv.c and the max sizes are stored in hyperv_net.h.
Could we move these to hyperv_net.h? We could write it like:
#define NETVSC_DEFAULT_RX ((16 * 1024 * 1024) / NETVSC_RECV_SECTION_SIZE)
16MB is sort of a weird default because it's larger than the 15MB
allowed for legacy versions, but it's smaller than the 32MB you'd want
for the current versions.
regards,
dan carpenter
^ permalink raw reply
* [PATCH net-next v4 2/2] net: thunderx: add timestamping support
From: Aleksey Makarov @ 2017-12-08 10:34 UTC (permalink / raw)
To: netdev
Cc: linux-arm-kernel, linux-kernel, Goutham, Sunil,
Radoslaw Biernacki, Aleksey Makarov, Robert Richter, David Daney,
Richard Cochran, Sunil Goutham
In-Reply-To: <20171208103442.19354-1-aleksey.makarov@cavium.com>
From: Sunil Goutham <sgoutham@cavium.com>
This adds timestamping support for both receive and transmit
paths. On the receive side no filters are supported i.e either
all pkts will get a timestamp appended infront of the packet or none.
On the transmit side HW doesn't support timestamp insertion but
only generates a separate CQE with transmitted packet's timestamp.
Also HW supports only one packet at a time for timestamping on the
transmit side.
Signed-off-by: Sunil Goutham <sgoutham@cavium.com>
Signed-off-by: Aleksey Makarov <aleksey.makarov@cavium.com>
---
drivers/net/ethernet/cavium/Kconfig | 1 +
drivers/net/ethernet/cavium/thunder/nic.h | 15 ++
drivers/net/ethernet/cavium/thunder/nic_main.c | 58 ++++++-
drivers/net/ethernet/cavium/thunder/nic_reg.h | 1 +
.../net/ethernet/cavium/thunder/nicvf_ethtool.c | 29 +++-
drivers/net/ethernet/cavium/thunder/nicvf_main.c | 173 ++++++++++++++++++++-
drivers/net/ethernet/cavium/thunder/nicvf_queues.c | 26 ++++
drivers/net/ethernet/cavium/thunder/thunder_bgx.c | 29 ++++
drivers/net/ethernet/cavium/thunder/thunder_bgx.h | 4 +
9 files changed, 330 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/cavium/Kconfig b/drivers/net/ethernet/cavium/Kconfig
index 2380e9834007..d163c5bdbbcb 100644
--- a/drivers/net/ethernet/cavium/Kconfig
+++ b/drivers/net/ethernet/cavium/Kconfig
@@ -27,6 +27,7 @@ config THUNDER_NIC_PF
config THUNDER_NIC_VF
tristate "Thunder Virtual function driver"
+ select CAVIUM_PTP
depends on 64BIT
---help---
This driver supports Thunder's NIC virtual function
diff --git a/drivers/net/ethernet/cavium/thunder/nic.h b/drivers/net/ethernet/cavium/thunder/nic.h
index 4a02e618e318..204b234beb9d 100644
--- a/drivers/net/ethernet/cavium/thunder/nic.h
+++ b/drivers/net/ethernet/cavium/thunder/nic.h
@@ -263,6 +263,8 @@ struct nicvf_drv_stats {
struct u64_stats_sync syncp;
};
+struct cavium_ptp;
+
struct nicvf {
struct nicvf *pnicvf;
struct net_device *netdev;
@@ -312,6 +314,12 @@ struct nicvf {
struct tasklet_struct qs_err_task;
struct work_struct reset_task;
+ /* PTP timestamp */
+ struct cavium_ptp *ptp_clock;
+ bool hw_rx_tstamp;
+ struct sk_buff *ptp_skb;
+ atomic_t tx_ptp_skbs;
+
/* Interrupt coalescing settings */
u32 cq_coalesce_usecs;
u32 msg_enable;
@@ -371,6 +379,7 @@ struct nicvf {
#define NIC_MBOX_MSG_LOOPBACK 0x16 /* Set interface in loopback */
#define NIC_MBOX_MSG_RESET_STAT_COUNTER 0x17 /* Reset statistics counters */
#define NIC_MBOX_MSG_PFC 0x18 /* Pause frame control */
+#define NIC_MBOX_MSG_PTP_CFG 0x19 /* HW packet timestamp */
#define NIC_MBOX_MSG_CFG_DONE 0xF0 /* VF configuration done */
#define NIC_MBOX_MSG_SHUTDOWN 0xF1 /* VF is being shutdown */
@@ -521,6 +530,11 @@ struct pfc {
u8 fc_tx;
};
+struct set_ptp {
+ u8 msg;
+ bool enable;
+};
+
/* 128 bit shared memory between PF and each VF */
union nic_mbx {
struct { u8 msg; } msg;
@@ -540,6 +554,7 @@ union nic_mbx {
struct set_loopback lbk;
struct reset_stat_cfg reset_stat;
struct pfc pfc;
+ struct set_ptp ptp;
};
#define NIC_NODE_ID_MASK 0x03
diff --git a/drivers/net/ethernet/cavium/thunder/nic_main.c b/drivers/net/ethernet/cavium/thunder/nic_main.c
index 8f1dd55b3e08..4c1c5414a162 100644
--- a/drivers/net/ethernet/cavium/thunder/nic_main.c
+++ b/drivers/net/ethernet/cavium/thunder/nic_main.c
@@ -426,13 +426,22 @@ static void nic_init_hw(struct nicpf *nic)
/* Enable backpressure */
nic_reg_write(nic, NIC_PF_BP_CFG, (1ULL << 6) | 0x03);
- /* TNS and TNS bypass modes are present only on 88xx */
+ /* TNS and TNS bypass modes are present only on 88xx
+ * Also offset of this CSR has changed in 81xx and 83xx.
+ */
if (nic->pdev->subsystem_device == PCI_SUBSYS_DEVID_88XX_NIC_PF) {
/* Disable TNS mode on both interfaces */
nic_reg_write(nic, NIC_PF_INTF_0_1_SEND_CFG,
- (NIC_TNS_BYPASS_MODE << 7) | BGX0_BLOCK);
+ (NIC_TNS_BYPASS_MODE << 7) |
+ BGX0_BLOCK | (1ULL << 16));
nic_reg_write(nic, NIC_PF_INTF_0_1_SEND_CFG | (1 << 8),
- (NIC_TNS_BYPASS_MODE << 7) | BGX1_BLOCK);
+ (NIC_TNS_BYPASS_MODE << 7) |
+ BGX1_BLOCK | (1ULL << 16));
+ } else {
+ /* Configure timestamp generation timeout to 10us */
+ for (i = 0; i < nic->hw->bgx_cnt; i++)
+ nic_reg_write(nic, NIC_PF_INTFX_SEND_CFG | (i << 3),
+ (1ULL << 16));
}
nic_reg_write(nic, NIC_PF_INTF_0_1_BP_CFG,
@@ -880,6 +889,46 @@ static void nic_pause_frame(struct nicpf *nic, int vf, struct pfc *cfg)
}
}
+/* Enable or disable HW timestamping by BGX for pkts received on a LMAC */
+static void nic_config_timestamp(struct nicpf *nic, int vf, struct set_ptp *ptp)
+{
+ struct pkind_cfg *pkind;
+ u8 lmac, bgx_idx;
+ u64 pkind_val, pkind_idx;
+
+ if (vf >= nic->num_vf_en)
+ return;
+
+ bgx_idx = NIC_GET_BGX_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
+ lmac = NIC_GET_LMAC_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
+
+ pkind_idx = lmac + bgx_idx * MAX_LMAC_PER_BGX;
+ pkind_val = nic_reg_read(nic, NIC_PF_PKIND_0_15_CFG | (pkind_idx << 3));
+ pkind = (struct pkind_cfg *)&pkind_val;
+
+ if (ptp->enable && !pkind->hdr_sl) {
+ /* Skiplen to exclude 8byte timestamp while parsing pkt
+ * If not configured, will result in L2 errors.
+ */
+ pkind->hdr_sl = 4;
+ /* Adjust max packet length allowed */
+ pkind->maxlen += (pkind->hdr_sl * 2);
+ bgx_config_timestamping(nic->node, bgx_idx, lmac, true);
+ nic_reg_write(nic,
+ NIC_PF_RX_ETYPE_0_7 | (1 << 3),
+ (ETYPE_ALG_ENDPARSE << 16) | ETH_P_1588);
+ } else if (!ptp->enable && pkind->hdr_sl) {
+ pkind->maxlen -= (pkind->hdr_sl * 2);
+ pkind->hdr_sl = 0;
+ bgx_config_timestamping(nic->node, bgx_idx, lmac, false);
+ nic_reg_write(nic,
+ NIC_PF_RX_ETYPE_0_7 | (1 << 3),
+ (1ULL << 16) | ETH_P_8021Q); /* reset value */
+ }
+
+ nic_reg_write(nic, NIC_PF_PKIND_0_15_CFG | (pkind_idx << 3), pkind_val);
+}
+
/* Interrupt handler to handle mailbox messages from VFs */
static void nic_handle_mbx_intr(struct nicpf *nic, int vf)
{
@@ -1022,6 +1071,9 @@ static void nic_handle_mbx_intr(struct nicpf *nic, int vf)
case NIC_MBOX_MSG_PFC:
nic_pause_frame(nic, vf, &mbx.pfc);
goto unlock;
+ case NIC_MBOX_MSG_PTP_CFG:
+ nic_config_timestamp(nic, vf, &mbx.ptp);
+ break;
default:
dev_err(&nic->pdev->dev,
"Invalid msg from VF%d, msg 0x%x\n", vf, mbx.msg.msg);
diff --git a/drivers/net/ethernet/cavium/thunder/nic_reg.h b/drivers/net/ethernet/cavium/thunder/nic_reg.h
index 80d46337cf29..a16c48a1ebb2 100644
--- a/drivers/net/ethernet/cavium/thunder/nic_reg.h
+++ b/drivers/net/ethernet/cavium/thunder/nic_reg.h
@@ -99,6 +99,7 @@
#define NIC_PF_ECC3_DBE_INT_W1S (0x2708)
#define NIC_PF_ECC3_DBE_ENA_W1C (0x2710)
#define NIC_PF_ECC3_DBE_ENA_W1S (0x2718)
+#define NIC_PF_INTFX_SEND_CFG (0x4000)
#define NIC_PF_MCAM_0_191_ENA (0x100000)
#define NIC_PF_MCAM_0_191_M_0_5_DATA (0x110000)
#define NIC_PF_MCAM_CTRL (0x120000)
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c b/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c
index b9ece9cbf98b..ed9f10bdf41e 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c
@@ -9,12 +9,14 @@
/* ETHTOOL Support for VNIC_VF Device*/
#include <linux/pci.h>
+#include <linux/net_tstamp.h>
#include "nic_reg.h"
#include "nic.h"
#include "nicvf_queues.h"
#include "q_struct.h"
#include "thunder_bgx.h"
+#include "../common/cavium_ptp.h"
#define DRV_NAME "thunder-nicvf"
#define DRV_VERSION "1.0"
@@ -824,6 +826,31 @@ static int nicvf_set_pauseparam(struct net_device *dev,
return 0;
}
+static int nicvf_get_ts_info(struct net_device *netdev,
+ struct ethtool_ts_info *info)
+{
+ struct nicvf *nic = netdev_priv(netdev);
+
+ if (!nic->ptp_clock)
+ return ethtool_op_get_ts_info(netdev, info);
+
+ info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE |
+ SOF_TIMESTAMPING_RX_SOFTWARE |
+ SOF_TIMESTAMPING_SOFTWARE |
+ SOF_TIMESTAMPING_TX_HARDWARE |
+ SOF_TIMESTAMPING_RX_HARDWARE |
+ SOF_TIMESTAMPING_RAW_HARDWARE;
+
+ info->phc_index = cavium_ptp_clock_index(nic->ptp_clock);
+
+ info->tx_types = (1 << HWTSTAMP_TX_OFF) | (1 << HWTSTAMP_TX_ON);
+
+ info->rx_filters = (1 << HWTSTAMP_FILTER_NONE) |
+ (1 << HWTSTAMP_FILTER_ALL);
+
+ return 0;
+}
+
static const struct ethtool_ops nicvf_ethtool_ops = {
.get_link = nicvf_get_link,
.get_drvinfo = nicvf_get_drvinfo,
@@ -847,7 +874,7 @@ static const struct ethtool_ops nicvf_ethtool_ops = {
.set_channels = nicvf_set_channels,
.get_pauseparam = nicvf_get_pauseparam,
.set_pauseparam = nicvf_set_pauseparam,
- .get_ts_info = ethtool_op_get_ts_info,
+ .get_ts_info = nicvf_get_ts_info,
.get_link_ksettings = nicvf_get_link_ksettings,
};
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
index 52b3a6044f85..8e3338f31e54 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
@@ -20,11 +20,13 @@
#include <linux/bpf.h>
#include <linux/bpf_trace.h>
#include <linux/filter.h>
+#include <linux/net_tstamp.h>
#include "nic_reg.h"
#include "nic.h"
#include "nicvf_queues.h"
#include "thunder_bgx.h"
+#include "../common/cavium_ptp.h"
#define DRV_NAME "thunder-nicvf"
#define DRV_VERSION "1.0"
@@ -601,6 +603,44 @@ static inline bool nicvf_xdp_rx(struct nicvf *nic, struct bpf_prog *prog,
return false;
}
+static void nicvf_snd_ptp_handler(struct net_device *netdev,
+ struct cqe_send_t *cqe_tx)
+{
+ struct nicvf *nic = netdev_priv(netdev);
+ struct skb_shared_hwtstamps ts;
+ u64 ns;
+
+ nic = nic->pnicvf;
+
+ /* Sync for 'ptp_skb' */
+ smp_rmb();
+
+ /* New timestamp request can be queued now */
+ atomic_set(&nic->tx_ptp_skbs, 0);
+
+ /* Check for timestamp requested skb */
+ if (!nic->ptp_skb)
+ return;
+
+ /* Check if timestamping is timedout, which is set to 10us */
+ if (cqe_tx->send_status == CQ_TX_ERROP_TSTMP_TIMEOUT ||
+ cqe_tx->send_status == CQ_TX_ERROP_TSTMP_CONFLICT)
+ goto no_tstamp;
+
+ /* Get the timestamp */
+ memset(&ts, 0, sizeof(ts));
+ ns = cavium_ptp_tstamp2time(nic->ptp_clock, cqe_tx->ptp_timestamp);
+ ts.hwtstamp = ns_to_ktime(ns);
+ skb_tstamp_tx(nic->ptp_skb, &ts);
+
+no_tstamp:
+ /* Free the original skb */
+ dev_kfree_skb_any(nic->ptp_skb);
+ nic->ptp_skb = NULL;
+ /* Sync 'ptp_skb' */
+ smp_wmb();
+}
+
static void nicvf_snd_pkt_handler(struct net_device *netdev,
struct cqe_send_t *cqe_tx,
int budget, int *subdesc_cnt,
@@ -657,7 +697,12 @@ static void nicvf_snd_pkt_handler(struct net_device *netdev,
prefetch(skb);
(*tx_pkts)++;
*tx_bytes += skb->len;
- napi_consume_skb(skb, budget);
+ /* If timestamp is requested for this skb, don't free it */
+ if (skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS &&
+ !nic->pnicvf->ptp_skb)
+ nic->pnicvf->ptp_skb = skb;
+ else
+ napi_consume_skb(skb, budget);
sq->skbuff[cqe_tx->sqe_ptr] = (u64)NULL;
} else {
/* In case of SW TSO on 88xx, only last segment will have
@@ -696,6 +741,21 @@ static inline void nicvf_set_rxhash(struct net_device *netdev,
skb_set_hash(skb, hash, hash_type);
}
+static inline void nicvf_set_rxtstamp(struct nicvf *nic, struct sk_buff *skb)
+{
+ u64 ns;
+
+ if (!nic->ptp_clock || !nic->hw_rx_tstamp)
+ return;
+
+ /* The first 8 bytes is the timestamp */
+ ns = cavium_ptp_tstamp2time(nic->ptp_clock,
+ be64_to_cpu(*(__be64 *)skb->data));
+ skb_hwtstamps(skb)->hwtstamp = ns_to_ktime(ns);
+
+ __skb_pull(skb, 8);
+}
+
static void nicvf_rcv_pkt_handler(struct net_device *netdev,
struct napi_struct *napi,
struct cqe_rx_t *cqe_rx, struct snd_queue *sq)
@@ -746,6 +806,7 @@ static void nicvf_rcv_pkt_handler(struct net_device *netdev,
return;
}
+ nicvf_set_rxtstamp(nic, skb);
nicvf_set_rxhash(netdev, cqe_rx, skb);
skb_record_rx_queue(skb, rq_idx);
@@ -820,10 +881,12 @@ static int nicvf_cq_intr_handler(struct net_device *netdev, u8 cq_idx,
&tx_pkts, &tx_bytes);
tx_done++;
break;
+ case CQE_TYPE_SEND_PTP:
+ nicvf_snd_ptp_handler(netdev, (void *)cq_desc);
+ break;
case CQE_TYPE_INVALID:
case CQE_TYPE_RX_SPLIT:
case CQE_TYPE_RX_TCP:
- case CQE_TYPE_SEND_PTP:
/* Ignore for now */
break;
}
@@ -1319,12 +1382,28 @@ int nicvf_stop(struct net_device *netdev)
nicvf_free_cq_poll(nic);
+ /* Free any pending SKB saved to receive timestamp */
+ if (nic->ptp_skb) {
+ dev_kfree_skb_any(nic->ptp_skb);
+ nic->ptp_skb = NULL;
+ }
+
/* Clear multiqset info */
nic->pnicvf = nic;
return 0;
}
+static int nicvf_config_hw_rx_tstamp(struct nicvf *nic, bool enable)
+{
+ union nic_mbx mbx = {};
+
+ mbx.ptp.msg = NIC_MBOX_MSG_PTP_CFG;
+ mbx.ptp.enable = enable;
+
+ return nicvf_send_msg_to_pf(nic, &mbx);
+}
+
static int nicvf_update_hw_max_frs(struct nicvf *nic, int mtu)
{
union nic_mbx mbx = {};
@@ -1394,6 +1473,12 @@ int nicvf_open(struct net_device *netdev)
if (nic->sqs_mode)
nicvf_get_primary_vf_struct(nic);
+ /* Configure PTP timestamp */
+ if (nic->ptp_clock)
+ nicvf_config_hw_rx_tstamp(nic, nic->hw_rx_tstamp);
+ atomic_set(&nic->tx_ptp_skbs, 0);
+ nic->ptp_skb = NULL;
+
/* Configure receive side scaling and MTU */
if (!nic->sqs_mode) {
nicvf_rss_init(nic);
@@ -1820,6 +1905,77 @@ static void nicvf_xdp_flush(struct net_device *dev)
return;
}
+static int nicvf_config_hwtstamp(struct net_device *netdev, struct ifreq *ifr)
+{
+ struct hwtstamp_config config;
+ struct nicvf *nic = netdev_priv(netdev);
+
+ if (!nic->ptp_clock)
+ return -ENODEV;
+
+ if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
+ return -EFAULT;
+
+ /* reserved for future extensions */
+ if (config.flags)
+ return -EINVAL;
+
+ switch (config.tx_type) {
+ case HWTSTAMP_TX_OFF:
+ case HWTSTAMP_TX_ON:
+ break;
+ default:
+ return -ERANGE;
+ }
+
+ switch (config.rx_filter) {
+ case HWTSTAMP_FILTER_NONE:
+ nic->hw_rx_tstamp = false;
+ break;
+ case HWTSTAMP_FILTER_ALL:
+ case HWTSTAMP_FILTER_SOME:
+ case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
+ case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
+ case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
+ case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
+ case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
+ case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
+ case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
+ case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
+ case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
+ case HWTSTAMP_FILTER_PTP_V2_EVENT:
+ case HWTSTAMP_FILTER_PTP_V2_SYNC:
+ case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
+ nic->hw_rx_tstamp = true;
+ config.rx_filter = HWTSTAMP_FILTER_ALL;
+ break;
+ default:
+ return -ERANGE;
+ }
+
+ if (netif_running(netdev)) {
+ if (nic->hw_rx_tstamp)
+ nicvf_config_hw_rx_tstamp(nic, true);
+ else
+ nicvf_config_hw_rx_tstamp(nic, false);
+ }
+
+ if (copy_to_user(ifr->ifr_data, &config, sizeof(config)))
+ return -EFAULT;
+
+ return 0;
+}
+
+static int nicvf_ioctl(struct net_device *netdev, struct ifreq *req, int cmd)
+{
+ switch (cmd) {
+ case SIOCSHWTSTAMP:
+ return nicvf_config_hwtstamp(netdev, req);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
static const struct net_device_ops nicvf_netdev_ops = {
.ndo_open = nicvf_open,
.ndo_stop = nicvf_stop,
@@ -1833,6 +1989,7 @@ static const struct net_device_ops nicvf_netdev_ops = {
.ndo_bpf = nicvf_xdp,
.ndo_xdp_xmit = nicvf_xdp_xmit,
.ndo_xdp_flush = nicvf_xdp_flush,
+ .ndo_do_ioctl = nicvf_ioctl,
};
static int nicvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
@@ -1842,6 +1999,16 @@ static int nicvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
struct nicvf *nic;
int err, qcount;
u16 sdevid;
+ struct cavium_ptp *ptp_clock;
+
+ ptp_clock = cavium_ptp_get();
+ if (IS_ERR(ptp_clock)) {
+ if (PTR_ERR(ptp_clock) == -ENODEV)
+ /* In virtualized environment we proceed without ptp */
+ ptp_clock = NULL;
+ else
+ return PTR_ERR(ptp_clock);
+ }
err = pci_enable_device(pdev);
if (err) {
@@ -1896,6 +2063,7 @@ static int nicvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
*/
if (!nic->t88)
nic->max_queues *= 2;
+ nic->ptp_clock = ptp_clock;
/* MAP VF's configuration registers */
nic->reg_base = pcim_iomap(pdev, PCI_CFG_REG_BAR_NUM, 0);
@@ -2009,6 +2177,7 @@ static void nicvf_remove(struct pci_dev *pdev)
pci_set_drvdata(pdev, NULL);
if (nic->drv_stats)
free_percpu(nic->drv_stats);
+ cavium_ptp_put(nic->ptp_clock);
free_netdev(netdev);
pci_release_regions(pdev);
pci_disable_device(pdev);
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
index 095c18aeb8d5..9a999c62d6ba 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
@@ -978,6 +978,9 @@ void nicvf_qset_config(struct nicvf *nic, bool enable)
qs_cfg->be = 1;
#endif
qs_cfg->vnic = qs->vnic_id;
+ /* Enable Tx timestamping capability */
+ if (nic->ptp_clock)
+ qs_cfg->send_tstmp_ena = 1;
}
nicvf_send_msg_to_pf(nic, &mbx);
}
@@ -1383,6 +1386,29 @@ nicvf_sq_add_hdr_subdesc(struct nicvf *nic, struct snd_queue *sq, int qentry,
hdr->inner_l3_offset = skb_network_offset(skb) - 2;
this_cpu_inc(nic->pnicvf->drv_stats->tx_tso);
}
+
+ /* Check if timestamp is requested */
+ if (!(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
+ skb_tx_timestamp(skb);
+ return;
+ }
+
+ /* Tx timestamping not supported along with TSO, so ignore request */
+ if (skb_shinfo(skb)->gso_size)
+ return;
+
+ /* HW supports only a single outstanding packet to timestamp */
+ if (!atomic_add_unless(&nic->pnicvf->tx_ptp_skbs, 1, 1))
+ return;
+
+ /* Mark the SKB for later reference */
+ skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
+
+ /* Finally enable timestamp generation
+ * Since 'post_cqe' is also set, two CQEs will be posted
+ * for this packet i.e CQE_TYPE_SEND and CQE_TYPE_SEND_PTP.
+ */
+ hdr->tstmp = 1;
}
/* SQ GATHER subdescriptor
diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
index 5e5c4d7796b8..0f23999c5bcf 100644
--- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
+++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
@@ -245,6 +245,35 @@ void bgx_lmac_rx_tx_enable(int node, int bgx_idx, int lmacid, bool enable)
}
EXPORT_SYMBOL(bgx_lmac_rx_tx_enable);
+/* Enables or disables timestamp insertion by BGX for Rx packets */
+void bgx_config_timestamping(int node, int bgx_idx, int lmacid, bool enable)
+{
+ struct bgx *bgx = get_bgx(node, bgx_idx);
+ struct lmac *lmac;
+ u64 csr_offset, cfg;
+
+ if (!bgx)
+ return;
+
+ lmac = &bgx->lmac[lmacid];
+
+ if (lmac->lmac_type == BGX_MODE_SGMII ||
+ lmac->lmac_type == BGX_MODE_QSGMII ||
+ lmac->lmac_type == BGX_MODE_RGMII)
+ csr_offset = BGX_GMP_GMI_RXX_FRM_CTL;
+ else
+ csr_offset = BGX_SMUX_RX_FRM_CTL;
+
+ cfg = bgx_reg_read(bgx, lmacid, csr_offset);
+
+ if (enable)
+ cfg |= BGX_PKT_RX_PTP_EN;
+ else
+ cfg &= ~BGX_PKT_RX_PTP_EN;
+ bgx_reg_write(bgx, lmacid, csr_offset, cfg);
+}
+EXPORT_SYMBOL(bgx_config_timestamping);
+
void bgx_lmac_get_pfc(int node, int bgx_idx, int lmacid, void *pause)
{
struct pfc *pfc = (struct pfc *)pause;
diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.h b/drivers/net/ethernet/cavium/thunder/thunder_bgx.h
index 23acdc5ab896..5a7567d31138 100644
--- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.h
+++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.h
@@ -122,6 +122,8 @@
#define SPU_DBG_CTL_AN_NONCE_MCT_DIS BIT_ULL(29)
#define BGX_SMUX_RX_INT 0x20000
+#define BGX_SMUX_RX_FRM_CTL 0x20020
+#define BGX_PKT_RX_PTP_EN BIT_ULL(12)
#define BGX_SMUX_RX_JABBER 0x20030
#define BGX_SMUX_RX_CTL 0x20048
#define SMU_RX_CTL_STATUS (3ull << 0)
@@ -172,6 +174,7 @@
#define GMI_PORT_CFG_SPEED_MSB BIT_ULL(8)
#define GMI_PORT_CFG_RX_IDLE BIT_ULL(12)
#define GMI_PORT_CFG_TX_IDLE BIT_ULL(13)
+#define BGX_GMP_GMI_RXX_FRM_CTL 0x38028
#define BGX_GMP_GMI_RXX_JABBER 0x38038
#define BGX_GMP_GMI_TXX_THRESH 0x38210
#define BGX_GMP_GMI_TXX_APPEND 0x38218
@@ -223,6 +226,7 @@ void bgx_set_lmac_mac(int node, int bgx_idx, int lmacid, const u8 *mac);
void bgx_get_lmac_link_state(int node, int bgx_idx, int lmacid, void *status);
void bgx_lmac_internal_loopback(int node, int bgx_idx,
int lmac_idx, bool enable);
+void bgx_config_timestamping(int node, int bgx_idx, int lmacid, bool enable);
void bgx_lmac_get_pfc(int node, int bgx_idx, int lmacid, void *pause);
void bgx_lmac_set_pfc(int node, int bgx_idx, int lmacid, void *pause);
--
2.15.1
^ permalink raw reply related
* [PATCH net-next v4 0/2] net: thunderx: add support for PTP clock
From: Aleksey Makarov @ 2017-12-08 10:34 UTC (permalink / raw)
To: netdev
Cc: linux-arm-kernel, linux-kernel, Goutham, Sunil,
Radoslaw Biernacki, Aleksey Makarov, Robert Richter, David Daney,
Richard Cochran
This series adds support for IEEE 1588 Precision Time Protocol
to Cavium ethernet driver.
The first patch adds support for the Precision Time Protocol Clocks and
Timestamping coprocessor (PTP) found on Cavium processors.
It registers a new PTP clock in the PTP core and provides functions
to use the counter in BGX, TNS, GTI, and NIC blocks.
The second patch introduces support for the PTP protocol to the
Cavium ThunderX ethernet driver.
v4:
- use IS_ENABLED. This fixes compilation of the ptp as a module (David Miller)
- select PTP_1588_CLOCK, not depend on it. This fixes a build warning.
- change u64 to __be64. This fixes the sparse warning
"warning: cast to restricted __be64"
- make nicvf_config_hwtstamp() static. This fixes the sparse warning
"warning: symbol 'nicvf_config_hwtstamp' was not declared. Should it be static?"
v3: https://lkml.kernel.org/r/20171206133100.26436-1-aleksey.makarov@cavium.com
- rebase to net-next
v2: https://lkml.kernel.org/r/20171117134909.8954-1-aleksey.makarov@cavium.com
- use readq()/writeq() in place of cavium_ptp_reg_read()/cavium_ptp_reg_write(),
don't use readq_relaxed()/writeq_relaxed() (David Daney)
v1: https://lkml.kernel.org/r/20171107190704.15458-1-aleksey.makarov@cavium.com
Radoslaw Biernacki (1):
net: add support for Cavium PTP coprocessor
Sunil Goutham (1):
net: thunderx: add timestamping support
drivers/net/ethernet/cavium/Kconfig | 13 +
drivers/net/ethernet/cavium/Makefile | 1 +
drivers/net/ethernet/cavium/common/Makefile | 1 +
drivers/net/ethernet/cavium/common/cavium_ptp.c | 334 +++++++++++++++++++++
drivers/net/ethernet/cavium/common/cavium_ptp.h | 78 +++++
drivers/net/ethernet/cavium/thunder/nic.h | 15 +
drivers/net/ethernet/cavium/thunder/nic_main.c | 58 +++-
drivers/net/ethernet/cavium/thunder/nic_reg.h | 1 +
.../net/ethernet/cavium/thunder/nicvf_ethtool.c | 29 +-
drivers/net/ethernet/cavium/thunder/nicvf_main.c | 173 ++++++++++-
drivers/net/ethernet/cavium/thunder/nicvf_queues.c | 26 ++
drivers/net/ethernet/cavium/thunder/thunder_bgx.c | 29 ++
drivers/net/ethernet/cavium/thunder/thunder_bgx.h | 4 +
13 files changed, 756 insertions(+), 6 deletions(-)
create mode 100644 drivers/net/ethernet/cavium/common/Makefile
create mode 100644 drivers/net/ethernet/cavium/common/cavium_ptp.c
create mode 100644 drivers/net/ethernet/cavium/common/cavium_ptp.h
--
2.15.1
^ permalink raw reply
* [PATCH net-next v4 1/2] net: add support for Cavium PTP coprocessor
From: Aleksey Makarov @ 2017-12-08 10:34 UTC (permalink / raw)
To: netdev
Cc: linux-arm-kernel, linux-kernel, Goutham, Sunil,
Radoslaw Biernacki, Aleksey Makarov, Robert Richter, David Daney,
Richard Cochran
In-Reply-To: <20171208103442.19354-1-aleksey.makarov@cavium.com>
From: Radoslaw Biernacki <rad@semihalf.com>
This patch adds support for the Precision Time Protocol
Clocks and Timestamping hardware found on Cavium ThunderX
processors.
Signed-off-by: Radoslaw Biernacki <rad@semihalf.com>
Signed-off-by: Aleksey Makarov <aleksey.makarov@cavium.com>
---
drivers/net/ethernet/cavium/Kconfig | 12 +
drivers/net/ethernet/cavium/Makefile | 1 +
drivers/net/ethernet/cavium/common/Makefile | 1 +
drivers/net/ethernet/cavium/common/cavium_ptp.c | 334 ++++++++++++++++++++++++
drivers/net/ethernet/cavium/common/cavium_ptp.h | 78 ++++++
5 files changed, 426 insertions(+)
create mode 100644 drivers/net/ethernet/cavium/common/Makefile
create mode 100644 drivers/net/ethernet/cavium/common/cavium_ptp.c
create mode 100644 drivers/net/ethernet/cavium/common/cavium_ptp.h
diff --git a/drivers/net/ethernet/cavium/Kconfig b/drivers/net/ethernet/cavium/Kconfig
index 63be75eb34d2..2380e9834007 100644
--- a/drivers/net/ethernet/cavium/Kconfig
+++ b/drivers/net/ethernet/cavium/Kconfig
@@ -50,6 +50,18 @@ config THUNDER_NIC_RGX
This driver supports configuring XCV block of RGX interface
present on CN81XX chip.
+config CAVIUM_PTP
+ tristate "Cavium PTP coprocessor as PTP clock"
+ depends on 64BIT
+ select PTP_1588_CLOCK
+ default y
+ ---help---
+ This driver adds support for the Precision Time Protocol Clocks and
+ Timestamping coprocessor (PTP) found on Cavium processors.
+ PTP provides timestamping mechanism that is suitable for use in IEEE 1588
+ Precision Time Protocol or other purposes. Timestamps can be used in
+ BGX, TNS, GTI, and NIC blocks.
+
config LIQUIDIO
tristate "Cavium LiquidIO support"
depends on 64BIT
diff --git a/drivers/net/ethernet/cavium/Makefile b/drivers/net/ethernet/cavium/Makefile
index 872da9f7c31a..946bba84e81d 100644
--- a/drivers/net/ethernet/cavium/Makefile
+++ b/drivers/net/ethernet/cavium/Makefile
@@ -1,6 +1,7 @@
#
# Makefile for the Cavium ethernet device drivers.
#
+obj-$(CONFIG_NET_VENDOR_CAVIUM) += common/
obj-$(CONFIG_NET_VENDOR_CAVIUM) += thunder/
obj-$(CONFIG_NET_VENDOR_CAVIUM) += liquidio/
obj-$(CONFIG_NET_VENDOR_CAVIUM) += octeon/
diff --git a/drivers/net/ethernet/cavium/common/Makefile b/drivers/net/ethernet/cavium/common/Makefile
new file mode 100644
index 000000000000..dd8561b8060b
--- /dev/null
+++ b/drivers/net/ethernet/cavium/common/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_CAVIUM_PTP) += cavium_ptp.o
diff --git a/drivers/net/ethernet/cavium/common/cavium_ptp.c b/drivers/net/ethernet/cavium/common/cavium_ptp.c
new file mode 100644
index 000000000000..f4c738db27fd
--- /dev/null
+++ b/drivers/net/ethernet/cavium/common/cavium_ptp.c
@@ -0,0 +1,334 @@
+/*
+ * cavium_ptp.c - PTP 1588 clock on Cavium hardware
+ *
+ * Copyright (c) 2003-2015, 2017 Cavium, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium, Inc. for more information
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/timecounter.h>
+#include <linux/pci.h>
+
+#include "cavium_ptp.h"
+
+#define DRV_NAME "Cavium PTP Driver"
+
+#define PCI_DEVICE_ID_CAVIUM_PTP 0xA00C
+#define PCI_DEVICE_ID_CAVIUM_RST 0xA00E
+
+#define PCI_PTP_BAR_NO 0
+#define PCI_RST_BAR_NO 0
+
+#define PTP_CLOCK_CFG 0xF00ULL
+#define PTP_CLOCK_CFG_PTP_EN BIT(0)
+#define PTP_CLOCK_LO 0xF08ULL
+#define PTP_CLOCK_HI 0xF10ULL
+#define PTP_CLOCK_COMP 0xF18ULL
+
+#define RST_BOOT 0x1600ULL
+#define CLOCK_BASE_RATE 50000000ULL
+
+static u64 ptp_cavium_clock_get(void)
+{
+ struct pci_dev *pdev;
+ void __iomem *base;
+ u64 ret = CLOCK_BASE_RATE * 16;
+
+ pdev = pci_get_device(PCI_VENDOR_ID_CAVIUM,
+ PCI_DEVICE_ID_CAVIUM_RST, NULL);
+ if (!pdev)
+ goto error;
+
+ base = pci_ioremap_bar(pdev, PCI_RST_BAR_NO);
+ if (!base)
+ goto error_put_pdev;
+
+ ret = CLOCK_BASE_RATE * ((readq(base + RST_BOOT) >> 33) & 0x3f);
+
+ iounmap(base);
+
+error_put_pdev:
+ pci_dev_put(pdev);
+
+error:
+ return ret;
+}
+
+struct cavium_ptp *cavium_ptp_get(void)
+{
+ struct cavium_ptp *ptp;
+ struct pci_dev *pdev;
+
+ pdev = pci_get_device(PCI_VENDOR_ID_CAVIUM,
+ PCI_DEVICE_ID_CAVIUM_PTP, NULL);
+ if (!pdev)
+ return ERR_PTR(-ENODEV);
+
+ ptp = pci_get_drvdata(pdev);
+ if (!ptp) {
+ pci_dev_put(pdev);
+ ptp = ERR_PTR(-EPROBE_DEFER);
+ }
+
+ return ptp;
+}
+EXPORT_SYMBOL(cavium_ptp_get);
+
+void cavium_ptp_put(struct cavium_ptp *ptp)
+{
+ pci_dev_put(ptp->pdev);
+}
+EXPORT_SYMBOL(cavium_ptp_put);
+
+/**
+ * cavium_ptp_adjfreq() - Adjust ptp frequency
+ * @ptp: PTP clock info
+ * @ppb: how much to adjust by, in parts-per-billion
+ */
+static int cavium_ptp_adjfreq(struct ptp_clock_info *ptp_info, s32 ppb)
+{
+ struct cavium_ptp *clock =
+ container_of(ptp_info, struct cavium_ptp, ptp_info);
+ unsigned long flags;
+ u64 comp;
+ u64 adj;
+ bool neg_adj = false;
+
+ if (ppb < 0) {
+ neg_adj = true;
+ ppb = -ppb;
+ }
+
+ /* The hardware adds the clock compensation value to the PTP clock
+ * on every coprocessor clock cycle. Typical convention is that it
+ * represent number of nanosecond betwen each cycle. In this
+ * convention compensation value is in 64 bit fixed-point
+ * representation where upper 32 bits are number of nanoseconds
+ * and lower is fractions of nanosecond.
+ * The ppb represent the ratio in "parts per bilion" by which the
+ * compensation value should be corrected.
+ * To calculate new compenstation value we use 64bit fixed point
+ * arithmetic on following formula comp = tbase + tbase * ppb / 1G
+ * where tbase is the basic compensation value calculated initialy
+ * in cavium_ptp_init() -> tbase = 1/Hz. Then we use endian
+ * independent structure definition to write data to PTP register.
+ */
+ comp = ((u64)1000000000ull << 32) / clock->clock_rate;
+ adj = comp * ppb;
+ adj = div_u64(adj, 1000000000ull);
+ comp = neg_adj ? comp - adj : comp + adj;
+
+ spin_lock_irqsave(&clock->spin_lock, flags);
+ writeq(comp, clock->reg_base + PTP_CLOCK_COMP);
+ spin_unlock_irqrestore(&clock->spin_lock, flags);
+
+ return 0;
+}
+
+/**
+ * cavium_ptp_adjtime() - Adjust ptp time
+ * @ptp: PTP clock info
+ * @delta: how much to adjust by, in nanosecs
+ */
+static int cavium_ptp_adjtime(struct ptp_clock_info *ptp_info, s64 delta)
+{
+ struct cavium_ptp *clock =
+ container_of(ptp_info, struct cavium_ptp, ptp_info);
+ unsigned long flags;
+
+ spin_lock_irqsave(&clock->spin_lock, flags);
+ timecounter_adjtime(&clock->time_counter, delta);
+ spin_unlock_irqrestore(&clock->spin_lock, flags);
+
+ /* Sync, for network driver to get latest value */
+ smp_mb();
+
+ return 0;
+}
+
+/**
+ * cavium_ptp_gettime() - Get hardware clock time with adjustment
+ * @ptp: PTP clock info
+ * @ts: timespec
+ */
+static int cavium_ptp_gettime(struct ptp_clock_info *ptp_info,
+ struct timespec64 *ts)
+{
+ struct cavium_ptp *clock =
+ container_of(ptp_info, struct cavium_ptp, ptp_info);
+ unsigned long flags;
+ u64 nsec;
+
+ spin_lock_irqsave(&clock->spin_lock, flags);
+ nsec = timecounter_read(&clock->time_counter);
+ spin_unlock_irqrestore(&clock->spin_lock, flags);
+
+ *ts = ns_to_timespec64(nsec);
+
+ return 0;
+}
+
+/**
+ * cavium_ptp_settime() - Set hardware clock time. Reset adjustment
+ * @ptp: PTP clock info
+ * @ts: timespec
+ */
+static int cavium_ptp_settime(struct ptp_clock_info *ptp_info,
+ const struct timespec64 *ts)
+{
+ struct cavium_ptp *clock =
+ container_of(ptp_info, struct cavium_ptp, ptp_info);
+ unsigned long flags;
+ u64 nsec;
+
+ nsec = timespec64_to_ns(ts);
+
+ spin_lock_irqsave(&clock->spin_lock, flags);
+ timecounter_init(&clock->time_counter, &clock->cycle_counter, nsec);
+ spin_unlock_irqrestore(&clock->spin_lock, flags);
+
+ return 0;
+}
+
+/**
+ * cavium_ptp_enable() - Check if PTP is enabled
+ * @ptp: PTP clock info
+ * @rq: request
+ * @on: is it on
+ */
+static int cavium_ptp_enable(struct ptp_clock_info *ptp_info,
+ struct ptp_clock_request *rq, int on)
+{
+ return -EOPNOTSUPP;
+}
+
+static u64 cavium_ptp_cc_read(const struct cyclecounter *cc)
+{
+ struct cavium_ptp *clock =
+ container_of(cc, struct cavium_ptp, cycle_counter);
+
+ return readq(clock->reg_base + PTP_CLOCK_HI);
+}
+
+static int cavium_ptp_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ struct device *dev = &pdev->dev;
+ struct cavium_ptp *clock;
+ struct cyclecounter *cc;
+ u64 clock_cfg;
+ u64 clock_comp;
+ int err;
+
+ clock = devm_kzalloc(dev, sizeof(*clock), GFP_KERNEL);
+ if (!clock)
+ return -ENOMEM;
+
+ clock->pdev = pdev;
+
+ err = pcim_enable_device(pdev);
+ if (err)
+ return err;
+
+ err = pcim_iomap_regions(pdev, 1 << PCI_PTP_BAR_NO, pci_name(pdev));
+ if (err)
+ return err;
+
+ clock->reg_base = pcim_iomap_table(pdev)[PCI_PTP_BAR_NO];
+
+ spin_lock_init(&clock->spin_lock);
+
+ cc = &clock->cycle_counter;
+ cc->read = cavium_ptp_cc_read;
+ cc->mask = CYCLECOUNTER_MASK(64);
+ cc->mult = 1;
+ cc->shift = 0;
+
+ timecounter_init(&clock->time_counter, &clock->cycle_counter,
+ ktime_to_ns(ktime_get_real()));
+
+ clock->clock_rate = ptp_cavium_clock_get();
+
+ clock->ptp_info = (struct ptp_clock_info) {
+ .owner = THIS_MODULE,
+ .name = "ThunderX PTP",
+ .max_adj = 1000000000ull,
+ .n_ext_ts = 0,
+ .n_pins = 0,
+ .pps = 0,
+ .adjfreq = cavium_ptp_adjfreq,
+ .adjtime = cavium_ptp_adjtime,
+ .gettime64 = cavium_ptp_gettime,
+ .settime64 = cavium_ptp_settime,
+ .enable = cavium_ptp_enable,
+ };
+
+ clock_cfg = readq(clock->reg_base + PTP_CLOCK_CFG);
+ clock_cfg |= PTP_CLOCK_CFG_PTP_EN;
+ writeq(clock_cfg, clock->reg_base + PTP_CLOCK_CFG);
+
+ clock_comp = ((u64)1000000000ull << 32) / clock->clock_rate;
+ writeq(clock_comp, clock->reg_base + PTP_CLOCK_COMP);
+
+ clock->ptp_clock = ptp_clock_register(&clock->ptp_info, dev);
+ if (IS_ERR(clock->ptp_clock)) {
+ clock_cfg = readq(clock->reg_base + PTP_CLOCK_CFG);
+ clock_cfg &= ~PTP_CLOCK_CFG_PTP_EN;
+ writeq(clock_cfg, clock->reg_base + PTP_CLOCK_CFG);
+ return PTR_ERR(clock->ptp_clock);
+ }
+
+ pci_set_drvdata(pdev, clock);
+ return 0;
+}
+
+static void cavium_ptp_remove(struct pci_dev *pdev)
+{
+ struct cavium_ptp *clock = pci_get_drvdata(pdev);
+ u64 clock_cfg;
+
+ pci_set_drvdata(pdev, NULL);
+
+ ptp_clock_unregister(clock->ptp_clock);
+
+ clock_cfg = readq(clock->reg_base + PTP_CLOCK_CFG);
+ clock_cfg &= ~PTP_CLOCK_CFG_PTP_EN;
+ writeq(clock_cfg, clock->reg_base + PTP_CLOCK_CFG);
+}
+
+static const struct pci_device_id cavium_ptp_id_table[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVICE_ID_CAVIUM_PTP) },
+ { 0, }
+};
+
+static struct pci_driver cavium_ptp_driver = {
+ .name = DRV_NAME,
+ .id_table = cavium_ptp_id_table,
+ .probe = cavium_ptp_probe,
+ .remove = cavium_ptp_remove,
+};
+
+static int __init cavium_ptp_init_module(void)
+{
+ return pci_register_driver(&cavium_ptp_driver);
+}
+
+static void __exit cavium_ptp_cleanup_module(void)
+{
+ pci_unregister_driver(&cavium_ptp_driver);
+}
+
+module_init(cavium_ptp_init_module);
+module_exit(cavium_ptp_cleanup_module);
+
+MODULE_DESCRIPTION(DRV_NAME);
+MODULE_AUTHOR("Cavium Networks <support@cavium.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_DEVICE_TABLE(pci, cavium_ptp_id_table);
diff --git a/drivers/net/ethernet/cavium/common/cavium_ptp.h b/drivers/net/ethernet/cavium/common/cavium_ptp.h
new file mode 100644
index 000000000000..0f6fe2b6e2ca
--- /dev/null
+++ b/drivers/net/ethernet/cavium/common/cavium_ptp.h
@@ -0,0 +1,78 @@
+/*
+ * cavium_ptp.h - PTP 1588 clock on Cavium hardware
+ *
+ * Copyright (c) 2003-2015, 2017 Cavium, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium, Inc. for more information
+ */
+
+#ifndef CAVIUM_PTP_H
+#define CAVIUM_PTP_H
+
+#include <linux/ptp_clock_kernel.h>
+#include <linux/timecounter.h>
+
+struct cavium_ptp {
+ struct pci_dev *pdev;
+
+ /* Serialize access to cycle_counter, time_counter and hw_registers */
+ spinlock_t spin_lock;
+ struct cyclecounter cycle_counter;
+ struct timecounter time_counter;
+ void __iomem *reg_base;
+
+ u32 clock_rate;
+
+ struct ptp_clock_info ptp_info;
+ struct ptp_clock *ptp_clock;
+};
+
+#if IS_ENABLED(CONFIG_CAVIUM_PTP)
+
+struct cavium_ptp *cavium_ptp_get(void);
+void cavium_ptp_put(struct cavium_ptp *ptp);
+
+static inline u64 cavium_ptp_tstamp2time(struct cavium_ptp *ptp, u64 tstamp)
+{
+ unsigned long flags;
+ u64 ret;
+
+ spin_lock_irqsave(&ptp->spin_lock, flags);
+ ret = timecounter_cyc2time(&ptp->time_counter, tstamp);
+ spin_unlock_irqrestore(&ptp->spin_lock, flags);
+
+ return ret;
+}
+
+static inline int cavium_ptp_clock_index(struct cavium_ptp *clock)
+{
+ return ptp_clock_index(clock->ptp_clock);
+}
+
+#else
+
+static inline struct cavium_ptp *cavium_ptp_get(void)
+{
+ return ERR_PTR(-ENODEV);
+}
+
+static inline void cavium_ptp_put(struct cavium_ptp *ptp) {}
+
+static inline u64 cavium_ptp_tstamp2time(struct cavium_ptp *ptp, u64 tstamp)
+{
+ return 0;
+}
+
+static inline int cavium_ptp_clock_index(struct cavium_ptp *clock)
+{
+ return -1;
+}
+
+#endif
+
+#endif
--
2.15.1
^ permalink raw reply related
* Re: Linux 4.14 - regression: broken tun/tap / bridge network with virtio - bisected
From: Andreas Hartmann @ 2017-12-08 10:31 UTC (permalink / raw)
To: Michal Kubecek; +Cc: Jason Wang, David Miller, netdev
In-Reply-To: <20171208084751.tom4auppogz4lanz@unicorn.suse.cz>
On 12/08/2017 at 09:47 AM Michal Kubecek wrote:
> On Fri, Dec 08, 2017 at 08:21:16AM +0100, Andreas Hartmann wrote:
>>
>> Thanks for this hint - I'm not using xdp. Therefore I rechecked my
>> bisect and detected a mistake. The rebisect now leads to
>>
>>
>>
>> [v2,RFC,11/13] net: Remove all references to SKB_GSO_UDP. [1]
>>
>>
>>
>> For the repeated bisect, I switched back to the original qemu 2.6.2
>> (instead of 2.10.1), because problems can be seen reliably with 2.6.2.
>>
>> All my VMs are using virtio_net. BTW: I couldn't see the problems
>> (sometimes, the VM couldn't be stopped at all) if all my VMs are using
>> e1000 as interface instead.
>>
>> This finding now matches pretty much the responsible UDP-package which
>> caused the stall. I already mentioned it here [2].
>>
>> To prove it, I reverted from the patch series "[PATCH v2 RFC 0/13]
>> Remove UDP Fragmentation Offload support" [3]
>>
>> 11/13 [v2,RFC,11/13] net: Remove all references to SKB_GSO_UDP. [4]
>> 12/13 [v2,RFC,12/13] inet: Remove software UFO fragmenting code. [5]
>> 13/13 [v2,RFC,13/13] net: Kill NETIF_F_UFO and SKB_GSO_UDP. [6]
>>
>> and applied it to Linux 4.14.4. It compiled fine and is running fine.
>> The vnet doesn't die anymore. Yet, I can't say if the qemu stop hangs
>> are gone, too.
>>
>> Obviously, there is something broken with the new UDP handling. Could
>> you please analyze this problem? I could test some more patches ... .
>
> Any chance your VMs were live migrated from pre-4.14 host kernel?
No - the VMs are not live migrated. They are always running on the same
host - either with kernel < 4.14 or with kernel 4.14.x.
> If
> this is the case, you should try commit 0c19f846d582 ("net: accept UFO
> datagrams from tuntap and packet").
It doesn't apply to 4.14.4
> Or disabling UFO in the guest should
> work around the issue.
ethtool -K ethX ufo off for each device / bridge in VM.
Yes, this seems to work. I'll wait and see if the non stoppable
qemu-problem on shutdown will remain.
When will there be a fix for 4.14? It is clearly a regression. Is it
possible / a good idea to just remove the complete patch series "Remove
UDP Fragmentation Offload support"?
Thanks,
Andreas
^ permalink raw reply
* Re: [PATCH v2 net-next 4/4] bpftool: implement cgroup bpf operations
From: Quentin Monnet @ 2017-12-08 10:34 UTC (permalink / raw)
To: Roman Gushchin, netdev
Cc: linux-kernel, kernel-team, ast, daniel, jakub.kicinski, kafai,
David Ahern
In-Reply-To: <20171207183909.16240-5-guro@fb.com>
2017-12-07 18:39 UTC+0000 ~ Roman Gushchin <guro@fb.com>
> This patch adds basic cgroup bpf operations to bpftool:
> cgroup list, attach and detach commands.
>
> Usage is described in the corresponding man pages,
> and examples are provided.
>
> Syntax:
> $ bpftool cgroup list CGROUP
> $ bpftool cgroup attach CGROUP ATTACH_TYPE PROG [ATTACH_FLAGS]
> $ bpftool cgroup detach CGROUP ATTACH_TYPE PROG
>
> Signed-off-by: Roman Gushchin <guro@fb.com>
> Cc: Alexei Starovoitov <ast@kernel.org>
> Cc: Daniel Borkmann <daniel@iogearbox.net>
> Cc: Jakub Kicinski <jakub.kicinski@netronome.com>
> Cc: Martin KaFai Lau <kafai@fb.com>
> Cc: Quentin Monnet <quentin.monnet@netronome.com>
> Cc: David Ahern <dsahern@gmail.com>
> ---
> tools/bpf/bpftool/Documentation/bpftool-cgroup.rst | 92 +++++++
> tools/bpf/bpftool/Documentation/bpftool-map.rst | 2 +-
> tools/bpf/bpftool/Documentation/bpftool-prog.rst | 2 +-
> tools/bpf/bpftool/Documentation/bpftool.rst | 6 +-
> tools/bpf/bpftool/cgroup.c | 305 +++++++++++++++++++++
> tools/bpf/bpftool/main.c | 3 +-
> tools/bpf/bpftool/main.h | 1 +
> 7 files changed, 406 insertions(+), 5 deletions(-)
> create mode 100644 tools/bpf/bpftool/Documentation/bpftool-cgroup.rst
> create mode 100644 tools/bpf/bpftool/cgroup.c
>
> diff --git a/tools/bpf/bpftool/Documentation/bpftool-cgroup.rst b/tools/bpf/bpftool/Documentation/bpftool-cgroup.rst
> new file mode 100644
> index 000000000000..61ded613aee1
> --- /dev/null
> +++ b/tools/bpf/bpftool/Documentation/bpftool-cgroup.rst
> @@ -0,0 +1,92 @@
> +================
> +bpftool-cgroup
> +================
> +-------------------------------------------------------------------------------
> +tool for inspection and simple manipulation of eBPF progs
> +-------------------------------------------------------------------------------
> +
> +:Manual section: 8
> +
> +SYNOPSIS
> +========
> +
> + **bpftool** [*OPTIONS*] **cgroup** *COMMAND*
> +
> + *OPTIONS* := { { **-j** | **--json** } [{ **-p** | **--pretty** }] | { **-f** | **--bpffs** } }
> +
> + *COMMANDS* :=
> + { **list** | **attach** | **detach** | **help** }
> +
> +MAP COMMANDS
> +=============
> +
> +| **bpftool** **cgroup list** *CGROUP*
> +| **bpftool** **cgroup attach** *CGROUP* *ATTACH_TYPE* *PROG* [*ATTACH_FLAGS*]
> +| **bpftool** **cgroup detach** *CGROUP* *ATTACH_TYPE* *PROG*
> +| **bpftool** **cgroup help**
> +|
> +| *PROG* := { **id** *PROG_ID* | **pinned** *FILE* | **tag** *PROG_TAG* }
Could you please give the different possible values for ATTACH_TYPE and
ATTACH_FLAGS, and provide some documentation for the flags?
> +
> +DESCRIPTION
> +===========
> + **bpftool cgroup list** *CGROUP*
> + List all programs attached to the cgroup *CGROUP*.
> +
> + Output will start with program ID followed by attach type,
> + attach flags and program name.
> +
> + **bpftool cgroup attach** *CGROUP* *ATTACH_TYPE* *PROG* [*ATTACH_FLAGS*]
> + Attach program *PROG* to the cgroup *CGROUP* with attach type
> + *ATTACH_TYPE* and optional *ATTACH_FLAGS*.
> +
> + **bpftool cgroup detach** *CGROUP* *ATTACH_TYPE* *PROG*
> + Detach *PROG* from the cgroup *CGROUP* and attach type
> + *ATTACH_TYPE*.
> +
> + **bpftool prog help**
> + Print short help message.
[…]
> diff --git a/tools/bpf/bpftool/cgroup.c b/tools/bpf/bpftool/cgroup.c
> new file mode 100644
> index 000000000000..88d67f74313f
> --- /dev/null
> +++ b/tools/bpf/bpftool/cgroup.c
> @@ -0,0 +1,305 @@
> +/*
> + * Copyright (C) 2017 Facebook
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version
> + * 2 of the License, or (at your option) any later version.
> + *
> + * Author: Roman Gushchin <guro@fb.com>
> + */
> +
[…]
> +static int do_detach(int argc, char **argv)
> +{
> + int prog_fd, cgroup_fd;
> + enum bpf_attach_type attach_type;
> + int ret = -1;
> +
> + if (argc < 4) {
> + p_err("too few parameters for cgroup detach\n");
> + goto exit;
> + }
> +
> + cgroup_fd = open(argv[0], O_RDONLY);
> + if (cgroup_fd < 0) {
> + p_err("can't open cgroup %s\n", argv[1]);
> + goto exit;
> + }
> +
> + attach_type = parse_attach_type(argv[1]);
> + if (attach_type == __MAX_BPF_ATTACH_TYPE) {
> + p_err("invalid attach type");
> + goto exit_cgroup;
> + }
> +
> + argc -= 2;
> + argv = &argv[2];
> + prog_fd = prog_parse_fd(&argc, &argv);
> + if (prog_fd < 0)
> + goto exit_cgroup;
> +
> + if (bpf_prog_detach2(prog_fd, cgroup_fd, attach_type)) {
> + p_err("failed to attach program");
Failed to *detach* instead of “attach”.
> + goto exit_prog;
> + }
> +
> + if (json_output)
> + jsonw_null(json_wtr);
> +
> + ret = 0;
> +
> +exit_prog:
> + close(prog_fd);
> +exit_cgroup:
> + close(cgroup_fd);
> +exit:
> + return ret;
> +}
[…]
Very nice work on this v2, thanks a lot!
Quentin
^ permalink raw reply
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