Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH net-next 1/3] ipv4: Multipath hashing on inner L3 needs to consider inner IPv6 pkts
From: David Miller @ 2019-07-05 22:19 UTC (permalink / raw)
  To: ssuryaextr; +Cc: netdev, idosch, nikolay, dsahern
In-Reply-To: <20190703151934.9567-2-ssuryaextr@gmail.com>

From: Stephen Suryaputra <ssuryaextr@gmail.com>
Date: Wed,  3 Jul 2019 11:19:32 -0400

> Commit 363887a2cdfe ("ipv4: Support multipath hashing on inner IP pkts
> for GRE tunnel") supports multipath policy value of 2, Layer 3 or inner
> Layer 3 if present, but it only considers inner IPv4. There is a use
> case of IPv6 over GRE over IPv4, thus add the ability to hash on inner
> IPv6 addresses.
> 
> Fixes: 363887a2cdfe ("ipv4: Support multipath hashing on inner IP pkts for GRE tunnel")
> Signed-off-by: Stephen Suryaputra <ssuryaextr@gmail.com>

The wording in this commit message is very confusing.

If you say "IPv6 over GRE over IPv4" then IPv6 is the outer protocol
type, not the inner one.

You need to clarify or reword this commit message so that it is
understandable and matches the logic.

Thanks.

^ permalink raw reply

* Re: [PATCH net-next v2 8/8] net: mscc: PTP Hardware Clock (PHC) support
From: Jakub Kicinski @ 2019-07-05 22:10 UTC (permalink / raw)
  To: Antoine Tenart
  Cc: davem, richardcochran, alexandre.belloni, UNGLinuxDriver, ralf,
	paul.burton, jhogan, netdev, linux-mips, thomas.petazzoni,
	allan.nielsen
In-Reply-To: <20190705195213.22041-9-antoine.tenart@bootlin.com>

On Fri,  5 Jul 2019 21:52:13 +0200, Antoine Tenart wrote:
> This patch adds support for PTP Hardware Clock (PHC) to the Ocelot
> switch for both PTP 1-step and 2-step modes.
> 
> Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>

> @@ -596,11 +606,50 @@ static int ocelot_port_xmit(struct sk_buff *skb, struct net_device *dev)
>  
>  	dev->stats.tx_packets++;
>  	dev->stats.tx_bytes += skb->len;
> -	dev_kfree_skb_any(skb);
> +
> +	if (ocelot->ptp && shinfo->tx_flags & SKBTX_HW_TSTAMP &&
> +	    port->ptp_cmd == IFH_REW_OP_TWO_STEP_PTP) {
> +		struct ocelot_skb *oskb =
> +			kzalloc(sizeof(struct ocelot_skb), GFP_KERNEL);

I think this is the TX path, you can't use GFP_KERNEL here.

> +
> +		oskb->skb = skb;
> +		oskb->id = port->ts_id % 4;
> +		port->ts_id++;
> +
> +		list_add_tail(&oskb->head, &port->skbs);
> +	} else {
> +		dev_kfree_skb_any(skb);
> +	}
>  
>  	return NETDEV_TX_OK;
>  }

> +static int ocelot_hwstamp_set(struct ocelot_port *port, struct ifreq *ifr)
> +{
> +	struct ocelot *ocelot = port->ocelot;
> +	struct hwtstamp_config cfg;
> +
> +	if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg)))
> +		return -EFAULT;
> +
> +	/* reserved for future extensions */
> +	if (cfg.flags)
> +		return -EINVAL;
> +
> +	/* Tx type sanity check */
> +	switch (cfg.tx_type) {
> +	case HWTSTAMP_TX_ON:
> +		port->ptp_cmd = IFH_REW_OP_TWO_STEP_PTP;
> +		break;
> +	case HWTSTAMP_TX_ONESTEP_SYNC:
> +		/* IFH_REW_OP_ONE_STEP_PTP updates the correctional field, we
> +		 * need to update the origin time.
> +		 */
> +		port->ptp_cmd = IFH_REW_OP_ORIGIN_PTP;
> +		break;
> +	case HWTSTAMP_TX_OFF:
> +		port->ptp_cmd = 0;
> +		break;
> +	default:
> +		return -ERANGE;
> +	}
> +
> +	mutex_lock(&ocelot->ptp_lock);
> +
> +	switch (cfg.rx_filter) {
> +	case HWTSTAMP_FILTER_NONE:
> +		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_NTP_ALL:
> +	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:
> +		cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
> +		break;
> +	default:
> +		mutex_unlock(&ocelot->ptp_lock);
> +		return -ERANGE;
> +	}

No device reconfig, so the PTP RX stamping is always enabled?  Perhaps
consider setting 

	ocelot->hwtstamp_config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT

at probe?

> +	/* Commit back the result & save it */
> +	memcpy(&ocelot->hwtstamp_config, &cfg, sizeof(cfg));
> +	mutex_unlock(&ocelot->ptp_lock);
> +
> +	return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
> +}
> +
> +static int ocelot_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
> +{
> +	struct ocelot_port *port = netdev_priv(dev);
> +	struct ocelot *ocelot = port->ocelot;
> +
> +	/* The function is only used for PTP operations for now */
> +	if (!ocelot->ptp)
> +		return -EOPNOTSUPP;
> +
> +	switch (cmd) {
> +	case SIOCSHWTSTAMP:
> +		return ocelot_hwstamp_set(port, ifr);
> +	case SIOCGHWTSTAMP:
> +		return ocelot_hwstamp_get(port, ifr);
> +	default:
> +		return -EOPNOTSUPP;
> +	}
> +}
> +
>  static const struct net_device_ops ocelot_port_netdev_ops = {
>  	.ndo_open			= ocelot_port_open,
>  	.ndo_stop			= ocelot_port_stop,
> @@ -933,6 +1073,7 @@ static const struct net_device_ops ocelot_port_netdev_ops = {
>  	.ndo_set_features		= ocelot_set_features,
>  	.ndo_get_port_parent_id		= ocelot_get_port_parent_id,
>  	.ndo_setup_tc			= ocelot_setup_tc,
> +	.ndo_do_ioctl			= ocelot_ioctl,
>  };
>  
>  static void ocelot_get_strings(struct net_device *netdev, u32 sset, u8 *data)
> @@ -1014,12 +1155,42 @@ static int ocelot_get_sset_count(struct net_device *dev, int sset)
>  	return ocelot->num_stats;
>  }
>  
> +static int ocelot_get_ts_info(struct net_device *dev,
> +			      struct ethtool_ts_info *info)
> +{
> +	struct ocelot_port *ocelot_port = netdev_priv(dev);
> +	struct ocelot *ocelot = ocelot_port->ocelot;
> +	int ret;
> +
> +	if (!ocelot->ptp)
> +		return -EOPNOTSUPP;

Hmm.. why does software timestamping depend on PTP?

> +	ret = ethtool_op_get_ts_info(dev, info);
> +	if (ret)
> +		return ret;
> +
> +	info->phc_index = ocelot->ptp_clock ?
> +			  ptp_clock_index(ocelot->ptp_clock) : -1;
> +	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->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON) |
> +			 BIT(HWTSTAMP_TX_ONESTEP_SYNC);
> +	info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) | BIT(HWTSTAMP_FILTER_ALL);
> +
> +	return 0;
> +}
> +
>  static const struct ethtool_ops ocelot_ethtool_ops = {
>  	.get_strings		= ocelot_get_strings,
>  	.get_ethtool_stats	= ocelot_get_ethtool_stats,
>  	.get_sset_count		= ocelot_get_sset_count,
>  	.get_link_ksettings	= phy_ethtool_get_link_ksettings,
>  	.set_link_ksettings	= phy_ethtool_set_link_ksettings,
> +	.get_ts_info		= ocelot_get_ts_info,
>  };
>  
>  static int ocelot_port_attr_stp_state_set(struct ocelot_port *ocelot_port,

^ permalink raw reply

* Re: [PATCH bpf-next 3/3] xdp: Add devmap_hash map type for looking up devices by hashed index
From: Y Song @ 2019-07-05 22:04 UTC (permalink / raw)
  To: Toke Høiland-Jørgensen
  Cc: Daniel Borkmann, Alexei Starovoitov, netdev, David Miller,
	Jesper Dangaard Brouer, Jakub Kicinski, Björn Töpel
In-Reply-To: <156234940855.2378.3580468359411972045.stgit@alrua-x1>

On Fri, Jul 5, 2019 at 11:14 AM Toke Høiland-Jørgensen <toke@redhat.com> wrote:
>
> From: Toke Høiland-Jørgensen <toke@redhat.com>
>
> A common pattern when using xdp_redirect_map() is to create a device map
> where the lookup key is simply ifindex. Because device maps are arrays,
> this leaves holes in the map, and the map has to be sized to fit the
> largest ifindex, regardless of how many devices actually are actually
> needed in the map.
>
> This patch adds a second type of device map where the key is looked up
> using a hashmap, instead of being used as an array index. This allows maps
> to be densely packed, so they can be smaller.
>
> Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
> ---
>  include/linux/bpf.h                     |    7 +
>  include/linux/bpf_types.h               |    1
>  include/trace/events/xdp.h              |    3
>  include/uapi/linux/bpf.h                |    7 +
>  kernel/bpf/devmap.c                     |  192 +++++++++++++++++++++++++++++++
>  kernel/bpf/verifier.c                   |    2
>  net/core/filter.c                       |    9 +
>  tools/bpf/bpftool/map.c                 |    1
>  tools/include/uapi/linux/bpf.h          |    7 +
>  tools/lib/bpf/libbpf_probes.c           |    1
>  tools/testing/selftests/bpf/test_maps.c |   16 +++
>  11 files changed, 237 insertions(+), 9 deletions(-)

Could you break this patch into multiple commits for easy backporting
and easy syncing to libbpf repo?
For example, you can break it into 4 patches:
   . kernel patch
   . sync uapi bpf.h
   . tools/lib/bpf/libbpf_probes.c
   . other tools changes.

>
> diff --git a/include/linux/bpf.h b/include/linux/bpf.h
> index bfdb54dd2ad1..f9a506147c8a 100644
> --- a/include/linux/bpf.h
> +++ b/include/linux/bpf.h
> @@ -713,6 +713,7 @@ struct xdp_buff;
>  struct sk_buff;
>
>  struct bpf_dtab_netdev *__dev_map_lookup_elem(struct bpf_map *map, u32 key);
> +struct bpf_dtab_netdev *__dev_map_hash_lookup_elem(struct bpf_map *map, u32 key);
>  void __dev_map_flush(struct bpf_map *map);
>  int dev_map_enqueue(struct bpf_dtab_netdev *dst, struct xdp_buff *xdp,
>                     struct net_device *dev_rx);
> @@ -799,6 +800,12 @@ static inline struct net_device  *__dev_map_lookup_elem(struct bpf_map *map,
>         return NULL;
>  }
>
> +static inline struct net_device  *__dev_map_hash_lookup_elem(struct bpf_map *map,
> +                                                            u32 key)
> +{
> +       return NULL;
> +}
> +
>  static inline void __dev_map_flush(struct bpf_map *map)
>  {
>  }
> diff --git a/include/linux/bpf_types.h b/include/linux/bpf_types.h
> index eec5aeeeaf92..36a9c2325176 100644
> --- a/include/linux/bpf_types.h
> +++ b/include/linux/bpf_types.h
> @@ -62,6 +62,7 @@ BPF_MAP_TYPE(BPF_MAP_TYPE_ARRAY_OF_MAPS, array_of_maps_map_ops)
>  BPF_MAP_TYPE(BPF_MAP_TYPE_HASH_OF_MAPS, htab_of_maps_map_ops)
>  #ifdef CONFIG_NET
>  BPF_MAP_TYPE(BPF_MAP_TYPE_DEVMAP, dev_map_ops)
> +BPF_MAP_TYPE(BPF_MAP_TYPE_DEVMAP_HASH, dev_map_hash_ops)
>  BPF_MAP_TYPE(BPF_MAP_TYPE_SK_STORAGE, sk_storage_map_ops)
>  #if defined(CONFIG_BPF_STREAM_PARSER)
>  BPF_MAP_TYPE(BPF_MAP_TYPE_SOCKMAP, sock_map_ops)
[...]

^ permalink raw reply

* Re: [PATCH net-next v2 8/8] net: mscc: PTP Hardware Clock (PHC) support
From: Richard Cochran @ 2019-07-05 22:02 UTC (permalink / raw)
  To: Antoine Tenart
  Cc: davem, alexandre.belloni, UNGLinuxDriver, ralf, paul.burton,
	jhogan, netdev, linux-mips, thomas.petazzoni, allan.nielsen
In-Reply-To: <20190705195213.22041-9-antoine.tenart@bootlin.com>

On Fri, Jul 05, 2019 at 09:52:13PM +0200, Antoine Tenart wrote:
> +static irqreturn_t ocelot_ptp_rdy_irq_handler(int irq, void *arg)
> +{
> +	struct ocelot *ocelot = arg;
> +
> +	do {

> +		/* Check if a timestamp can be retrieved */
> +		if (!(val & SYS_PTP_STATUS_PTP_MESS_VLD))
> +			break;

As in my reply on v1, I suggest adding a sanity check on this ISR's
infinite loop.

> +	} while (true);
> +
> +	return IRQ_HANDLED;
> +}

Thanks,
Richard

^ permalink raw reply

* Re: pull request (net-next): ipsec-next 2019-07-05
From: David Miller @ 2019-07-05 22:01 UTC (permalink / raw)
  To: steffen.klassert; +Cc: herbert, netdev
In-Reply-To: <20190705084610.3646-1-steffen.klassert@secunet.com>

From: Steffen Klassert <steffen.klassert@secunet.com>
Date: Fri, 5 Jul 2019 10:46:01 +0200

> 1) A lot of work to remove indirections from the xfrm code.
>    From Florian Westphal.
> 
> 2) Fix a WARN_ON with ipv6 that triggered because of a
>    forgotten break statement. From Florian Westphal.
> 
> 3)  Remove xfrmi_init_net, it is not needed.
>     From Li RongQing.
> 
> Please pull or let me know if there are problems.

Pulled, thanks.

^ permalink raw reply

* Re: [PATCH bpf-next] Enable zext optimization for more RV64G ALU ops
From: Daniel Borkmann @ 2019-07-05 22:01 UTC (permalink / raw)
  To: Luke Nelson, linux-kernel
  Cc: Luke Nelson, Song Liu, Jiong Wang, Xi Wang, Björn Töpel,
	Palmer Dabbelt, Albert Ou, Alexei Starovoitov, Martin KaFai Lau,
	Song Liu, Yonghong Song, netdev, linux-riscv, bpf
In-Reply-To: <20190705001803.30094-1-luke.r.nels@gmail.com>

On 07/05/2019 02:18 AM, Luke Nelson wrote:
> commit 66d0d5a854a6 ("riscv: bpf: eliminate zero extension code-gen")
> added the new zero-extension optimization for some BPF ALU operations.
> 
> Since then, bugs in the JIT that have been fixed in the bpf tree require
> this optimization to be added to other operations: commit 1e692f09e091
> ("bpf, riscv: clear high 32 bits for ALU32 add/sub/neg/lsh/rsh/arsh"),
> and commit fe121ee531d1 ("bpf, riscv: clear target register high 32-bits
> for and/or/xor on ALU32")
> 
> Now that these have been merged to bpf-next, the zext optimization can
> be enabled for the fixed operations.
> 
> Cc: Song Liu <liu.song.a23@gmail.com>
> Cc: Jiong Wang <jiong.wang@netronome.com>
> Cc: Xi Wang <xi.wang@gmail.com>
> Signed-off-by: Luke Nelson <luke.r.nels@gmail.com>

Applied, thanks!

^ permalink raw reply

* Re: [PATCHv2] tools bpftool: Fix json dump crash on powerpc
From: Daniel Borkmann @ 2019-07-05 22:00 UTC (permalink / raw)
  To: Quentin Monnet, Jakub Kicinski, Jiri Olsa
  Cc: Jiri Olsa, Alexei Starovoitov, Michael Petlan, netdev, bpf,
	Martin KaFai Lau
In-Reply-To: <83d18af0-8efa-c8d5-3d99-01aed29915df@netronome.com>

On 07/05/2019 07:26 PM, Quentin Monnet wrote:
> 2019-07-05 10:24 UTC-0700 ~ Jakub Kicinski <jakub.kicinski@netronome.com>
>> On Fri, 5 Jul 2019 14:10:31 +0200, Jiri Olsa wrote:
>>> Michael reported crash with by bpf program in json mode on powerpc:
>>>
>>>   # bpftool prog -p dump jited id 14
>>>   [{
>>>         "name": "0xd00000000a9aa760",
>>>         "insns": [{
>>>                 "pc": "0x0",
>>>                 "operation": "nop",
>>>                 "operands": [null
>>>                 ]
>>>             },{
>>>                 "pc": "0x4",
>>>                 "operation": "nop",
>>>                 "operands": [null
>>>                 ]
>>>             },{
>>>                 "pc": "0x8",
>>>                 "operation": "mflr",
>>>   Segmentation fault (core dumped)
>>>
>>> The code is assuming char pointers in format, which is not always
>>> true at least for powerpc. Fixing this by dumping the whole string
>>> into buffer based on its format.
>>>
>>> Please note that libopcodes code does not check return values from
>>> fprintf callback, but as per Jakub suggestion returning -1 on allocation
>>> failure so we do the best effort to propagate the error. 
>>>
>>> Reported-by: Michael Petlan <mpetlan@redhat.com>
>>> Signed-off-by: Jiri Olsa <jolsa@kernel.org>
>>
>> Thanks, let me repost all the tags (Quentin, please shout if you're
>> not ok with this :)):
> 
> I confirm it's all good for me, thanks :)
> 
>> Fixes: 107f041212c1 ("tools: bpftool: add JSON output for `bpftool prog dump jited *` command")
>> Reviewed-by: Quentin Monnet <quentin.monnet@netronome.com>
>> Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com>

Given merge window coming up, I've applied this to bpf-next, thanks everyone!

P.s.: Jiri, please repost full/proper patch next time instead of inline reply.

^ permalink raw reply

* Re: [PATCH bpf-next v2] tools: bpftool: add "prog run" subcommand to test-run programs
From: Daniel Borkmann @ 2019-07-05 21:58 UTC (permalink / raw)
  To: Quentin Monnet, Alexei Starovoitov
  Cc: bpf, netdev, oss-drivers, Yonghong Song
In-Reply-To: <20190705175433.22511-1-quentin.monnet@netronome.com>

On 07/05/2019 07:54 PM, Quentin Monnet wrote:
> Add a new "bpftool prog run" subcommand to run a loaded program on input
> data (and possibly with input context) passed by the user.
> 
> Print output data (and output context if relevant) into a file or into
> the console. Print return value and duration for the test run into the
> console.
> 
> A "repeat" argument can be passed to run the program several times in a
> row.
> 
> The command does not perform any kind of verification based on program
> type (Is this program type allowed to use an input context?) or on data
> consistency (Can I work with empty input data?), this is left to the
> kernel.
> 
> Example invocation:
> 
>     # perl -e 'print "\x0" x 14' | ./bpftool prog run \
>             pinned /sys/fs/bpf/sample_ret0 \
>             data_in - data_out - repeat 5
>     0000000 0000 0000 0000 0000 0000 0000 0000      | ........ ......
>     Return value: 0, duration (average): 260ns
> 
> When one of data_in or ctx_in is "-", bpftool reads from standard input,
> in binary format. Other formats (JSON, hexdump) might be supported (via
> an optional command line keyword like "data_fmt_in") in the future if
> relevant, but this would require doing more parsing in bpftool.
> 
> v2:
> - Fix argument names for function check_single_stdin(). (Yonghong)
> 
> Signed-off-by: Quentin Monnet <quentin.monnet@netronome.com>
> Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com>

Looks great, thanks for adding, applied!

^ permalink raw reply

* Re: [PATCH net-next 8/8] net: mscc: PTP Hardware Clock (PHC) support
From: Richard Cochran @ 2019-07-05 21:58 UTC (permalink / raw)
  To: Antoine Tenart
  Cc: davem, alexandre.belloni, UNGLinuxDriver, ralf, paul.burton,
	jhogan, netdev, linux-mips, thomas.petazzoni, allan.nielsen
In-Reply-To: <20190701100327.6425-9-antoine.tenart@bootlin.com>

On Mon, Jul 01, 2019 at 12:03:27PM +0200, Antoine Tenart wrote:

> +static irqreturn_t ocelot_ptp_rdy_irq_handler(int irq, void *arg)
> +{
> +	struct ocelot *ocelot = arg;
> +
> +	do {
> +		struct skb_shared_hwtstamps shhwtstamps;
> +		struct list_head *pos, *tmp;
> +		struct ocelot_skb *entry;
> +		struct ocelot_port *port;
> +		struct timespec64 ts;
> +		struct sk_buff *skb = NULL;
> +		u32 val, id, txport;
> +
> +		val = ocelot_read(ocelot, SYS_PTP_STATUS);
> +
> +		/* Check if a timestamp can be retrieved */
> +		if (!(val & SYS_PTP_STATUS_PTP_MESS_VLD))
> +			break;

Instead of an infinite do/while loop, I suggest a for loop bounded by
number of iterations or by execution time.  That would avoid getting
stuck here forever.  After all, this code is an ISR.

Thanks,
Richard

> +		WARN_ON(val & SYS_PTP_STATUS_PTP_OVFL);
> +
> +		/* Retrieve the ts ID and Tx port */
> +		id = SYS_PTP_STATUS_PTP_MESS_ID_X(val);
> +		txport = SYS_PTP_STATUS_PTP_MESS_TXPORT_X(val);
> +
> +		/* Retrieve its associated skb */
> +		port = ocelot->ports[txport];
> +
> +		list_for_each_safe(pos, tmp, &port->skbs) {
> +			entry = list_entry(pos, struct ocelot_skb, head);
> +			if (entry->id != id)
> +				continue;
> +
> +			skb = entry->skb;
> +
> +			list_del(pos);
> +			kfree(entry);
> +		}
> +
> +		/* Next ts */
> +		ocelot_write(ocelot, SYS_PTP_NXT_PTP_NXT, SYS_PTP_NXT);
> +
> +		if (unlikely(!skb))
> +			continue;
> +
> +		/* Get the h/w timestamp */
> +		ocelot_get_hwtimestamp(ocelot, &ts);
> +
> +		/* Set the timestamp into the skb */
> +		memset(&shhwtstamps, 0, sizeof(shhwtstamps));
> +		shhwtstamps.hwtstamp = ktime_set(ts.tv_sec, ts.tv_nsec);
> +		skb_tstamp_tx(skb, &shhwtstamps);
> +
> +		dev_kfree_skb_any(skb);
> +	} while (true);
> +
> +	return IRQ_HANDLED;
> +}

^ permalink raw reply

* Re: pull request (net): ipsec 2019-07-05
From: David Miller @ 2019-07-05 21:58 UTC (permalink / raw)
  To: steffen.klassert; +Cc: herbert, netdev
In-Reply-To: <20190705082700.31107-1-steffen.klassert@secunet.com>

From: Steffen Klassert <steffen.klassert@secunet.com>
Date: Fri, 5 Jul 2019 10:26:53 +0200

> 1)  Fix xfrm selector prefix length validation for
>     inter address family tunneling.
>     From Anirudh Gupta.
> 
> 2) Fix a memleak in pfkey.
>    From Jeremy Sowden.
> 
> 3) Fix SA selector validation to allow empty selectors again.
>    From Nicolas Dichtel.
> 
> 4) Select crypto ciphers for xfrm_algo, this fixes some
>    randconfig builds. From Arnd Bergmann.
> 
> 5) Remove a duplicated assignment in xfrm_bydst_resize.
>    From Cong Wang.
> 
> 6) Fix a hlist corruption on hash rebuild.
>    From Florian Westphal.
> 
> 7) Fix a memory leak when creating xfrm interfaces.
>    From Nicolas Dichtel.
> 
> Please pull or let me know if there are problems.

Pulled, thanks Steffen.

^ permalink raw reply

* Re: [PATCH net-next 0/2] net: mvpp2: Add classification based on the ETHER flow
From: Jakub Kicinski @ 2019-07-05 21:49 UTC (permalink / raw)
  To: Maxime Chevallier
  Cc: davem, netdev, linux-kernel, linux-arm-kernel, Antoine Tenart,
	thomas.petazzoni, gregory.clement, miquel.raynal, nadavh, stefanc,
	mw
In-Reply-To: <20190705120913.25013-1-maxime.chevallier@bootlin.com>

On Fri,  5 Jul 2019 14:09:11 +0200, Maxime Chevallier wrote:
> Hello everyone,
> 
> This series adds support for classification of the ETHER flow in the
> mvpp2 driver.
> 
> The first patch allows detecting when a user specifies a flow_type that
> isn't supported by the driver, while the second adds support for this
> flow_type by adding the mapping between the ETHER_FLOW enum value and
> the relevant classifier flow entries.

LGTM

^ permalink raw reply

* Re: [PATCH bpf-next 1/2] bpf, libbpf: add a new API bpf_object__reuse_maps()
From: Daniel Borkmann @ 2019-07-05 21:44 UTC (permalink / raw)
  To: Anton Protopopov, Alexei Starovoitov, Martin KaFai Lau, Song Liu,
	Yonghong Song, netdev, bpf, linux-kernel, andriin
In-Reply-To: <e183c0af99056f8ea4de06acb358ace7f3a3d6ae.1562359091.git.a.s.protopopov@gmail.com>

On 07/05/2019 10:44 PM, Anton Protopopov wrote:
> Add a new API bpf_object__reuse_maps() which can be used to replace all maps in
> an object by maps pinned to a directory provided in the path argument.  Namely,
> each map M in the object will be replaced by a map pinned to path/M.name.
> 
> Signed-off-by: Anton Protopopov <a.s.protopopov@gmail.com>
> ---
>  tools/lib/bpf/libbpf.c   | 34 ++++++++++++++++++++++++++++++++++
>  tools/lib/bpf/libbpf.h   |  2 ++
>  tools/lib/bpf/libbpf.map |  1 +
>  3 files changed, 37 insertions(+)
> 
> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> index 4907997289e9..84c9e8f7bfd3 100644
> --- a/tools/lib/bpf/libbpf.c
> +++ b/tools/lib/bpf/libbpf.c
> @@ -3144,6 +3144,40 @@ int bpf_object__unpin_maps(struct bpf_object *obj, const char *path)
>  	return 0;
>  }
>  
> +int bpf_object__reuse_maps(struct bpf_object *obj, const char *path)
> +{
> +	struct bpf_map *map;
> +
> +	if (!obj)
> +		return -ENOENT;
> +
> +	if (!path)
> +		return -EINVAL;
> +
> +	bpf_object__for_each_map(map, obj) {
> +		int len, err;
> +		int pinned_map_fd;
> +		char buf[PATH_MAX];

We'd need to skip the case of bpf_map__is_internal(map) since they are always
recreated for the given object.

> +		len = snprintf(buf, PATH_MAX, "%s/%s", path, bpf_map__name(map));
> +		if (len < 0) {
> +			return -EINVAL;
> +		} else if (len >= PATH_MAX) {
> +			return -ENAMETOOLONG;
> +		}
> +
> +		pinned_map_fd = bpf_obj_get(buf);
> +		if (pinned_map_fd < 0)
> +			return pinned_map_fd;

Should we rather have a new map definition attribute that tells to reuse
the map if it's pinned in bpf fs, and if not, we create it and later on
pin it? This is what iproute2 is doing and which we're making use of heavily.
In bpf_object__reuse_maps() bailing out if bpf_obj_get() fails is perhaps
too limiting for a generic API as new version of an object file may contain
new maps which are not yet present in bpf fs at that point.

> +		err = bpf_map__reuse_fd(map, pinned_map_fd);
> +		if (err)
> +			return err;
> +	}
> +
> +	return 0;
> +}
> +
>  int bpf_object__pin_programs(struct bpf_object *obj, const char *path)
>  {
>  	struct bpf_program *prog;
> diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
> index d639f47e3110..7fe465a1be76 100644
> --- a/tools/lib/bpf/libbpf.h
> +++ b/tools/lib/bpf/libbpf.h
> @@ -82,6 +82,8 @@ int bpf_object__variable_offset(const struct bpf_object *obj, const char *name,
>  LIBBPF_API int bpf_object__pin_maps(struct bpf_object *obj, const char *path);
>  LIBBPF_API int bpf_object__unpin_maps(struct bpf_object *obj,
>  				      const char *path);
> +LIBBPF_API int bpf_object__reuse_maps(struct bpf_object *obj,
> +				      const char *path);
>  LIBBPF_API int bpf_object__pin_programs(struct bpf_object *obj,
>  					const char *path);
>  LIBBPF_API int bpf_object__unpin_programs(struct bpf_object *obj,
> diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map
> index 2c6d835620d2..66a30be6696c 100644
> --- a/tools/lib/bpf/libbpf.map
> +++ b/tools/lib/bpf/libbpf.map
> @@ -172,5 +172,6 @@ LIBBPF_0.0.4 {
>  		btf_dump__new;
>  		btf__parse_elf;
>  		bpf_object__load_xattr;
> +		bpf_object__reuse_maps;
>  		libbpf_num_possible_cpus;
>  } LIBBPF_0.0.3;
> 


^ permalink raw reply

* [GIT PULL] Keys: Set 4 - Key ACLs for 5.3
From: David Howells @ 2019-07-05 21:30 UTC (permalink / raw)
  To: torvalds
  Cc: dhowells, jmorris, keyrings, netdev, linux-nfs, linux-cifs,
	linux-afs, linux-fsdevel, linux-integrity, linux-security-module,
	linux-kernel

Hi Linus,

Here's my fourth block of keyrings changes for the next merge window.  They
change the permissions model used by keys and keyrings to be based on an
internal ACL by the following means:

 (1) Replace the permissions mask internally with an ACL that contains a
     list of ACEs, each with a specific subject with a permissions mask.
     Potted default ACLs are available for new keys and keyrings.

     ACE subjects can be macroised to indicate the UID and GID specified on
     the key (which remain).  Future commits will be able to add additional
     subject types, such as specific UIDs or domain tags/namespaces.

     Also split a number of permissions to give finer control.  Examples
     include splitting the revocation permit from the change-attributes
     permit, thereby allowing someone to be granted permission to revoke a
     key without allowing them to change the owner; also the ability to
     join a keyring is split from the ability to link to it, thereby
     stopping a process accessing a keyring by joining it and thus
     acquiring use of possessor permits.

 (2) Provide a keyctl to allow the granting or denial of one or more
     permits to a specific subject.  Direct access to the ACL is not
     granted, and the ACL cannot be viewed.

David
---
The following changes since commit a58946c158a040068e7c94dc1d58bbd273258068:

  keys: Pass the network namespace into request_key mechanism (2019-06-27 23:02:12 +0100)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs.git tags/keys-acl-20190703

for you to fetch changes up to 7a1ade847596dadc94b37e49f8c03f167fd71748:

  keys: Provide KEYCTL_GRANT_PERMISSION (2019-07-03 13:05:22 +0100)

----------------------------------------------------------------
Keyrings ACL

----------------------------------------------------------------
David Howells (2):
      keys: Replace uid/gid/perm permissions checking with an ACL
      keys: Provide KEYCTL_GRANT_PERMISSION

 Documentation/security/keys/core.rst               | 128 ++++++--
 Documentation/security/keys/request-key.rst        |   9 +-
 certs/blacklist.c                                  |   7 +-
 certs/system_keyring.c                             |  12 +-
 drivers/md/dm-crypt.c                              |   2 +-
 drivers/nvdimm/security.c                          |   2 +-
 fs/afs/security.c                                  |   2 +-
 fs/cifs/cifs_spnego.c                              |  25 +-
 fs/cifs/cifsacl.c                                  |  28 +-
 fs/cifs/connect.c                                  |   4 +-
 fs/crypto/keyinfo.c                                |   2 +-
 fs/ecryptfs/ecryptfs_kernel.h                      |   2 +-
 fs/ecryptfs/keystore.c                             |   2 +-
 fs/fscache/object-list.c                           |   2 +-
 fs/nfs/nfs4idmap.c                                 |  30 +-
 fs/ubifs/auth.c                                    |   2 +-
 include/linux/key.h                                | 121 +++----
 include/uapi/linux/keyctl.h                        |  65 ++++
 lib/digsig.c                                       |   2 +-
 net/ceph/ceph_common.c                             |   2 +-
 net/dns_resolver/dns_key.c                         |  12 +-
 net/dns_resolver/dns_query.c                       |  15 +-
 net/rxrpc/key.c                                    |  19 +-
 net/wireless/reg.c                                 |   6 +-
 security/integrity/digsig.c                        |  31 +-
 security/integrity/digsig_asymmetric.c             |   2 +-
 security/integrity/evm/evm_crypto.c                |   2 +-
 security/integrity/ima/ima_mok.c                   |  13 +-
 security/integrity/integrity.h                     |   6 +-
 .../integrity/platform_certs/platform_keyring.c    |  14 +-
 security/keys/compat.c                             |   2 +
 security/keys/encrypted-keys/encrypted.c           |   2 +-
 security/keys/encrypted-keys/masterkey_trusted.c   |   2 +-
 security/keys/gc.c                                 |   2 +-
 security/keys/internal.h                           |  16 +-
 security/keys/key.c                                |  29 +-
 security/keys/keyctl.c                             | 104 ++++--
 security/keys/keyring.c                            |  27 +-
 security/keys/permission.c                         | 361 +++++++++++++++++++--
 security/keys/persistent.c                         |  27 +-
 security/keys/proc.c                               |  22 +-
 security/keys/process_keys.c                       |  86 +++--
 security/keys/request_key.c                        |  34 +-
 security/keys/request_key_auth.c                   |  15 +-
 security/selinux/hooks.c                           |  16 +-
 security/smack/smack_lsm.c                         |   3 +-
 46 files changed, 992 insertions(+), 325 deletions(-)

^ permalink raw reply

* [GIT PULL] Keys: Set 3 - Keyrings namespacing for 5.3
From: David Howells @ 2019-07-05 21:20 UTC (permalink / raw)
  To: torvalds
  Cc: dhowells, jmorris, ebiederm, dwalsh, keyrings, netdev, linux-nfs,
	linux-cifs, linux-afs, linux-security-module, linux-kernel

Here's my third block of keyrings changes for the next merge window.

These patches help make keys and keyrings more namespace aware.  Firstly
some miscellaneous patches to make the process easier:

 (1) Simplify key index_key handling so that the word-sized chunks
     assoc_array requires don't have to be shifted about, making it easier
     to add more bits into the key.

 (2) Cache the hash value in the key so that we don't have to calculate on
     every key we examine during a search (it involves a bunch of
     multiplications).

 (3) Allow keying_search() to search non-recursively.

Then the main patches:

 (4) Make it so that keyring names are per-user_namespace from the point of
     view of KEYCTL_JOIN_SESSION_KEYRING so that they're not accessible
     cross-user_namespace.

     keyctl_capabilities() shows KEYCTL_CAPS1_NS_KEYRING_NAME for this.

 (5) Move the user and user-session keyrings to the user_namespace rather
     than the user_struct.  This prevents them propagating directly across
     user_namespaces boundaries (ie. the KEY_SPEC_* flags will only pick
     from the current user_namespace).

 (6) Make it possible to include the target namespace in which the key shall
     operate in the index_key.  This will allow the possibility of multiple
     keys with the same description, but different target domains to be held
     in the same keyring.

     keyctl_capabilities() shows KEYCTL_CAPS1_NS_KEY_TAG for this.

 (7) Make it so that keys are implicitly invalidated by removal of a domain
     tag, causing them to be garbage collected.

 (8) Institute a network namespace domain tag that allows keys to be
     differentiated by the network namespace in which they operate.  New keys
     that are of a type marked 'KEY_TYPE_NET_DOMAIN' are assigned the network
     domain in force when they are created.

 (9) Make it so that the desired network namespace can be handed down into the
     request_key() mechanism.  This allows AFS, NFS, etc. to request keys
     specific to the network namespace of the superblock.

     This also means that the keys in the DNS record cache are thenceforth
     namespaced, provided network filesystems pass the appropriate network
     namespace down into dns_query().

     For DNS, AFS and NFS are good, whilst CIFS and Ceph are not.  Other
     cache keyrings, such as idmapper keyrings, also need to set the domain
     tag - for which they need access to the network namespace of the
     superblock.

David
---
The following changes since commit 3b8c4a08a471d56ecaaca939c972fdf5b8255629:

  keys: Kill off request_key_async{,_with_auxdata} (2019-06-26 20:58:13 +0100)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs.git tags/keys-namespace-20190627

for you to fetch changes up to a58946c158a040068e7c94dc1d58bbd273258068:

  keys: Pass the network namespace into request_key mechanism (2019-06-27 23:02:12 +0100)

----------------------------------------------------------------
Keyrings namespacing

----------------------------------------------------------------
David Howells (9):
      keys: Simplify key description management
      keys: Cache the hash value to avoid lots of recalculation
      keys: Add a 'recurse' flag for keyring searches
      keys: Namespace keyring names
      keys: Move the user and user-session keyrings to the user_namespace
      keys: Include target namespace in match criteria
      keys: Garbage collect keys for which the domain has been removed
      keys: Network namespace domain tag
      keys: Pass the network namespace into request_key mechanism

 Documentation/security/keys/core.rst        |  38 ++--
 Documentation/security/keys/request-key.rst |  29 ++-
 certs/blacklist.c                           |   2 +-
 crypto/asymmetric_keys/asymmetric_type.c    |   2 +-
 fs/afs/addr_list.c                          |   4 +-
 fs/afs/dynroot.c                            |   8 +-
 fs/cifs/dns_resolve.c                       |   3 +-
 fs/nfs/dns_resolve.c                        |   3 +-
 fs/nfs/nfs4idmap.c                          |   2 +-
 include/linux/dns_resolver.h                |   3 +-
 include/linux/key-type.h                    |   3 +
 include/linux/key.h                         |  81 ++++++++-
 include/linux/sched/user.h                  |  14 --
 include/linux/user_namespace.h              |  12 +-
 include/net/net_namespace.h                 |   3 +
 include/uapi/linux/keyctl.h                 |   2 +
 kernel/user.c                               |   8 +-
 kernel/user_namespace.c                     |   9 +-
 lib/digsig.c                                |   2 +-
 net/ceph/messenger.c                        |   3 +-
 net/core/net_namespace.c                    |  20 +++
 net/dns_resolver/dns_key.c                  |   1 +
 net/dns_resolver/dns_query.c                |   7 +-
 net/rxrpc/key.c                             |   6 +-
 net/rxrpc/security.c                        |   2 +-
 security/integrity/digsig_asymmetric.c      |   4 +-
 security/keys/gc.c                          |   2 +-
 security/keys/internal.h                    |  10 +-
 security/keys/key.c                         |   5 +-
 security/keys/keyctl.c                      |   8 +-
 security/keys/keyring.c                     | 263 ++++++++++++++++------------
 security/keys/persistent.c                  |  10 +-
 security/keys/proc.c                        |   3 +-
 security/keys/process_keys.c                | 262 +++++++++++++++++----------
 security/keys/request_key.c                 |  62 ++++---
 security/keys/request_key_auth.c            |   3 +-
 36 files changed, 589 insertions(+), 310 deletions(-)

^ permalink raw reply

* Re: [PATCH v5 bpf-next 0/4] capture integers in BTF type info for map defs
From: Daniel Borkmann @ 2019-07-05 21:15 UTC (permalink / raw)
  To: Andrii Nakryiko, andrii.nakryiko, kernel-team, ast, netdev, bpf
In-Reply-To: <20190705155012.3539722-1-andriin@fb.com>

On 07/05/2019 05:50 PM, Andrii Nakryiko wrote:
> This patch set implements an update to how BTF-defined maps are specified. The
> change is in how integer attributes, e.g., type, max_entries, map_flags, are
> specified: now they are captured as part of map definition struct's BTF type
> information (using array dimension), eliminating the need for compile-time
> data initialization and keeping all the metadata in one place.
> 
> All existing selftests that were using BTF-defined maps are updated, along
> with some other selftests, that were switched to new syntax.
> 
> v4->v5:
> - revert sample_map_ret0.c, which is loaded with iproute2 (kernel test robot);
> v3->v4:
> - add acks;
> - fix int -> uint type in commit message;
> v2->v3:
> - rename __int into __uint (Yonghong);
> v1->v2:
> - split bpf_helpers.h change from libbpf change (Song).
> 
> Andrii Nakryiko (4):
>   libbpf: capture value in BTF type info for BTF-defined map defs
>   selftests/bpf: add __uint and __type macro for BTF-defined maps
>   selftests/bpf: convert selftests using BTF-defined maps to new syntax
>   selftests/bpf: convert legacy BPF maps to BTF-defined ones
> 
>  tools/lib/bpf/libbpf.c                        |  58 +++++----
>  tools/testing/selftests/bpf/bpf_helpers.h     |   3 +
>  tools/testing/selftests/bpf/progs/bpf_flow.c  |  28 ++---
>  .../selftests/bpf/progs/get_cgroup_id_kern.c  |  26 ++---
>  .../testing/selftests/bpf/progs/netcnt_prog.c |  20 ++--
>  tools/testing/selftests/bpf/progs/pyperf.h    |  90 +++++++-------
>  .../selftests/bpf/progs/socket_cookie_prog.c  |  13 +--
>  .../bpf/progs/sockmap_verdict_prog.c          |  48 ++++----
>  .../testing/selftests/bpf/progs/strobemeta.h  |  68 +++++------
>  .../selftests/bpf/progs/test_btf_newkv.c      |  13 +--
>  .../bpf/progs/test_get_stack_rawtp.c          |  39 +++----
>  .../selftests/bpf/progs/test_global_data.c    |  37 +++---
>  tools/testing/selftests/bpf/progs/test_l4lb.c |  65 ++++-------
>  .../selftests/bpf/progs/test_l4lb_noinline.c  |  65 ++++-------
>  .../selftests/bpf/progs/test_map_in_map.c     |  30 ++---
>  .../selftests/bpf/progs/test_map_lock.c       |  26 ++---
>  .../testing/selftests/bpf/progs/test_obj_id.c |  12 +-
>  .../bpf/progs/test_select_reuseport_kern.c    |  67 ++++-------
>  .../bpf/progs/test_send_signal_kern.c         |  26 ++---
>  .../bpf/progs/test_sock_fields_kern.c         |  78 +++++--------
>  .../selftests/bpf/progs/test_spin_lock.c      |  36 +++---
>  .../bpf/progs/test_stacktrace_build_id.c      |  55 ++++-----
>  .../selftests/bpf/progs/test_stacktrace_map.c |  52 +++------
>  .../selftests/bpf/progs/test_tcp_estats.c     |  13 +--
>  .../selftests/bpf/progs/test_tcpbpf_kern.c    |  26 ++---
>  .../selftests/bpf/progs/test_tcpnotify_kern.c |  28 ++---
>  tools/testing/selftests/bpf/progs/test_xdp.c  |  26 ++---
>  .../selftests/bpf/progs/test_xdp_loop.c       |  26 ++---
>  .../selftests/bpf/progs/test_xdp_noinline.c   |  81 +++++--------
>  .../selftests/bpf/progs/xdp_redirect_map.c    |  12 +-
>  .../testing/selftests/bpf/progs/xdping_kern.c |  12 +-
>  .../selftests/bpf/test_queue_stack_map.h      |  30 ++---
>  .../testing/selftests/bpf/test_sockmap_kern.h | 110 +++++++++---------
>  33 files changed, 559 insertions(+), 760 deletions(-)

LGTM, applied, thanks! Shouldn't we also move __uint and __type macros
into libbpf as otherwise people tend to redefine this over and over?

^ permalink raw reply

* [PATCH net-next v2 0/8] net: mscc: PTP Hardware Clock (PHC) support
From: Antoine Tenart @ 2019-07-05 19:52 UTC (permalink / raw)
  To: davem, richardcochran, alexandre.belloni, UNGLinuxDriver, ralf,
	paul.burton, jhogan
  Cc: Antoine Tenart, netdev, linux-mips, thomas.petazzoni,
	allan.nielsen

Hello,

This series introduces the PTP Hardware Clock (PHC) support to the Mscc
Ocelot switch driver. In order to make use of this, a new register bank
is added and described in the device tree, as well as a new interrupt.
The use this bank and interrupt was made optional in the driver for dt
compatibility reasons.

Patches 2 and 4 should probably go through the MIPS tree.

Thanks!
Antoine

Since v1:
  - Used list_for_each_safe() in ocelot_deinit().
  - Fixed a memory leak in ocelot_deinit() by calling
    dev_kfree_skb_any().
  - Fixed a locking issue in get_hwtimestamp().
  - Handled the NULL case of ptp_clock_register().
  - Added comments on optional dt properties.

Antoine Tenart (8):
  Documentation/bindings: net: ocelot: document the PTP bank
  MIPS: dts: mscc: describe the PTP register range
  Documentation/bindings: net: ocelot: document the PTP ready IRQ
  MIPS: dts: mscc: describe the PTP ready interrupt
  net: mscc: describe the PTP register range
  net: mscc: improve the frame header parsing readability
  net: mscc: remove the frame_info cpuq member
  net: mscc: PTP Hardware Clock (PHC) support

 .../devicetree/bindings/net/mscc-ocelot.txt   |  20 +-
 arch/mips/boot/dts/mscc/ocelot.dtsi           |   7 +-
 drivers/net/ethernet/mscc/ocelot.c            | 393 +++++++++++++++++-
 drivers/net/ethernet/mscc/ocelot.h            |  47 ++-
 drivers/net/ethernet/mscc/ocelot_board.c      | 139 ++++++-
 drivers/net/ethernet/mscc/ocelot_ptp.h        |  41 ++
 drivers/net/ethernet/mscc/ocelot_regs.c       |  11 +
 7 files changed, 626 insertions(+), 32 deletions(-)
 create mode 100644 drivers/net/ethernet/mscc/ocelot_ptp.h

-- 
2.21.0


^ permalink raw reply

* Re: [PATCH v5 bpf-next 4/9] libbpf: add kprobe/uprobe attach API
From: Daniel Borkmann @ 2019-07-05 20:46 UTC (permalink / raw)
  To: Andrii Nakryiko
  Cc: Andrii Nakryiko, bpf, Networking, Alexei Starovoitov, Kernel Team,
	Yonghong Song
In-Reply-To: <CAEf4BzaUeLDgwzBc0EbXnzahe8wxf9CNVFa_isgRp8rwJ0OSjQ@mail.gmail.com>

On 07/04/2019 02:57 AM, Andrii Nakryiko wrote:
> On Wed, Jul 3, 2019 at 9:47 AM Andrii Nakryiko
> <andrii.nakryiko@gmail.com> wrote:
[...]
>>   [1] https://lore.kernel.org/bpf/20190621045555.4152743-4-andriin@fb.com/T/#m6cfc141e7b57970bc948134bf671a46972b95134
>>
>>> with bpf_link with destructor looks good to me, but my feedback from back then was
>>> that all the kprobe/uprobe/tracepoint/raw_tracepoint should be split API-wise, so
>>> you'll end up with something like the below, that is, 1) a set of functions that
>>> only /create/ the bpf_link handle /once/, and 2) a helper that allows /attaching/
>>> progs to one or multiple bpf_links. The set of APIs would look like:
>>>
>>> struct bpf_link *bpf_link__create_kprobe(bool retprobe, const char *func_name);
>>> struct bpf_link *bpf_link__create_uprobe(bool retprobe, pid_t pid,
>>>                                          const char *binary_path,
>>>                                          size_t func_offset);
>>> int bpf_program__attach_to_link(struct bpf_link *link, struct bpf_program *prog);
>>> int bpf_link__destroy(struct bpf_link *link);
>>>
>>> This seems much more natural to me. Right now you sort of do both in one single API.
>>
>> It felt that way for me as well, until I implemented it and used it in
>> selftests. And then it felt unnecessarily verbose without giving any
>> benefit. I still have a local patchset with that change, I can post it
>> as RFC, if you don't trust my judgement. Please let me know.
>>
>>> Detangling the bpf_program__attach_{uprobe,kprobe}() would also avoid that you have
>>> to redo all the perf_event_open_probe() work over and over in order to get the pfd
> 
> So re-reading this again, I wonder if you meant that with separate
> bpf_link (or rather bpf_hook in that case) creation and attachment
> operations, one would be able to create single bpf_hook for same
> kprobe and then attach multiple BPF programs to that single pfd
> representing that specific probe.
> 
> If that's how I should have read it, I agree that it probably would be
> possible for some types of hooks, but not for every type of hook. But
> furthermore, how often in practice same application attaches many
> different BPF programs to the same hook? And it's also hard to imagine
> that hook creation (i.e., creating such FD for BPF hook), would ever
> be a bottleneck.
> 
> So I still think it's not a strong reason to go with API that's harder
> to use for typical use cases just because of hypothetical benefits in
> some extreme cases.

Was thinking along that lines, yes, as we run over an array of BPF progs,
but I just double checked the kernel code again and the relationship of
a BPF prog to perf_event is really just 1:1, just that the backing tp_event
(trace_event_call) contains the shared array. Given that, all makes sense
and there is no point in splitting. Therefore, applied, thanks!

^ permalink raw reply

* [PATCH bpf-next 1/2] bpf, libbpf: add a new API bpf_object__reuse_maps()
From: Anton Protopopov @ 2019-07-05 20:44 UTC (permalink / raw)
  To: Alexei Starovoitov, Daniel Borkmann, Martin KaFai Lau, Song Liu,
	Yonghong Song, netdev, bpf, linux-kernel
  Cc: Anton Protopopov
In-Reply-To: <cover.1562359091.git.a.s.protopopov@gmail.com>

Add a new API bpf_object__reuse_maps() which can be used to replace all maps in
an object by maps pinned to a directory provided in the path argument.  Namely,
each map M in the object will be replaced by a map pinned to path/M.name.

Signed-off-by: Anton Protopopov <a.s.protopopov@gmail.com>
---
 tools/lib/bpf/libbpf.c   | 34 ++++++++++++++++++++++++++++++++++
 tools/lib/bpf/libbpf.h   |  2 ++
 tools/lib/bpf/libbpf.map |  1 +
 3 files changed, 37 insertions(+)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 4907997289e9..84c9e8f7bfd3 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -3144,6 +3144,40 @@ int bpf_object__unpin_maps(struct bpf_object *obj, const char *path)
 	return 0;
 }
 
+int bpf_object__reuse_maps(struct bpf_object *obj, const char *path)
+{
+	struct bpf_map *map;
+
+	if (!obj)
+		return -ENOENT;
+
+	if (!path)
+		return -EINVAL;
+
+	bpf_object__for_each_map(map, obj) {
+		int len, err;
+		int pinned_map_fd;
+		char buf[PATH_MAX];
+
+		len = snprintf(buf, PATH_MAX, "%s/%s", path, bpf_map__name(map));
+		if (len < 0) {
+			return -EINVAL;
+		} else if (len >= PATH_MAX) {
+			return -ENAMETOOLONG;
+		}
+
+		pinned_map_fd = bpf_obj_get(buf);
+		if (pinned_map_fd < 0)
+			return pinned_map_fd;
+
+		err = bpf_map__reuse_fd(map, pinned_map_fd);
+		if (err)
+			return err;
+	}
+
+	return 0;
+}
+
 int bpf_object__pin_programs(struct bpf_object *obj, const char *path)
 {
 	struct bpf_program *prog;
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index d639f47e3110..7fe465a1be76 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -82,6 +82,8 @@ int bpf_object__variable_offset(const struct bpf_object *obj, const char *name,
 LIBBPF_API int bpf_object__pin_maps(struct bpf_object *obj, const char *path);
 LIBBPF_API int bpf_object__unpin_maps(struct bpf_object *obj,
 				      const char *path);
+LIBBPF_API int bpf_object__reuse_maps(struct bpf_object *obj,
+				      const char *path);
 LIBBPF_API int bpf_object__pin_programs(struct bpf_object *obj,
 					const char *path);
 LIBBPF_API int bpf_object__unpin_programs(struct bpf_object *obj,
diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map
index 2c6d835620d2..66a30be6696c 100644
--- a/tools/lib/bpf/libbpf.map
+++ b/tools/lib/bpf/libbpf.map
@@ -172,5 +172,6 @@ LIBBPF_0.0.4 {
 		btf_dump__new;
 		btf__parse_elf;
 		bpf_object__load_xattr;
+		bpf_object__reuse_maps;
 		libbpf_num_possible_cpus;
 } LIBBPF_0.0.3;
-- 
2.19.1


^ permalink raw reply related

* [PATCH bpf-next 2/2] bpf, libbpf: add an option to reuse existing maps in bpf_prog_load_xattr
From: Anton Protopopov @ 2019-07-05 20:44 UTC (permalink / raw)
  To: Alexei Starovoitov, Daniel Borkmann, Martin KaFai Lau, Song Liu,
	Yonghong Song, netdev, bpf, linux-kernel
  Cc: Anton Protopopov
In-Reply-To: <cover.1562359091.git.a.s.protopopov@gmail.com>

Add a new pinned_maps_path member to the bpf_prog_load_attr structure and
extend the bpf_prog_load_xattr() function to pass this pointer to the new
bpf_object__reuse_maps() helper. This change provides users with a simple
way to use existing pinned maps when (re)loading BPF programs.

Signed-off-by: Anton Protopopov <a.s.protopopov@gmail.com>
---
 tools/lib/bpf/libbpf.c | 8 ++++++++
 tools/lib/bpf/libbpf.h | 1 +
 2 files changed, 9 insertions(+)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 84c9e8f7bfd3..9daa09c9fe1a 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -3953,6 +3953,14 @@ int bpf_prog_load_xattr(const struct bpf_prog_load_attr *attr,
 			first_prog = prog;
 	}
 
+	if (attr->pinned_maps_path) {
+		err = bpf_object__reuse_maps(obj, attr->pinned_maps_path);
+		if (err < 0) {
+			bpf_object__close(obj);
+			return err;
+		}
+	}
+
 	bpf_object__for_each_map(map, obj) {
 		if (!bpf_map__is_offload_neutral(map))
 			map->map_ifindex = attr->ifindex;
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index 7fe465a1be76..6bf405bb9c1f 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -329,6 +329,7 @@ struct bpf_prog_load_attr {
 	int ifindex;
 	int log_level;
 	int prog_flags;
+	const char *pinned_maps_path;
 };
 
 LIBBPF_API int bpf_prog_load_xattr(const struct bpf_prog_load_attr *attr,
-- 
2.19.1


^ permalink raw reply related

* [PATCH bpf-next 0/2]  libbpf: add an option to reuse maps when loading a program
From: Anton Protopopov @ 2019-07-05 20:40 UTC (permalink / raw)
  To: Alexei Starovoitov, Daniel Borkmann, Martin KaFai Lau, Song Liu,
	Yonghong Song, netdev, bpf, linux-kernel
  Cc: Anton Protopopov

The following two patches add an option for users to reuse existing maps when
loading a program using the bpf_prog_load_xattr function.  A user can specify a
directory containing pinned maps inside the bpf_prog_load_attr structure, and in
this case the bpf_prog_load_xattr function will replace (bpf_map__reuse_fd) all
maps defined in the object with file descriptors obtained from corresponding
entries from the specified directory.

Anton Protopopov (2):
  bpf, libbpf: add a new API bpf_object__reuse_maps()
  bpf, libbpf: add an option to reuse existing maps in bpf_prog_load_xattr

 tools/lib/bpf/libbpf.c   | 42 ++++++++++++++++++++++++++++++++++++++++
 tools/lib/bpf/libbpf.h   |  3 +++
 tools/lib/bpf/libbpf.map |  1 +
 3 files changed, 46 insertions(+)

--
2.19.1

^ permalink raw reply

* Re: [PATCH net-next 00/12] mlx5 TLS TX HW offload support
From: Jakub Kicinski @ 2019-07-05 20:19 UTC (permalink / raw)
  To: Tariq Toukan
  Cc: David S. Miller, netdev, Eran Ben Elisha, Saeed Mahameed, moshe
In-Reply-To: <1562340622-4423-1-git-send-email-tariqt@mellanox.com>

On Fri,  5 Jul 2019 18:30:10 +0300, Tariq Toukan wrote:
> Hi Dave,
> 
> This series from Eran and me, adds TLS TX HW offload support to
> the mlx5 driver.
> 
> This offloads the kTLS encryption process from kernel to the 
> Mellanox NIC, saving CPU cycles and improving utilization.
> 
> Upon a new TLS connection request, driver is responsible to create
> a dedicated HW context and configure it according to the crypto info,
> so HW can do the encryption itself.
> 
> When the HW context gets out-of-sync (i.e. due to packets retransmission),
> driver is responsible for the re-sync process.
> This is done by posting special resync descriptors to the HW.
> 
> Feature is supported on Mellanox Connect-X 6DX, and newer.
> Series was tested on SimX simulator.
> 
> Series generated against net-next commit [1], with Saeed's request pulled [2]:
> 
> [1] c4cde5804d51 Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next
> [2] git://git.kernel.org/pub/scm/linux/kernel/git/saeed/linux.git tags/mlx5-updates-2019-07-04-v2
> 
> Changes from last pull request:
> Fixed comments from Jakub:
> Patch 4:
> - Replace zero  memset with a call to memzero_explicit().
> Patch 11:
> - Fix stats counters names.
> - Drop TLS SKB with non-matching netdev.

You guys probably really want to make 5.3 with this, so please feel free
to follow up on the comments to patch 12 separately.

Acked-by: Jakub Kicinski <jakub.kicinski@netronome.com>

^ permalink raw reply

* Re: [PATCH net-next 12/12] net/mlx5e: Add kTLS TX HW offload support
From: Jakub Kicinski @ 2019-07-05 20:17 UTC (permalink / raw)
  To: Tariq Toukan
  Cc: David S. Miller, netdev, Eran Ben Elisha, Saeed Mahameed, moshe
In-Reply-To: <1562340622-4423-13-git-send-email-tariqt@mellanox.com>

On Fri,  5 Jul 2019 18:30:22 +0300, Tariq Toukan wrote:
> Add support for transmit side kernel-TLS acceleration.
> Offload the crypto encryption to HW.
> 
> Per TLS connection:
> - Use a separate TIS to maintain the HW context.
> - Use a separate encryption key.
> - Maintain static and progress HW contexts by posting the proper
>   WQEs at creation time, or upon resync.
> - Use a special DUMP opcode to replay the previous frags and sync
>   the HW context.
> 
> To make sure the SQ is able to serve an xmit request, increase
> SQ stop room to cover:
> - static params WQE,
> - progress params WQE, and
> - resync DUMP per frag.
> 
> Currently supporting TLS 1.2, and key size 128bit.
> 
> Tested over SimX simulator.
> 
> Signed-off-by: Tariq Toukan <tariqt@mellanox.com>
> Signed-off-by: Eran Ben Elisha <eranbe@mellanox.com>
> Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>

> +struct sk_buff *mlx5e_ktls_handle_tx_skb(struct net_device *netdev,
> +					 struct mlx5e_txqsq *sq,
> +					 struct sk_buff *skb,
> +					 struct mlx5e_tx_wqe **wqe, u16 *pi)
> +{
> +	struct mlx5e_ktls_offload_context_tx *priv_tx;
> +	struct mlx5e_sq_stats *stats = sq->stats;
> +	struct mlx5_wqe_ctrl_seg *cseg;
> +	struct tls_context *tls_ctx;
> +	int datalen;
> +	u32 seq;
> +
> +	if (!skb->sk || !tls_is_sk_tx_device_offloaded(skb->sk))
> +		goto out;
> +
> +	datalen = skb->len - (skb_transport_offset(skb) + tcp_hdrlen(skb));
> +	if (!datalen)
> +		goto out;
> +
> +	tls_ctx = tls_get_ctx(skb->sk);
> +	if (unlikely(tls_ctx->netdev != netdev))

This really shouldn't happen, could you please add a WARN_ON_ONCE here?

> +		goto err_out;
> +
> +	priv_tx = mlx5e_get_ktls_tx_priv_ctx(tls_ctx);
> +
> +	if (unlikely(mlx5e_ktls_tx_offload_test_and_clear_pending(priv_tx))) {
> +		mlx5e_ktls_tx_post_param_wqes(sq, priv_tx, false, false);
> +		*wqe = mlx5e_sq_fetch_wqe(sq, sizeof(**wqe), pi);
> +		stats->tls_ctx++;
> +	}
> +
> +	seq = ntohl(tcp_hdr(skb)->seq);
> +	if (unlikely(priv_tx->expected_seq != seq)) {
> +		skb = mlx5e_ktls_tx_handle_ooo(priv_tx, sq, skb, seq);
> +		if (unlikely(!skb))
> +			goto out;
> +		*wqe = mlx5e_sq_fetch_wqe(sq, sizeof(**wqe), pi);
> +	}
> +
> +	priv_tx->expected_seq = seq + datalen;
> +
> +	cseg = &(*wqe)->ctrl;
> +	cseg->imm = cpu_to_be32(priv_tx->tisn);
> +
> +	stats->tls_encrypted_packets += skb_is_gso(skb) ? skb_shinfo(skb)->gso_segs : 1;
> +	stats->tls_encrypted_bytes   += datalen;
> +
> +out:
> +	return skb;
> +
> +err_out:
> +	dev_kfree_skb_any(skb);
> +	return NULL;
> +}

> diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
> index 5f540db47cc9..539b4d3656da 100644
> --- a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
> +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
> @@ -48,8 +48,15 @@
>  	{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_nop) },
>  
>  #ifdef CONFIG_MLX5_EN_TLS
> +	{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_tls_encrypted_packets) },

As mentioned in the other email could you change this in docs and
the nfp driver (just change the ethtool string)?

> +	{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_tls_encrypted_bytes) },

This one looks like it'd be worth adding to the general doc.
Could you please make it clear this only counts L4 payload data, 
not the full frames?  Also perhaps worth mentioning for the packet
counter that it doesn't count pure acks and other frames with no
playload.

> +	{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_tls_ctx) },

And this one.

>  	{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_tls_ooo) },
>  	{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_tls_resync_bytes) },
> +	{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_tls_drop_no_sync_data) },
> +	{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_tls_drop_bypass_req) },

And this one, too.

> +	{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_tls_dump_packets) },
> +	{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_tls_dump_bytes) },
>  #endif
>  
>  	{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_lro_packets) },
> @@ -271,8 +278,15 @@ static void mlx5e_grp_sw_update_stats(struct mlx5e_priv *priv)
>  			s->tx_csum_none		+= sq_stats->csum_none;
>  			s->tx_csum_partial	+= sq_stats->csum_partial;
>  #ifdef CONFIG_MLX5_EN_TLS
> -			s->tx_tls_ooo		+= sq_stats->tls_ooo;
> -			s->tx_tls_resync_bytes	+= sq_stats->tls_resync_bytes;
> +			s->tx_tls_encrypted_packets += sq_stats->tls_encrypted_packets;
> +			s->tx_tls_encrypted_bytes   += sq_stats->tls_encrypted_bytes;
> +			s->tx_tls_ctx               += sq_stats->tls_ctx;
> +			s->tx_tls_ooo               += sq_stats->tls_ooo;
> +			s->tx_tls_resync_bytes      += sq_stats->tls_resync_bytes;
> +			s->tx_tls_drop_no_sync_data += sq_stats->tls_drop_no_sync_data;
> +			s->tx_tls_drop_bypass_req   += sq_stats->tls_drop_bypass_req;
> +			s->tx_tls_dump_bytes        += sq_stats->tls_dump_bytes;
> +			s->tx_tls_dump_packets      += sq_stats->tls_dump_packets;
>  #endif
>  			s->tx_cqes		+= sq_stats->cqes;
>  		}
> @@ -1293,6 +1307,16 @@ static int mlx5e_grp_tls_fill_stats(struct mlx5e_priv *priv, u64 *data, int idx)
>  	{ MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, csum_partial_inner) },
>  	{ MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, added_vlan_packets) },
>  	{ MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, nop) },
> +#ifdef CONFIG_MLX5_EN_TLS
> +	{ MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, tls_encrypted_packets) },
> +	{ MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, tls_encrypted_bytes) },
> +	{ MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, tls_ctx) },
> +	{ MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, tls_ooo) },
> +	{ MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, tls_drop_no_sync_data) },
> +	{ MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, tls_drop_bypass_req) },
> +	{ MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, tls_dump_packets) },
> +	{ MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, tls_dump_bytes) },
> +#endif
>  	{ MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, csum_none) },
>  	{ MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, stopped) },
>  	{ MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, dropped) },

^ permalink raw reply

* Re: [PATCH] selftests: txring_overwrite: fix incorrect test of mmap() return value
From: Willem de Bruijn @ 2019-07-05 19:55 UTC (permalink / raw)
  To: Frank de Brabander; +Cc: David S . Miller, Network Development
In-Reply-To: <1562326994-4569-1-git-send-email-debrabander@gmail.com>

On Fri, Jul 5, 2019 at 7:44 AM Frank de Brabander <debrabander@gmail.com> wrote:
>
> If mmap() fails it returns MAP_FAILED, which is defined as ((void *) -1).
> The current if-statement incorrectly tests if *ring is NULL.
>
> Signed-off-by: Frank de Brabander <debrabander@gmail.com>

Acked-by: Willem de Bruijn <willemb@google.com>

Fixes: 358be656406d ("selftests/net: add txring_overwrite")

Thanks Frank. Please mark future networking patches as [PATCH net] or
[PATCH net-next].

^ permalink raw reply

* [PATCH net-next v2 8/8] net: mscc: PTP Hardware Clock (PHC) support
From: Antoine Tenart @ 2019-07-05 19:52 UTC (permalink / raw)
  To: davem, richardcochran, alexandre.belloni, UNGLinuxDriver, ralf,
	paul.burton, jhogan
  Cc: Antoine Tenart, netdev, linux-mips, thomas.petazzoni,
	allan.nielsen
In-Reply-To: <20190705195213.22041-1-antoine.tenart@bootlin.com>

This patch adds support for PTP Hardware Clock (PHC) to the Ocelot
switch for both PTP 1-step and 2-step modes.

Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
---
 drivers/net/ethernet/mscc/ocelot.c       | 393 ++++++++++++++++++++++-
 drivers/net/ethernet/mscc/ocelot.h       |  37 +++
 drivers/net/ethernet/mscc/ocelot_board.c | 106 +++++-
 3 files changed, 528 insertions(+), 8 deletions(-)

diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
index b71e4ecbe469..e05f209717e8 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -14,6 +14,7 @@
 #include <linux/module.h>
 #include <linux/netdevice.h>
 #include <linux/phy.h>
+#include <linux/ptp_clock_kernel.h>
 #include <linux/skbuff.h>
 #include <linux/iopoll.h>
 #include <net/arp.h>
@@ -538,7 +539,7 @@ static int ocelot_port_stop(struct net_device *dev)
  */
 static int ocelot_gen_ifh(u32 *ifh, struct frame_info *info)
 {
-	ifh[0] = IFH_INJ_BYPASS;
+	ifh[0] = IFH_INJ_BYPASS | ((0x1ff & info->rew_op) << 21);
 	ifh[1] = (0xf00 & info->port) >> 8;
 	ifh[2] = (0xff & info->port) << 24;
 	ifh[3] = (info->tag_type << 16) | info->vid;
@@ -548,6 +549,7 @@ static int ocelot_gen_ifh(u32 *ifh, struct frame_info *info)
 
 static int ocelot_port_xmit(struct sk_buff *skb, struct net_device *dev)
 {
+	struct skb_shared_info *shinfo = skb_shinfo(skb);
 	struct ocelot_port *port = netdev_priv(dev);
 	struct ocelot *ocelot = port->ocelot;
 	u32 val, ifh[IFH_LEN];
@@ -566,6 +568,14 @@ static int ocelot_port_xmit(struct sk_buff *skb, struct net_device *dev)
 	info.port = BIT(port->chip_port);
 	info.tag_type = IFH_TAG_TYPE_C;
 	info.vid = skb_vlan_tag_get(skb);
+
+	/* Check if timestamping is needed */
+	if (ocelot->ptp && shinfo->tx_flags & SKBTX_HW_TSTAMP) {
+		info.rew_op = port->ptp_cmd;
+		if (port->ptp_cmd == IFH_REW_OP_TWO_STEP_PTP)
+			info.rew_op |= (port->ts_id  % 4) << 3;
+	}
+
 	ocelot_gen_ifh(ifh, &info);
 
 	for (i = 0; i < IFH_LEN; i++)
@@ -596,11 +606,50 @@ static int ocelot_port_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	dev->stats.tx_packets++;
 	dev->stats.tx_bytes += skb->len;
-	dev_kfree_skb_any(skb);
+
+	if (ocelot->ptp && shinfo->tx_flags & SKBTX_HW_TSTAMP &&
+	    port->ptp_cmd == IFH_REW_OP_TWO_STEP_PTP) {
+		struct ocelot_skb *oskb =
+			kzalloc(sizeof(struct ocelot_skb), GFP_KERNEL);
+
+		oskb->skb = skb;
+		oskb->id = port->ts_id % 4;
+		port->ts_id++;
+
+		list_add_tail(&oskb->head, &port->skbs);
+	} else {
+		dev_kfree_skb_any(skb);
+	}
 
 	return NETDEV_TX_OK;
 }
 
+void ocelot_get_hwtimestamp(struct ocelot *ocelot, struct timespec64 *ts)
+{
+	unsigned long flags;
+	u32 val;
+
+	spin_lock_irqsave(&ocelot->ptp_clock_lock, flags);
+
+	/* Read current PTP time to get seconds */
+	val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN);
+
+	val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK | PTP_PIN_CFG_DOM);
+	val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_SAVE);
+	ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN);
+	ts->tv_sec = ocelot_read_rix(ocelot, PTP_PIN_TOD_SEC_LSB, TOD_ACC_PIN);
+
+	/* Read packet HW timestamp from FIFO */
+	val = ocelot_read(ocelot, SYS_PTP_TXSTAMP);
+	ts->tv_nsec = SYS_PTP_TXSTAMP_PTP_TXSTAMP(val);
+
+	/* Sec has incremented since the ts was registered */
+	if ((ts->tv_sec & 0x1) != !!(val & SYS_PTP_TXSTAMP_PTP_TXSTAMP_SEC))
+		ts->tv_sec--;
+
+	spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
+}
+
 static int ocelot_mc_unsync(struct net_device *dev, const unsigned char *addr)
 {
 	struct ocelot_port *port = netdev_priv(dev);
@@ -917,6 +966,97 @@ static int ocelot_get_port_parent_id(struct net_device *dev,
 	return 0;
 }
 
+static int ocelot_hwstamp_get(struct ocelot_port *port, struct ifreq *ifr)
+{
+	struct ocelot *ocelot = port->ocelot;
+
+	return copy_to_user(ifr->ifr_data, &ocelot->hwtstamp_config,
+			    sizeof(ocelot->hwtstamp_config)) ? -EFAULT : 0;
+}
+
+static int ocelot_hwstamp_set(struct ocelot_port *port, struct ifreq *ifr)
+{
+	struct ocelot *ocelot = port->ocelot;
+	struct hwtstamp_config cfg;
+
+	if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg)))
+		return -EFAULT;
+
+	/* reserved for future extensions */
+	if (cfg.flags)
+		return -EINVAL;
+
+	/* Tx type sanity check */
+	switch (cfg.tx_type) {
+	case HWTSTAMP_TX_ON:
+		port->ptp_cmd = IFH_REW_OP_TWO_STEP_PTP;
+		break;
+	case HWTSTAMP_TX_ONESTEP_SYNC:
+		/* IFH_REW_OP_ONE_STEP_PTP updates the correctional field, we
+		 * need to update the origin time.
+		 */
+		port->ptp_cmd = IFH_REW_OP_ORIGIN_PTP;
+		break;
+	case HWTSTAMP_TX_OFF:
+		port->ptp_cmd = 0;
+		break;
+	default:
+		return -ERANGE;
+	}
+
+	mutex_lock(&ocelot->ptp_lock);
+
+	switch (cfg.rx_filter) {
+	case HWTSTAMP_FILTER_NONE:
+		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_NTP_ALL:
+	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:
+		cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
+		break;
+	default:
+		mutex_unlock(&ocelot->ptp_lock);
+		return -ERANGE;
+	}
+
+	/* Commit back the result & save it */
+	memcpy(&ocelot->hwtstamp_config, &cfg, sizeof(cfg));
+	mutex_unlock(&ocelot->ptp_lock);
+
+	return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
+}
+
+static int ocelot_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+	struct ocelot_port *port = netdev_priv(dev);
+	struct ocelot *ocelot = port->ocelot;
+
+	/* The function is only used for PTP operations for now */
+	if (!ocelot->ptp)
+		return -EOPNOTSUPP;
+
+	switch (cmd) {
+	case SIOCSHWTSTAMP:
+		return ocelot_hwstamp_set(port, ifr);
+	case SIOCGHWTSTAMP:
+		return ocelot_hwstamp_get(port, ifr);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
 static const struct net_device_ops ocelot_port_netdev_ops = {
 	.ndo_open			= ocelot_port_open,
 	.ndo_stop			= ocelot_port_stop,
@@ -933,6 +1073,7 @@ static const struct net_device_ops ocelot_port_netdev_ops = {
 	.ndo_set_features		= ocelot_set_features,
 	.ndo_get_port_parent_id		= ocelot_get_port_parent_id,
 	.ndo_setup_tc			= ocelot_setup_tc,
+	.ndo_do_ioctl			= ocelot_ioctl,
 };
 
 static void ocelot_get_strings(struct net_device *netdev, u32 sset, u8 *data)
@@ -1014,12 +1155,42 @@ static int ocelot_get_sset_count(struct net_device *dev, int sset)
 	return ocelot->num_stats;
 }
 
+static int ocelot_get_ts_info(struct net_device *dev,
+			      struct ethtool_ts_info *info)
+{
+	struct ocelot_port *ocelot_port = netdev_priv(dev);
+	struct ocelot *ocelot = ocelot_port->ocelot;
+	int ret;
+
+	if (!ocelot->ptp)
+		return -EOPNOTSUPP;
+
+	ret = ethtool_op_get_ts_info(dev, info);
+	if (ret)
+		return ret;
+
+	info->phc_index = ocelot->ptp_clock ?
+			  ptp_clock_index(ocelot->ptp_clock) : -1;
+	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->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON) |
+			 BIT(HWTSTAMP_TX_ONESTEP_SYNC);
+	info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) | BIT(HWTSTAMP_FILTER_ALL);
+
+	return 0;
+}
+
 static const struct ethtool_ops ocelot_ethtool_ops = {
 	.get_strings		= ocelot_get_strings,
 	.get_ethtool_stats	= ocelot_get_ethtool_stats,
 	.get_sset_count		= ocelot_get_sset_count,
 	.get_link_ksettings	= phy_ethtool_get_link_ksettings,
 	.set_link_ksettings	= phy_ethtool_set_link_ksettings,
+	.get_ts_info		= ocelot_get_ts_info,
 };
 
 static int ocelot_port_attr_stp_state_set(struct ocelot_port *ocelot_port,
@@ -1629,6 +1800,191 @@ struct notifier_block ocelot_switchdev_blocking_nb __read_mostly = {
 };
 EXPORT_SYMBOL(ocelot_switchdev_blocking_nb);
 
+int ocelot_ptp_gettime64(struct ptp_clock_info *ptp, struct timespec64 *ts)
+{
+	struct ocelot *ocelot = container_of(ptp, struct ocelot, ptp_info);
+	unsigned long flags;
+	time64_t s;
+	u32 val;
+	s64 ns;
+
+	spin_lock_irqsave(&ocelot->ptp_clock_lock, flags);
+
+	val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN);
+	val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK | PTP_PIN_CFG_DOM);
+	val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_SAVE);
+	ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN);
+
+	s = ocelot_read_rix(ocelot, PTP_PIN_TOD_SEC_MSB, TOD_ACC_PIN) & 0xffff;
+	s <<= 32;
+	s += ocelot_read_rix(ocelot, PTP_PIN_TOD_SEC_LSB, TOD_ACC_PIN);
+	ns = ocelot_read_rix(ocelot, PTP_PIN_TOD_NSEC, TOD_ACC_PIN);
+
+	spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
+
+	/* Deal with negative values */
+	if (ns >= 0x3ffffff0 && ns <= 0x3fffffff) {
+		s--;
+		ns &= 0xf;
+		ns += 999999984;
+	}
+
+	set_normalized_timespec64(ts, s, ns);
+	return 0;
+}
+
+static int ocelot_ptp_settime64(struct ptp_clock_info *ptp,
+				const struct timespec64 *ts)
+{
+	struct ocelot *ocelot = container_of(ptp, struct ocelot, ptp_info);
+	unsigned long flags;
+	u32 val;
+
+	spin_lock_irqsave(&ocelot->ptp_clock_lock, flags);
+
+	val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN);
+	val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK | PTP_PIN_CFG_DOM);
+	val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_IDLE);
+
+	ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN);
+
+	ocelot_write_rix(ocelot, lower_32_bits(ts->tv_sec), PTP_PIN_TOD_SEC_LSB,
+			 TOD_ACC_PIN);
+	ocelot_write_rix(ocelot, upper_32_bits(ts->tv_sec), PTP_PIN_TOD_SEC_MSB,
+			 TOD_ACC_PIN);
+	ocelot_write_rix(ocelot, ts->tv_nsec, PTP_PIN_TOD_NSEC, TOD_ACC_PIN);
+
+	val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN);
+	val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK | PTP_PIN_CFG_DOM);
+	val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_LOAD);
+
+	ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN);
+
+	spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
+	return 0;
+}
+
+static int ocelot_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
+{
+	if (delta > -(NSEC_PER_SEC / 2) && delta < (NSEC_PER_SEC / 2)) {
+		struct ocelot *ocelot = container_of(ptp, struct ocelot, ptp_info);
+		unsigned long flags;
+		u32 val;
+
+		spin_lock_irqsave(&ocelot->ptp_clock_lock, flags);
+
+		val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN);
+		val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK | PTP_PIN_CFG_DOM);
+		val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_IDLE);
+
+		ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN);
+
+		ocelot_write_rix(ocelot, 0, PTP_PIN_TOD_SEC_LSB, TOD_ACC_PIN);
+		ocelot_write_rix(ocelot, 0, PTP_PIN_TOD_SEC_MSB, TOD_ACC_PIN);
+		ocelot_write_rix(ocelot, delta, PTP_PIN_TOD_NSEC, TOD_ACC_PIN);
+
+		val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN);
+		val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK | PTP_PIN_CFG_DOM);
+		val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_DELTA);
+
+		ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN);
+
+		spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
+	} else {
+		/* Fall back using ocelot_ptp_settime64 which is not exact. */
+		struct timespec64 ts;
+		u64 now;
+
+		ocelot_ptp_gettime64(ptp, &ts);
+
+		now = ktime_to_ns(timespec64_to_ktime(ts));
+		ts = ns_to_timespec64(now + delta);
+
+		ocelot_ptp_settime64(ptp, &ts);
+	}
+	return 0;
+}
+
+static int ocelot_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
+{
+	struct ocelot *ocelot = container_of(ptp, struct ocelot, ptp_info);
+	u32 unit = 0, direction = 0;
+	unsigned long flags;
+	u64 adj = 0;
+
+	if (!scaled_ppm)
+		goto disable_adj;
+
+	if (scaled_ppm < 0) {
+		direction = PTP_CFG_CLK_ADJ_CFG_DIR;
+		scaled_ppm = -scaled_ppm;
+	}
+
+	adj = PSEC_PER_SEC << 16;
+	do_div(adj, scaled_ppm);
+	do_div(adj, 1000);
+
+	/* If the adjustment value is too large, use ns instead */
+	if (adj >= (1L << 30)) {
+		unit = PTP_CFG_CLK_ADJ_FREQ_NS;
+		do_div(adj, 1000);
+	}
+
+	spin_lock_irqsave(&ocelot->ptp_clock_lock, flags);
+
+	/* Still too big */
+	if (adj >= (1L << 30))
+		goto disable_adj;
+
+	ocelot_write(ocelot, unit | adj, PTP_CLK_CFG_ADJ_FREQ);
+	ocelot_write(ocelot, PTP_CFG_CLK_ADJ_CFG_ENA | direction,
+		     PTP_CLK_CFG_ADJ_CFG);
+
+	spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
+	return 0;
+
+disable_adj:
+	ocelot_write(ocelot, 0, PTP_CLK_CFG_ADJ_CFG);
+
+	spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
+	return 0;
+}
+
+static struct ptp_clock_info ocelot_ptp_clock_info = {
+	.owner		= THIS_MODULE,
+	.name		= "ocelot ptp",
+	.max_adj	= 0x7fffffff,
+	.n_alarm	= 0,
+	.n_ext_ts	= 0,
+	.n_per_out	= 0,
+	.n_pins		= 0,
+	.pps		= 0,
+	.gettime64	= ocelot_ptp_gettime64,
+	.settime64	= ocelot_ptp_settime64,
+	.adjtime	= ocelot_ptp_adjtime,
+	.adjfine	= ocelot_ptp_adjfine,
+};
+
+static int ocelot_init_timestamp(struct ocelot *ocelot)
+{
+	ocelot->ptp_info = ocelot_ptp_clock_info;
+
+	ocelot->ptp_clock = ptp_clock_register(&ocelot->ptp_info, ocelot->dev);
+	if (IS_ERR(ocelot->ptp_clock))
+		return PTR_ERR(ocelot->ptp_clock);
+	/* Check if PHC support is missing at the configuration level */
+	if (!ocelot->ptp_clock)
+		return 0;
+
+	ocelot_write(ocelot, SYS_PTP_CFG_PTP_STAMP_WID(30), SYS_PTP_CFG);
+	ocelot_write(ocelot, 0xffffffff, ANA_TABLES_PTP_ID_LOW);
+	ocelot_write(ocelot, 0xffffffff, ANA_TABLES_PTP_ID_HIGH);
+
+	ocelot_write(ocelot, PTP_CFG_MISC_PTP_EN, PTP_CFG_MISC);
+
+	return 0;
+}
+
 int ocelot_probe_port(struct ocelot *ocelot, u8 port,
 		      void __iomem *regs,
 		      struct phy_device *phy)
@@ -1661,6 +2017,8 @@ int ocelot_probe_port(struct ocelot *ocelot, u8 port,
 	ocelot_mact_learn(ocelot, PGID_CPU, dev->dev_addr, ocelot_port->pvid,
 			  ENTRYTYPE_LOCKED);
 
+	INIT_LIST_HEAD(&ocelot_port->skbs);
+
 	err = register_netdev(dev);
 	if (err) {
 		dev_err(ocelot->dev, "register_netdev failed\n");
@@ -1684,7 +2042,7 @@ EXPORT_SYMBOL(ocelot_probe_port);
 int ocelot_init(struct ocelot *ocelot)
 {
 	u32 port;
-	int i, cpu = ocelot->num_phys_ports;
+	int i, ret, cpu = ocelot->num_phys_ports;
 	char queue_name[32];
 
 	ocelot->lags = devm_kcalloc(ocelot->dev, ocelot->num_phys_ports,
@@ -1699,6 +2057,8 @@ int ocelot_init(struct ocelot *ocelot)
 		return -ENOMEM;
 
 	mutex_init(&ocelot->stats_lock);
+	mutex_init(&ocelot->ptp_lock);
+	spin_lock_init(&ocelot->ptp_clock_lock);
 	snprintf(queue_name, sizeof(queue_name), "%s-stats",
 		 dev_name(ocelot->dev));
 	ocelot->stats_queue = create_singlethread_workqueue(queue_name);
@@ -1812,15 +2172,42 @@ int ocelot_init(struct ocelot *ocelot)
 	INIT_DELAYED_WORK(&ocelot->stats_work, ocelot_check_stats_work);
 	queue_delayed_work(ocelot->stats_queue, &ocelot->stats_work,
 			   OCELOT_STATS_CHECK_DELAY);
+
+	if (ocelot->ptp) {
+		ret = ocelot_init_timestamp(ocelot);
+		if (ret) {
+			dev_err(ocelot->dev,
+				"Timestamp initialization failed\n");
+			return ret;
+		}
+	}
+
 	return 0;
 }
 EXPORT_SYMBOL(ocelot_init);
 
 void ocelot_deinit(struct ocelot *ocelot)
 {
+	struct list_head *pos, *tmp;
+	struct ocelot_port *port;
+	struct ocelot_skb *entry;
+	int i;
+
 	destroy_workqueue(ocelot->stats_queue);
 	mutex_destroy(&ocelot->stats_lock);
 	ocelot_ace_deinit();
+
+	for (i = 0; i < ocelot->num_phys_ports; i++) {
+		port = ocelot->ports[i];
+
+		list_for_each_safe(pos, tmp, &port->skbs) {
+			entry = list_entry(pos, struct ocelot_skb, head);
+
+			list_del(pos);
+			dev_kfree_skb_any(entry->skb);
+			kfree(entry);
+		}
+	}
 }
 EXPORT_SYMBOL(ocelot_deinit);
 
diff --git a/drivers/net/ethernet/mscc/ocelot.h b/drivers/net/ethernet/mscc/ocelot.h
index 515dee6fa8a6..bad4b6bbdc32 100644
--- a/drivers/net/ethernet/mscc/ocelot.h
+++ b/drivers/net/ethernet/mscc/ocelot.h
@@ -11,9 +11,11 @@
 #include <linux/bitops.h>
 #include <linux/etherdevice.h>
 #include <linux/if_vlan.h>
+#include <linux/net_tstamp.h>
 #include <linux/phy.h>
 #include <linux/phy/phy.h>
 #include <linux/platform_device.h>
+#include <linux/ptp_clock_kernel.h>
 #include <linux/regmap.h>
 
 #include "ocelot_ana.h"
@@ -46,6 +48,8 @@ struct frame_info {
 	u16 port;
 	u16 vid;
 	u8 tag_type;
+	u16 rew_op;
+	u32 timestamp;	/* rew_val */
 };
 
 #define IFH_INJ_BYPASS	BIT(31)
@@ -54,6 +58,12 @@ struct frame_info {
 #define IFH_TAG_TYPE_C 0
 #define IFH_TAG_TYPE_S 1
 
+#define IFH_REW_OP_NOOP			0x0
+#define IFH_REW_OP_DSCP			0x1
+#define IFH_REW_OP_ONE_STEP_PTP		0x2
+#define IFH_REW_OP_TWO_STEP_PTP		0x3
+#define IFH_REW_OP_ORIGIN_PTP		0x5
+
 #define OCELOT_SPEED_2500 0
 #define OCELOT_SPEED_1000 1
 #define OCELOT_SPEED_100  2
@@ -401,6 +411,13 @@ enum ocelot_regfield {
 	REGFIELD_MAX
 };
 
+enum ocelot_clk_pins {
+	ALT_PPS_PIN	= 1,
+	EXT_CLK_PIN,
+	ALT_LDST_PIN,
+	TOD_ACC_PIN
+};
+
 struct ocelot_multicast {
 	struct list_head list;
 	unsigned char addr[ETH_ALEN];
@@ -450,6 +467,13 @@ struct ocelot {
 	u64 *stats;
 	struct delayed_work stats_work;
 	struct workqueue_struct *stats_queue;
+
+	u8 ptp:1;
+	struct ptp_clock *ptp_clock;
+	struct ptp_clock_info ptp_info;
+	struct hwtstamp_config hwtstamp_config;
+	struct mutex ptp_lock; /* Protects the PTP interface state */
+	spinlock_t ptp_clock_lock; /* Protects the PTP clock */
 };
 
 struct ocelot_port {
@@ -473,6 +497,16 @@ struct ocelot_port {
 	struct phy *serdes;
 
 	struct ocelot_port_tc tc;
+
+	u8 ptp_cmd;
+	struct list_head skbs;
+	u8 ts_id;
+};
+
+struct ocelot_skb {
+	struct list_head head;
+	struct sk_buff *skb;
+	u8 id;
 };
 
 u32 __ocelot_read_ix(struct ocelot *ocelot, u32 reg, u32 offset);
@@ -517,4 +551,7 @@ extern struct notifier_block ocelot_netdevice_nb;
 extern struct notifier_block ocelot_switchdev_nb;
 extern struct notifier_block ocelot_switchdev_blocking_nb;
 
+int ocelot_ptp_gettime64(struct ptp_clock_info *ptp, struct timespec64 *ts);
+void ocelot_get_hwtimestamp(struct ocelot *ocelot, struct timespec64 *ts);
+
 #endif
diff --git a/drivers/net/ethernet/mscc/ocelot_board.c b/drivers/net/ethernet/mscc/ocelot_board.c
index 008a762512b9..2e7e5944a7b0 100644
--- a/drivers/net/ethernet/mscc/ocelot_board.c
+++ b/drivers/net/ethernet/mscc/ocelot_board.c
@@ -31,6 +31,8 @@ static int ocelot_parse_ifh(u32 *_ifh, struct frame_info *info)
 
 	info->len = OCELOT_BUFFER_CELL_SZ * wlen + llen - 80;
 
+	info->timestamp = IFH_EXTRACT_BITFIELD64(ifh[0], 21, 32);
+
 	info->port = IFH_EXTRACT_BITFIELD64(ifh[1], 43, 4);
 
 	info->tag_type = IFH_EXTRACT_BITFIELD64(ifh[1], 16,  1);
@@ -98,7 +100,11 @@ static irqreturn_t ocelot_xtr_irq_handler(int irq, void *arg)
 		int sz, len, buf_len;
 		u32 ifh[4];
 		u32 val;
-		struct frame_info info;
+		struct frame_info info = {};
+		struct timespec64 ts;
+		struct skb_shared_hwtstamps *shhwtstamps;
+		u64 tod_in_ns;
+		u64 full_ts_in_ns;
 
 		for (i = 0; i < IFH_LEN; i++) {
 			err = ocelot_rx_frame_word(ocelot, grp, true, &ifh[i]);
@@ -145,6 +151,22 @@ static irqreturn_t ocelot_xtr_irq_handler(int irq, void *arg)
 			break;
 		}
 
+		if (ocelot->ptp) {
+			ocelot_ptp_gettime64(&ocelot->ptp_info, &ts);
+
+			tod_in_ns = ktime_set(ts.tv_sec, ts.tv_nsec);
+			if ((tod_in_ns & 0xffffffff) < info.timestamp)
+				full_ts_in_ns = (((tod_in_ns >> 32) - 1) << 32) |
+						info.timestamp;
+			else
+				full_ts_in_ns = (tod_in_ns & GENMASK_ULL(63, 32)) |
+						info.timestamp;
+
+			shhwtstamps = skb_hwtstamps(skb);
+			memset(shhwtstamps, 0, sizeof(struct skb_shared_hwtstamps));
+			shhwtstamps->hwtstamp = full_ts_in_ns;
+		}
+
 		/* Everything we see on an interface that is in the HW bridge
 		 * has already been forwarded.
 		 */
@@ -164,6 +186,65 @@ static irqreturn_t ocelot_xtr_irq_handler(int irq, void *arg)
 	return IRQ_HANDLED;
 }
 
+static irqreturn_t ocelot_ptp_rdy_irq_handler(int irq, void *arg)
+{
+	struct ocelot *ocelot = arg;
+
+	do {
+		struct skb_shared_hwtstamps shhwtstamps;
+		struct list_head *pos, *tmp;
+		struct sk_buff *skb = NULL;
+		struct ocelot_skb *entry;
+		struct ocelot_port *port;
+		struct timespec64 ts;
+		u32 val, id, txport;
+
+		val = ocelot_read(ocelot, SYS_PTP_STATUS);
+
+		/* Check if a timestamp can be retrieved */
+		if (!(val & SYS_PTP_STATUS_PTP_MESS_VLD))
+			break;
+
+		WARN_ON(val & SYS_PTP_STATUS_PTP_OVFL);
+
+		/* Retrieve the ts ID and Tx port */
+		id = SYS_PTP_STATUS_PTP_MESS_ID_X(val);
+		txport = SYS_PTP_STATUS_PTP_MESS_TXPORT_X(val);
+
+		/* Retrieve its associated skb */
+		port = ocelot->ports[txport];
+
+		list_for_each_safe(pos, tmp, &port->skbs) {
+			entry = list_entry(pos, struct ocelot_skb, head);
+			if (entry->id != id)
+				continue;
+
+			skb = entry->skb;
+
+			list_del(pos);
+			kfree(entry);
+		}
+
+		/* Next ts */
+		ocelot_write(ocelot, SYS_PTP_NXT_PTP_NXT, SYS_PTP_NXT);
+
+		if (unlikely(!skb))
+			continue;
+
+		/* Get the h/w timestamp */
+		ocelot_get_hwtimestamp(ocelot, &ts);
+
+		/* Set the timestamp into the skb */
+		memset(&shhwtstamps, 0, sizeof(shhwtstamps));
+		shhwtstamps.hwtstamp = ktime_set(ts.tv_sec, ts.tv_nsec);
+		skb_tstamp_tx(skb, &shhwtstamps);
+
+		dev_kfree_skb_any(skb);
+	} while (true);
+
+	return IRQ_HANDLED;
+}
+
 static const struct of_device_id mscc_ocelot_match[] = {
 	{ .compatible = "mscc,vsc7514-switch" },
 	{ }
@@ -172,8 +253,8 @@ MODULE_DEVICE_TABLE(of, mscc_ocelot_match);
 
 static int mscc_ocelot_probe(struct platform_device *pdev)
 {
-	int err, irq;
 	unsigned int i;
+	int err, irq_xtr, irq_ptp_rdy;
 	struct device_node *np = pdev->dev.of_node;
 	struct device_node *ports, *portnp;
 	struct ocelot *ocelot;
@@ -232,16 +313,31 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
 	if (err)
 		return err;
 
-	irq = platform_get_irq_byname(pdev, "xtr");
-	if (irq < 0)
+	irq_xtr = platform_get_irq_byname(pdev, "xtr");
+	if (irq_xtr < 0)
 		return -ENODEV;
 
-	err = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+	err = devm_request_threaded_irq(&pdev->dev, irq_xtr, NULL,
 					ocelot_xtr_irq_handler, IRQF_ONESHOT,
 					"frame extraction", ocelot);
 	if (err)
 		return err;
 
+
+	irq_ptp_rdy = platform_get_irq_byname(pdev, "ptp_rdy");
+	if (irq_ptp_rdy > 0) {
+		err = devm_request_threaded_irq(&pdev->dev, irq_ptp_rdy, NULL,
+						ocelot_ptp_rdy_irq_handler,
+						IRQF_ONESHOT, "ptp ready",
+						ocelot);
+		if (err)
+			return err;
+
+		/* Check if we can support PTP */
+		if (ocelot->targets[PTP])
+			ocelot->ptp = 1;
+	}
+
 	regmap_field_write(ocelot->regfields[SYS_RESET_CFG_MEM_INIT], 1);
 	regmap_field_write(ocelot->regfields[SYS_RESET_CFG_MEM_ENA], 1);
 
-- 
2.21.0


^ permalink raw reply related

* [PATCH net-next v2 7/8] net: mscc: remove the frame_info cpuq member
From: Antoine Tenart @ 2019-07-05 19:52 UTC (permalink / raw)
  To: davem, richardcochran, alexandre.belloni, UNGLinuxDriver, ralf,
	paul.burton, jhogan
  Cc: Antoine Tenart, netdev, linux-mips, thomas.petazzoni,
	allan.nielsen
In-Reply-To: <20190705195213.22041-1-antoine.tenart@bootlin.com>

In struct frame_info, the cpuq member is never used. This cosmetic patch
removes it from the structure, and from the parsing of the frame header
as it's only set but never used.

Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
---
 drivers/net/ethernet/mscc/ocelot.h       | 1 -
 drivers/net/ethernet/mscc/ocelot_board.c | 1 -
 2 files changed, 2 deletions(-)

diff --git a/drivers/net/ethernet/mscc/ocelot.h b/drivers/net/ethernet/mscc/ocelot.h
index e0da8b4eddf2..515dee6fa8a6 100644
--- a/drivers/net/ethernet/mscc/ocelot.h
+++ b/drivers/net/ethernet/mscc/ocelot.h
@@ -45,7 +45,6 @@ struct frame_info {
 	u32 len;
 	u16 port;
 	u16 vid;
-	u8 cpuq;
 	u8 tag_type;
 };
 
diff --git a/drivers/net/ethernet/mscc/ocelot_board.c b/drivers/net/ethernet/mscc/ocelot_board.c
index 09ad6a123347..008a762512b9 100644
--- a/drivers/net/ethernet/mscc/ocelot_board.c
+++ b/drivers/net/ethernet/mscc/ocelot_board.c
@@ -33,7 +33,6 @@ static int ocelot_parse_ifh(u32 *_ifh, struct frame_info *info)
 
 	info->port = IFH_EXTRACT_BITFIELD64(ifh[1], 43, 4);
 
-	info->cpuq = IFH_EXTRACT_BITFIELD64(ifh[1], 20, 8);
 	info->tag_type = IFH_EXTRACT_BITFIELD64(ifh[1], 16,  1);
 	info->vid = IFH_EXTRACT_BITFIELD64(ifh[1], 0,  12);
 
-- 
2.21.0


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox