Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH net-next 1/3] net: dsa: add support for bridge flags
From: Florian Fainelli @ 2019-02-17 22:07 UTC (permalink / raw)
  To: Russell King - ARM Linux admin
  Cc: Andrew Lunn, Vivien Didelot, David S. Miller, netdev
In-Reply-To: <20190217220439.zqu7dz7kfukssrlz@shell.armlinux.org.uk>



On 2/17/2019 2:04 PM, Russell King - ARM Linux admin wrote:
> On Sun, Feb 17, 2019 at 01:37:19PM -0800, Florian Fainelli wrote:
>>
>>
>> On 2/17/2019 6:25 AM, Russell King wrote:
>>> The Linux bridge implementation allows various properties of the bridge
>>> to be controlled, such as flooding unknown unicast and multicast frames.
>>> This patch adds the necessary DSA infrastructure to allow the Linux
>>> bridge support to control these properties for DSA switches.
>>>
>>> We implement this by providing two new methods: one to get the switch-
>>> wide support bitmask, and another to set the properties.
>>>
>>> Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
>>> ---
>>
>> [snip]
>>
>>>  
>>> +int dsa_port_bridge_flags(const struct dsa_port *dp, unsigned long flags,
>>> +			  struct switchdev_trans *trans)
>>> +{
>>> +	struct dsa_switch *ds = dp->ds;
>>> +	int port = dp->index;
>>> +
>>> +	if (switchdev_trans_ph_prepare(trans))
>>> +		return ds->ops->port_bridge_flags ? 0 : -EOPNOTSUPP;
>>> +
>>> +	if (ds->ops->port_bridge_flags)
>>> +		ds->ops->port_bridge_flags(ds, port, flags);
>>
>> If you have a switch fabric with multiple switches, it seems to me that
>> you also need to make sure that the DSA and CPU ports will have
>> compatible flooding attribute, so just like the port_vlan_add()
>> callback, you probably need to make this a switch fabric-wide event and
>> use a notifier here. At least the DSA ports need to have MC flooding
>> turned on for an user port to also have MC flooding working.
> 
> mv88e6xxx already today detects CPU and DSA ports and sets unicast
> and multicast flooding for these ports - see
> mv88e6xxx_setup_egress_floods():

Indeed, probably for historical reasons, since that type of logic should
ideally be migrated to the core DSA layer, this is fine for now though.

> 
>         /* Upstream ports flood frames with unknown unicast or multicast DA */
>         flood = dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port);
>         if (chip->info->ops->port_set_egress_floods)
>                 return chip->info->ops->port_set_egress_floods(chip, port,
>                                                                flood, flood);
> 

-- 
Florian

^ permalink raw reply

* Re: [PATCH net-next 3/3] net: dsa: mv88e6xxx: defautl to multicast and unicast flooding
From: Russell King - ARM Linux admin @ 2019-02-17 22:19 UTC (permalink / raw)
  To: Florian Fainelli; +Cc: Andrew Lunn, Vivien Didelot, David S. Miller, netdev
In-Reply-To: <39dbb59c-0c67-95f8-6703-d3e628d8c50e@gmail.com>

On Sun, Feb 17, 2019 at 02:03:40PM -0800, Florian Fainelli wrote:
> 
> 
> On 2/17/2019 1:58 PM, Russell King - ARM Linux admin wrote:
> > On Sun, Feb 17, 2019 at 01:45:24PM -0800, Florian Fainelli wrote:
> >>
> >>
> >> On 2/17/2019 8:34 AM, Russell King - ARM Linux admin wrote:
> >>> On Sun, Feb 17, 2019 at 02:27:16PM +0000, Russell King - ARM Linux admin wrote:
> >>>> On Sun, Feb 17, 2019 at 02:25:17PM +0000, Russell King wrote:
> >>>>> Switches work by learning the MAC address for each attached station by
> >>>>> monitoring traffic from each station.  When a station sends a packet,
> >>>>> the switch records which port the MAC address is connected to.
> >>>>>
> >>>>> With IPv4 networking, before communication commences with a neighbour,
> >>>>> an ARP packet is broadcasted to all stations asking for the MAC address
> >>>>> corresponding with the IPv4.  The desired station responds with an ARP
> >>>>> reply, and the ARP reply causes the switch to learn which port the
> >>>>> station is connected to.
> >>>>>
> >>>>> With IPv6 networking, the situation is rather different.  Rather than
> >>>>> broadcasting ARP packets, a "neighbour solicitation" is multicasted
> >>>>> rather than broadcasted.  This multicast needs to reach the intended
> >>>>> station in order for the neighbour to be discovered.
> >>>>>
> >>>>> Once a neighbour has been discovered, and entered into the sending
> >>>>> stations neighbour cache, communication can restart at a point later
> >>>>> without sending a new neighbour solicitation, even if the entry in
> >>>>> the neighbour cache is marked as stale.  This can be after the MAC
> >>>>> address has expired from the forwarding cache of the DSA switch -
> >>>>> when that occurs, there is a long pause in communication.
> >>>>>
> >>>>> Our DSA implementation for mv88e6xxx switches has defaulted to having
> >>>>> multicast and unicast flooding disabled.  As per the above description,
> >>>>> this is fine for IPv4 networking, since the broadcasted ARP queries
> >>>>> will be sent to and received by all stations on the same network.
> >>>>> However, this breaks IPv6 very badly - blocking neighbour solicitations
> >>>>> and later causing connections to stall.
> >>>>>
> >>>>> The defaults that the Linux bridge code expect from bridges are that
> >>>>> unknown unicast frames and unknown multicast frames are flooded to
> >>>>> all stations, which is at odds to the defaults adopted by our DSA
> >>>>> implementation for mv88e6xxx switches.
> >>>>>
> >>>>> This commit enables by default flooding of both unknown unicast and
> >>>>> unknown multicast frames.  This means that mv88e6xxx DSA switches now
> >>>>> behave as per the bridge(8) man page, and IPv6 works flawlessly through
> >>>>> such a switch.
> >>>>
> >>>> Note that there is the open question whether this affects the case where
> >>>> each port is used as a separate network interface: that case has not yet
> >>>> been tested.
> >>>
> >>> I've checked with a mv88e6131 on the clearfog gt8k board.  lan1
> >>> connected to my lan with plenty of traffic on, and configured as
> >>> part of a bridge.  lan2 connected to the zii board, but not part
> >>> of the bridge.  Monitoring lan2 from the zii board shows no traffic
> >>> that was received from lan1.
> >>>
> >>> So it looks fine.
> >>
> >> With the current state whereby we do not have the necessary hooks to
> >> perform filtering on non-bridged/standalone ports, this is entirely fine
> >> indeed.
> >>
> >> In the future this is part of something I want to address because it is
> >> IMHO highly undesirable to have non-bridged ports be flooded with
> >> unknown multicast or unknown unicast for that matter because that makes
> >> them deviate from a standard NIC interface. Unknown unicast is not
> >> necessarily a low hanging fruit, but still, if we have switches capable
> >> of filtering, we might as well make use of that. Of course, one
> >> difficulty is that we must not break running tcpdump on those DSA slave
> >> network interfaces.
> > 
> > Sorry, I think you have the wrong end of the stick.
> > 
> > For a non-bridged port, I am seeing _no_ traffic apart from that
> > explicitly sent out through that port.  In other words, there are
> > _no_ flooded frames coming out of the non-bridged port.
> > 
> > This patch appears to have no material effect on non-bridged ports.
> 
> Presumably because that non-bridged port and the CPU port are part of
> the same domain with only those 2 ports and that is what we want.
> 
> Now what happens if say you have a station that sends multicast traffic
> through that port to e.g.: 226.94.1.1, I bet that port happily sends
> that multicast traffic to the CPU port with no filtering what so ever
> and this ends-up being dropped in the network stack because there is a
> socket look up failure there. IMHO unless you have a receiver/server on
> that network interface on the DSA network interface and a matching
> socket you should not be receiving that multicast traffic and the switch
> should be filtering it. Since the network stack will call into
> ndo_set_rx_mode() for those cases, we really just need to make that
> multicast traffic known, instead of unknown to the switch.

If the port is not bridged, then it's operating as network interface,
and traffic to/from that port needs to be routed to the CPU port so
that it appears as it would do from a real network interface.
Doing anything else makes breaks the idea that you can use a set
of DSA ports as individual interfaces and run anything but IPv4
non-multicast over them.

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 12.1Mbps down 622kbps up
According to speedtest.net: 11.9Mbps down 500kbps up

^ permalink raw reply

* Re: [PATCH net-next 3/3] net: dsa: mv88e6xxx: defautl to multicast and unicast flooding
From: Florian Fainelli @ 2019-02-17 22:30 UTC (permalink / raw)
  To: Russell King - ARM Linux admin
  Cc: Andrew Lunn, Vivien Didelot, David S. Miller, netdev
In-Reply-To: <20190217221927.5efgzd5buy6e4sg3@shell.armlinux.org.uk>



On 2/17/2019 2:19 PM, Russell King - ARM Linux admin wrote:
> On Sun, Feb 17, 2019 at 02:03:40PM -0800, Florian Fainelli wrote:
>>
>>
>> On 2/17/2019 1:58 PM, Russell King - ARM Linux admin wrote:
>>> On Sun, Feb 17, 2019 at 01:45:24PM -0800, Florian Fainelli wrote:
>>>>
>>>>
>>>> On 2/17/2019 8:34 AM, Russell King - ARM Linux admin wrote:
>>>>> On Sun, Feb 17, 2019 at 02:27:16PM +0000, Russell King - ARM Linux admin wrote:
>>>>>> On Sun, Feb 17, 2019 at 02:25:17PM +0000, Russell King wrote:
>>>>>>> Switches work by learning the MAC address for each attached station by
>>>>>>> monitoring traffic from each station.  When a station sends a packet,
>>>>>>> the switch records which port the MAC address is connected to.
>>>>>>>
>>>>>>> With IPv4 networking, before communication commences with a neighbour,
>>>>>>> an ARP packet is broadcasted to all stations asking for the MAC address
>>>>>>> corresponding with the IPv4.  The desired station responds with an ARP
>>>>>>> reply, and the ARP reply causes the switch to learn which port the
>>>>>>> station is connected to.
>>>>>>>
>>>>>>> With IPv6 networking, the situation is rather different.  Rather than
>>>>>>> broadcasting ARP packets, a "neighbour solicitation" is multicasted
>>>>>>> rather than broadcasted.  This multicast needs to reach the intended
>>>>>>> station in order for the neighbour to be discovered.
>>>>>>>
>>>>>>> Once a neighbour has been discovered, and entered into the sending
>>>>>>> stations neighbour cache, communication can restart at a point later
>>>>>>> without sending a new neighbour solicitation, even if the entry in
>>>>>>> the neighbour cache is marked as stale.  This can be after the MAC
>>>>>>> address has expired from the forwarding cache of the DSA switch -
>>>>>>> when that occurs, there is a long pause in communication.
>>>>>>>
>>>>>>> Our DSA implementation for mv88e6xxx switches has defaulted to having
>>>>>>> multicast and unicast flooding disabled.  As per the above description,
>>>>>>> this is fine for IPv4 networking, since the broadcasted ARP queries
>>>>>>> will be sent to and received by all stations on the same network.
>>>>>>> However, this breaks IPv6 very badly - blocking neighbour solicitations
>>>>>>> and later causing connections to stall.
>>>>>>>
>>>>>>> The defaults that the Linux bridge code expect from bridges are that
>>>>>>> unknown unicast frames and unknown multicast frames are flooded to
>>>>>>> all stations, which is at odds to the defaults adopted by our DSA
>>>>>>> implementation for mv88e6xxx switches.
>>>>>>>
>>>>>>> This commit enables by default flooding of both unknown unicast and
>>>>>>> unknown multicast frames.  This means that mv88e6xxx DSA switches now
>>>>>>> behave as per the bridge(8) man page, and IPv6 works flawlessly through
>>>>>>> such a switch.
>>>>>>
>>>>>> Note that there is the open question whether this affects the case where
>>>>>> each port is used as a separate network interface: that case has not yet
>>>>>> been tested.
>>>>>
>>>>> I've checked with a mv88e6131 on the clearfog gt8k board.  lan1
>>>>> connected to my lan with plenty of traffic on, and configured as
>>>>> part of a bridge.  lan2 connected to the zii board, but not part
>>>>> of the bridge.  Monitoring lan2 from the zii board shows no traffic
>>>>> that was received from lan1.
>>>>>
>>>>> So it looks fine.
>>>>
>>>> With the current state whereby we do not have the necessary hooks to
>>>> perform filtering on non-bridged/standalone ports, this is entirely fine
>>>> indeed.
>>>>
>>>> In the future this is part of something I want to address because it is
>>>> IMHO highly undesirable to have non-bridged ports be flooded with
>>>> unknown multicast or unknown unicast for that matter because that makes
>>>> them deviate from a standard NIC interface. Unknown unicast is not
>>>> necessarily a low hanging fruit, but still, if we have switches capable
>>>> of filtering, we might as well make use of that. Of course, one
>>>> difficulty is that we must not break running tcpdump on those DSA slave
>>>> network interfaces.
>>>
>>> Sorry, I think you have the wrong end of the stick.
>>>
>>> For a non-bridged port, I am seeing _no_ traffic apart from that
>>> explicitly sent out through that port.  In other words, there are
>>> _no_ flooded frames coming out of the non-bridged port.
>>>
>>> This patch appears to have no material effect on non-bridged ports.
>>
>> Presumably because that non-bridged port and the CPU port are part of
>> the same domain with only those 2 ports and that is what we want.
>>
>> Now what happens if say you have a station that sends multicast traffic
>> through that port to e.g.: 226.94.1.1, I bet that port happily sends
>> that multicast traffic to the CPU port with no filtering what so ever
>> and this ends-up being dropped in the network stack because there is a
>> socket look up failure there. IMHO unless you have a receiver/server on
>> that network interface on the DSA network interface and a matching
>> socket you should not be receiving that multicast traffic and the switch
>> should be filtering it. Since the network stack will call into
>> ndo_set_rx_mode() for those cases, we really just need to make that
>> multicast traffic known, instead of unknown to the switch.
> 
> If the port is not bridged, then it's operating as network interface,
> and traffic to/from that port needs to be routed to the CPU port so
> that it appears as it would do from a real network interface.
> Doing anything else makes breaks the idea that you can use a set
> of DSA ports as individual interfaces and run anything but IPv4
> non-multicast over them.

I am not proposing changing any of that just making use of the switch's
ability to snoop management traffic (ARP, DHCP, MLD, etc.) and use of
the network stack's hints in order to avoid flooding unknown multicast.
This is starting to diverge a little bit from the original issue though.
-- 
Florian

^ permalink raw reply

* Re: [BUG] [FIX] net: dsa: oops in br_vlan_enabled
From: Florian Fainelli @ 2019-02-17 22:38 UTC (permalink / raw)
  To: Frank Wunderlich, netdev, andrew, Vivien Didelot
In-Reply-To: <trinity-1108d2b6-42f0-4770-b561-6a66804f210a-1550430319767@3c-app-gmx-bs61>



On 2/17/2019 11:05 AM, Frank Wunderlich wrote:
> Hi Florian
> 
> a user from Bananapi-forum has reported the oops and i had reproduced this and patched out this oops.
> That means not that vlan in bridge works, only no crash.
> 
> my kernel only conatins the second gmac dsa-patches for mt7530/bpi-r2 i've posted at the end of last year, but the oops also occur without them.
> 
> have not changed bridge vlan-configuration by
> 
> echo 1 > /sys/class/net/bridge_name/bridge/vlan_filtering
> 
> maybe that vlan-objects/configuration is not passed through, but there should happen no oops.
> 
> kernel-source is here: https://github.com/frank-w/BPI-R2-4.14/tree/4.19-main
> 
> ps: please take me in CC so i can answer directly

You were in the To: of my previous reply, let's move it back there since
it has all context.
-- 
Florian

^ permalink raw reply

* [PATCH] lib/test_rhashtable: fix spelling mistake "existant" -> "existent"
From: Colin King @ 2019-02-17 22:52 UTC (permalink / raw)
  To: Thomas Graf, Herbert Xu, netdev; +Cc: kernel-janitors, linux-kernel

From: Colin Ian King <colin.king@canonical.com>

There are spelling mistakes in warning macro messages. Fix them.

Signed-off-by: Colin Ian King <colin.king@canonical.com>
---
 lib/test_rhashtable.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lib/test_rhashtable.c b/lib/test_rhashtable.c
index e52f8cafe227..2c0c53a99734 100644
--- a/lib/test_rhashtable.c
+++ b/lib/test_rhashtable.c
@@ -395,7 +395,7 @@ static int __init test_rhltable(unsigned int entries)
 			if (WARN(err, "cannot remove element at slot %d", i))
 				continue;
 		} else {
-			if (WARN(err != -ENOENT, "removed non-existant element %d, error %d not %d",
+			if (WARN(err != -ENOENT, "removed non-existent element %d, error %d not %d",
 			     i, err, -ENOENT))
 				continue;
 		}
@@ -440,7 +440,7 @@ static int __init test_rhltable(unsigned int entries)
 			if (WARN(err, "cannot remove element at slot %d", i))
 				continue;
 		} else {
-			if (WARN(err != -ENOENT, "removed non-existant element, error %d not %d",
+			if (WARN(err != -ENOENT, "removed non-existent element, error %d not %d",
 				 err, -ENOENT))
 			continue;
 		}
-- 
2.20.1


^ permalink raw reply related

* [PATCH] net/mlx4_en: fix spelling mistake: "quiting" -> "quitting"
From: Colin King @ 2019-02-17 23:03 UTC (permalink / raw)
  To: Tariq Toukan, David S . Miller, netdev, linux-rdma
  Cc: kernel-janitors, linux-kernel

From: Colin Ian King <colin.king@canonical.com>

There is a spelling mistake in a en_err error message. Fix it.

Signed-off-by: Colin Ian King <colin.king@canonical.com>
---
 drivers/net/ethernet/mellanox/mlx4/en_netdev.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index 6b88881b8e35..c1438ae52a11 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -3360,7 +3360,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
 	dev->addr_len = ETH_ALEN;
 	mlx4_en_u64_to_mac(dev->dev_addr, mdev->dev->caps.def_mac[priv->port]);
 	if (!is_valid_ether_addr(dev->dev_addr)) {
-		en_err(priv, "Port: %d, invalid mac burned: %pM, quiting\n",
+		en_err(priv, "Port: %d, invalid mac burned: %pM, quitting\n",
 		       priv->port, dev->dev_addr);
 		err = -EINVAL;
 		goto out;
-- 
2.20.1


^ permalink raw reply related

* Re: [PATCH v3 perf,bpf 05/11] perf, bpf: save bpf_prog_info in a rbtree in perf_env
From: Jiri Olsa @ 2019-02-17 23:05 UTC (permalink / raw)
  To: Song Liu
  Cc: netdev, linux-kernel, ast, daniel, kernel-team, peterz, acme,
	jolsa, namhyung
In-Reply-To: <20190215215354.3114006-6-songliubraving@fb.com>

On Fri, Feb 15, 2019 at 01:53:48PM -0800, Song Liu wrote:

SNIP

>  	info_linear = bpf_program__get_prog_info_linear(fd, arrays);
>  	if (IS_ERR_OR_NULL(info_linear)) {
> @@ -151,8 +165,8 @@ static int perf_event__synthesize_one_bpf_prog(struct perf_tool *tool,
>  						     machine, process);
>  	}
>  
> -	/* Synthesize PERF_RECORD_BPF_EVENT */
>  	if (opts->bpf_event) {
> +		/* Synthesize PERF_RECORD_BPF_EVENT */
>  		*bpf_event = (struct bpf_event){
>  			.header = {
>  				.type = PERF_RECORD_BPF_EVENT,
> @@ -165,6 +179,19 @@ static int perf_event__synthesize_one_bpf_prog(struct perf_tool *tool,
>  		memcpy(bpf_event->tag, info->tag, BPF_TAG_SIZE);
>  		memset((void *)event + event->header.size, 0, machine->id_hdr_size);
>  		event->header.size += machine->id_hdr_size;
> +
> +		/* save bpf_prog_info to env */
> +		info_node = malloc(sizeof(struct bpf_prog_info_node));
> +		if (info_node) {
> +			info_node->info_linear = info_linear;
> +			perf_env__insert_bpf_prog_info(env, info_node);
> +			info_linear = NULL;
> +		}

what if the allocation fails? we don't care?

jirka

^ permalink raw reply

* Re: [PATCH v3 perf,bpf 10/11] perf, bpf: enable annotation of bpf program
From: Jiri Olsa @ 2019-02-17 23:05 UTC (permalink / raw)
  To: Song Liu
  Cc: netdev, linux-kernel, ast, daniel, kernel-team, peterz, acme,
	jolsa, namhyung
In-Reply-To: <20190215215354.3114006-11-songliubraving@fb.com>

On Fri, Feb 15, 2019 at 01:53:53PM -0800, Song Liu wrote:

SNIP

> diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
> index 70de8f6b3aee..078017d31ca9 100644
> --- a/tools/perf/util/annotate.c
> +++ b/tools/perf/util/annotate.c
> @@ -22,6 +22,7 @@
>  #include "annotate.h"
>  #include "evsel.h"
>  #include "evlist.h"
> +#include "bpf-event.h"
>  #include "block-range.h"
>  #include "string2.h"
>  #include "arch/common.h"
> @@ -29,6 +30,9 @@
>  #include <pthread.h>
>  #include <linux/bitops.h>
>  #include <linux/kernel.h>
> +#include <bfd.h>
> +#include <dis-asm.h>
> +#include <bpf/libbpf.h>
>  
>  /* FIXME: For the HE_COLORSET */
>  #include "ui/browser.h"
> @@ -1672,6 +1676,147 @@ static int dso__disassemble_filename(struct dso *dso, char *filename, size_t fil
>  	return 0;
>  }
>  
> +static void get_exec_path(char *tpath, size_t size)
> +{
> +	const char *path = "/proc/self/exe";
> +	ssize_t len;
> +
> +	len = readlink(path, tpath, size - 1);
> +	assert(len > 0);
> +	tpath[len] = 0;
> +}

this is also used in write_cmdline, could you please
move it under util.c and use it in write_cmdline as well?

thanks,
jirka

> +
> +static int symbol__disassemble_bpf(struct symbol *sym,
> +				   struct annotate_args *args)
> +{
> +	struct annotation *notes = symbol__annotation(sym);
> +	struct annotation_options *opts = args->options;
> +	struct bpf_prog_info_linear *info_linear;
> +	struct bpf_prog_linfo *prog_linfo = NULL;
> +	struct bpf_prog_info_node *info_node;
> +	int len = sym->end - sym->start;
> +	disassembler_ftype disassemble;
> +	struct map *map = args->ms.map;
> +	struct disassemble_info info;
> +	struct dso *dso = map->dso;
> +	int pc = 0, count, sub_id;
> +	struct btf *btf = NULL;
> +	char tpath[PATH_MAX];
> +	size_t buf_size;
> +	int nr_skip = 0;
> +	__u64 arrays;
> +	char *buf;
> +	bfd *bfdf;
> +	FILE *s;

nice triangle ;-)

SNIP

^ permalink raw reply

* Re: [PATCH v3 perf,bpf 06/11] perf, bpf: save bpf_prog_info information as headers to perf.data
From: Jiri Olsa @ 2019-02-17 23:05 UTC (permalink / raw)
  To: Song Liu
  Cc: netdev, linux-kernel, ast, daniel, kernel-team, peterz, acme,
	jolsa, namhyung
In-Reply-To: <20190215215354.3114006-7-songliubraving@fb.com>

On Fri, Feb 15, 2019 at 01:53:49PM -0800, Song Liu wrote:

SNIP

> +static int process_bpf_prog_info(struct feat_fd *ff,
> +				 void *data __maybe_unused)
> +{
> +	struct bpf_prog_info_linear *info_linear;
> +	struct bpf_prog_info_node *info_node;
> +	struct perf_env *env = &ff->ph->env;
> +	u32 count, i;
> +	int err = -1;
> +
> +	if (do_read_u32(ff, &count))
> +		return -1;
> +
> +	down_write(&env->bpf_progs.bpf_info_lock);
> +
> +	for (i = 0; i < count; ++i) {
> +		u32 info_len, data_len;
> +
> +		info_linear = NULL;
> +		info_node = NULL;
> +		if (do_read_u32(ff, &info_len))
> +			goto out;
> +		if (do_read_u32(ff, &data_len))
> +			goto out;
> +
> +		if (info_len > sizeof(struct bpf_prog_info)) {
> +			pr_warning("detected invalid bpf_prog_info\n");
> +			goto out;
> +		}
> +
> +		info_linear = malloc(sizeof(struct bpf_prog_info_linear) +
> +				     data_len);
> +		if (!info_linear)
> +			goto out;
> +		info_linear->info_len = sizeof(struct bpf_prog_info);
> +		info_linear->data_len = data_len;
> +		if (do_read_u64(ff, (u64 *)(&info_linear->arrays)))
> +			goto out;
> +		if (__do_read(ff, &info_linear->info, info_len))
> +			goto out;

hum, hows the endianity swap handled for struct bpf_prog_info?

> +		if (info_len < sizeof(struct bpf_prog_info))
> +			memset(((void *)(&info_linear->info)) + info_len, 0,
> +			       sizeof(struct bpf_prog_info) - info_len);
> +
> +		if (__do_read(ff, info_linear->data, data_len))
> +			goto out;

and the data?

thanks,
jirka

^ permalink raw reply

* Re: [PATCH v3 perf,bpf 08/11] perf, bpf: save btf information as headers to perf.data
From: Jiri Olsa @ 2019-02-17 23:05 UTC (permalink / raw)
  To: Song Liu
  Cc: netdev, linux-kernel, ast, daniel, kernel-team, peterz, acme,
	jolsa, namhyung
In-Reply-To: <20190215215354.3114006-9-songliubraving@fb.com>

On Fri, Feb 15, 2019 at 01:53:51PM -0800, Song Liu wrote:

SNIP

>  struct header_print_data {
> diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
> index 0785c91b4c3a..ba51d8e43c53 100644
> --- a/tools/perf/util/header.h
> +++ b/tools/perf/util/header.h
> @@ -40,6 +40,7 @@ enum {
>  	HEADER_MEM_TOPOLOGY,
>  	HEADER_CLOCKID,
>  	HEADER_BPF_PROG_INFO,
> +	HEADER_BTF,

hu, could we maybe prefix all the bpf related features with BPF_ ?

jirka

>  	HEADER_LAST_FEATURE,
>  	HEADER_FEAT_BITS	= 256,
>  };
> -- 
> 2.17.1
> 

^ permalink raw reply

* Re: [PATCH v3 perf,bpf 05/11] perf, bpf: save bpf_prog_info in a rbtree in perf_env
From: Jiri Olsa @ 2019-02-17 23:05 UTC (permalink / raw)
  To: Song Liu
  Cc: netdev, linux-kernel, ast, daniel, kernel-team, peterz, acme,
	jolsa, namhyung
In-Reply-To: <20190215215354.3114006-6-songliubraving@fb.com>

On Fri, Feb 15, 2019 at 01:53:48PM -0800, Song Liu wrote:

SNIP

> diff --git a/tools/perf/util/env.h b/tools/perf/util/env.h
> index d01b8355f4ca..d0c53fe6d431 100644
> --- a/tools/perf/util/env.h
> +++ b/tools/perf/util/env.h
> @@ -3,7 +3,9 @@
>  #define __PERF_ENV_H
>  
>  #include <linux/types.h>
> +#include <linux/rbtree.h>
>  #include "cpumap.h"
> +#include "rwsem.h"
>  
>  struct cpu_topology_map {
>  	int	socket_id;
> @@ -64,8 +66,19 @@ struct perf_env {
>  	struct memory_node	*memory_nodes;
>  	unsigned long long	 memory_bsize;
>  	u64                     clockid_res_ns;
> +
> +	/*
> +	 * bpf_info_lock protects bpf rbtrees. This is needed because the
> +	 * trees are accessed by different threads in perf-top
> +	 */
> +	struct {
> +		struct rw_semaphore	bpf_info_lock;
> +		struct rb_root		bpf_prog_infos;

there's already struct name 'bpf_progs', no need for
those bpf_ prefixes

jirka


> +	} bpf_progs;

SNIP

^ permalink raw reply

* Re: [PATCH v3 perf,bpf 11/11] perf, bpf: save information about short living bpf programs
From: Jiri Olsa @ 2019-02-17 23:05 UTC (permalink / raw)
  To: Song Liu
  Cc: netdev, linux-kernel, ast, daniel, kernel-team, peterz, acme,
	jolsa, namhyung
In-Reply-To: <20190215215354.3114006-12-songliubraving@fb.com>

On Fri, Feb 15, 2019 at 01:53:54PM -0800, Song Liu wrote:
> To annotate bpf programs in perf, it is necessary to save information in
> bpf_prog_info and btf. For short living bpf program, it is necessary to
> save these information before it is unloaded.
> 
> This patch saves these information in a separate thread. This thread
> creates its own evlist, that only tracks bpf events. This evlists uses
> ring buffer with very low watermark for lower latency. When bpf load
> events are received, this thread tries to gather information via sys_bpf
> and save it in perf_env.

could we make this a generic? like havving support
to create a thread that would process sideband evets?

itcould be used for the that buildid stuff and for
things like getting full command lines from comm
events and such

jirka

^ permalink raw reply

* Re: [PATCH v3 perf,bpf 10/11] perf, bpf: enable annotation of bpf program
From: Jiri Olsa @ 2019-02-17 23:06 UTC (permalink / raw)
  To: Song Liu
  Cc: netdev, linux-kernel, ast, daniel, kernel-team, peterz, acme,
	jolsa, namhyung
In-Reply-To: <20190215215354.3114006-11-songliubraving@fb.com>

On Fri, Feb 15, 2019 at 01:53:53PM -0800, Song Liu wrote:
> This patch enables the annotation of bpf program.
> 
> A new dso type DSO_BINARY_TYPE__BPF_PROG_INFO is introduced to for BPF
> programs. In symbol__disassemble(), DSO_BINARY_TYPE__BPF_PROG_INFO dso
> calls into a new function symbol__disassemble_bpf(), where annotation
> line information is filled based bpf_prog_info and btf saved in given
> perf_env.
> 
> symbol__disassemble_bpf() uses libbfd to disassemble bpf programs.
> 
> Signed-off-by: Song Liu <songliubraving@fb.com>
> ---
>  tools/perf/Makefile.config  |   6 +-
>  tools/perf/util/annotate.c  | 149 +++++++++++++++++++++++++++++++++++-
>  tools/perf/util/bpf-event.c |  48 ++++++++++++
>  tools/perf/util/bpf-event.h |   4 +
>  tools/perf/util/dso.c       |   1 +
>  tools/perf/util/dso.h       |  33 +++++---
>  tools/perf/util/symbol.c    |   1 +
>  7 files changed, 229 insertions(+), 13 deletions(-)
> 
> diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
> index b441c88cafa1..ab223239f1fb 100644
> --- a/tools/perf/Makefile.config
> +++ b/tools/perf/Makefile.config
> @@ -701,7 +701,7 @@ else
>  endif
>  
>  ifeq ($(feature-libbfd), 1)
> -  EXTLIBS += -lbfd
> +  EXTLIBS += -lbfd -lopcodes

hum, what's this -lopcodes lib? please add it in a separate
patch and explain why it's added and how it affects others
it looks like it could break some distros without that lib

jirka

^ permalink raw reply

* Re: [PATCH v3 perf,bpf 10/11] perf, bpf: enable annotation of bpf program
From: Jiri Olsa @ 2019-02-17 23:06 UTC (permalink / raw)
  To: Song Liu
  Cc: netdev, linux-kernel, ast, daniel, kernel-team, peterz, acme,
	jolsa, namhyung
In-Reply-To: <20190215215354.3114006-11-songliubraving@fb.com>

On Fri, Feb 15, 2019 at 01:53:53PM -0800, Song Liu wrote:

SNIP

> +static int symbol__disassemble_bpf(struct symbol *sym,
> +				   struct annotate_args *args)
> +{
> +	struct annotation *notes = symbol__annotation(sym);
> +	struct annotation_options *opts = args->options;
> +	struct bpf_prog_info_linear *info_linear;
> +	struct bpf_prog_linfo *prog_linfo = NULL;
> +	struct bpf_prog_info_node *info_node;
> +	int len = sym->end - sym->start;
> +	disassembler_ftype disassemble;
> +	struct map *map = args->ms.map;
> +	struct disassemble_info info;
> +	struct dso *dso = map->dso;
> +	int pc = 0, count, sub_id;
> +	struct btf *btf = NULL;
> +	char tpath[PATH_MAX];
> +	size_t buf_size;
> +	int nr_skip = 0;
> +	__u64 arrays;
> +	char *buf;
> +	bfd *bfdf;
> +	FILE *s;
> +
> +	if (dso->binary_type != DSO_BINARY_TYPE__BPF_PROG_INFO)
> +		return -1;
> +
> +	pr_debug("%s: handling sym %s addr %lx len %lx\n", __func__,
> +		 sym->name, sym->start, sym->end - sym->start);
> +
> +	memset(tpath, 0, sizeof(tpath));
> +	get_exec_path(tpath, sizeof(tpath));
> +
> +	bfdf = bfd_openr(tpath, NULL);
> +	assert(bfdf);
> +	assert(bfd_check_format(bfdf, bfd_object));
> +
> +	s = open_memstream(&buf, &buf_size);

what if open_memstream fails?


> +	init_disassemble_info(&info, s,
> +			      (fprintf_ftype) fprintf);
> +
> +	info.arch = bfd_get_arch(bfdf);
> +	info.mach = bfd_get_mach(bfdf);
> +
> +	arrays = 1UL << BPF_PROG_INFO_JITED_INSNS;
> +	arrays |= 1UL << BPF_PROG_INFO_JITED_KSYMS;
> +	arrays |= 1UL << BPF_PROG_INFO_LINE_INFO;
> +	arrays |= 1UL << BPF_PROG_INFO_FUNC_INFO;

what's the arrays for?

> +
> +	info_node = perf_env__find_bpf_prog_info(dso->bpf_prog.env,
> +						 dso->bpf_prog.id);
> +	if (!info_node)
> +		return -1;
> +	info_linear = info_node->info_linear;
> +	sub_id = dso->bpf_prog.sub_id;
> +
> +	info.buffer = (void *)(info_linear->info.jited_prog_insns);
> +	info.buffer_length = info_linear->info.jited_prog_len;
> +
> +	if (info_linear->info.nr_line_info)
> +		prog_linfo = bpf_prog_linfo__new(&info_linear->info);
> +	prog_linfo = prog_linfo;
> +
> +	if (info_linear->info.btf_id) {
> +		struct btf_node *node;
> +
> +		node = perf_env__find_btf(dso->bpf_prog.env,
> +					  info_linear->info.btf_id);
> +		if (node)
> +			btf = btf__new((__u8 *)(node->data),
> +				       node->data_size);
> +	}

what if btf__new fails? the btf__name_by_offset
does not check btf != NULL

> +
> +	disassemble_init_for_target(&info);
> +
> +#ifdef DISASM_FOUR_ARGS_SIGNATURE
> +	disassemble = disassembler(info.arch,
> +				   bfd_big_endian(bfdf),
> +				   info.mach,
> +				   bfdf);
> +#else
> +	disassemble = disassembler(bfdf);
> +#endif
> +	assert(disassemble);
> +
> +	fflush(s);

any chance this function could be split into some logical
pieces/fucntions?

thanks,
jirka

> +	do {
> +		const struct bpf_line_info *linfo = NULL;
> +		struct disasm_line *dl;
> +		size_t prev_buf_size;
> +		const char *srcline;
> +		u64 addr;
> +
> +		addr = pc + ((u64 *)(info_linear->info.jited_ksyms))[sub_id];
> +		count = disassemble(pc, &info);
> +
> +		linfo = bpf_prog_linfo__lfind_addr_func(prog_linfo, addr, sub_id,
> +							nr_skip);
> +
> +		if (linfo) {
> +			srcline = btf__name_by_offset(btf, linfo->line_off);
> +			nr_skip++;
> +		} else
> +			srcline = NULL;
> +
> +		fprintf(s, "\n");
> +		prev_buf_size = buf_size;
> +		fflush(s);
> +
> +		if (!opts->hide_src_code && srcline) {
> +			args->offset = -1;
> +			args->line = strdup(srcline);
> +			args->line_nr = 0;
> +			args->ms.sym  = sym;
> +			dl = disasm_line__new(args);
> +			annotation_line__add(&dl->al, &notes->src->source);
> +		}
> +
> +		args->offset = pc;
> +		args->line = buf + prev_buf_size;
> +		args->line_nr = 0;
> +		args->ms.sym  = sym;
> +		dl = disasm_line__new(args);
> +		annotation_line__add(&dl->al, &notes->src->source);
> +
> +		pc += count;
> +	} while (count > 0 && pc < len);
> +
> +	bfd_close(bfdf);
> +	return 0;
> +}

SNIP

^ permalink raw reply

* Re: [PATCH v3 perf,bpf 10/11] perf, bpf: enable annotation of bpf program
From: Jiri Olsa @ 2019-02-17 23:06 UTC (permalink / raw)
  To: Song Liu
  Cc: netdev, linux-kernel, ast, daniel, kernel-team, peterz, acme,
	jolsa, namhyung
In-Reply-To: <20190215215354.3114006-11-songliubraving@fb.com>

On Fri, Feb 15, 2019 at 01:53:53PM -0800, Song Liu wrote:

SNIP

>  int machine__process_bpf_event(struct machine *machine __maybe_unused,
>  			       union perf_event *event,
>  			       struct perf_sample *sample __maybe_unused)
>  {
>  	if (dump_trace)
>  		perf_event__fprintf_bpf_event(event, stdout);
> +
> +	switch (event->bpf_event.type) {
> +	case PERF_BPF_EVENT_PROG_LOAD:
> +		return machine__process_bpf_event_load(machine, event, sample);
> +
> +	case PERF_BPF_EVENT_PROG_UNLOAD:
> +		break;

could we make a comment here, descriving why we dont
remove bpf programs.. which I assume is intentional 

thanks,
jirka

^ permalink raw reply

* Re: [PATCH v3 perf,bpf 08/11] perf, bpf: save btf information as headers to perf.data
From: Jiri Olsa @ 2019-02-17 23:06 UTC (permalink / raw)
  To: Song Liu
  Cc: netdev, linux-kernel, ast, daniel, kernel-team, peterz, acme,
	jolsa, namhyung
In-Reply-To: <20190215215354.3114006-9-songliubraving@fb.com>

On Fri, Feb 15, 2019 at 01:53:51PM -0800, Song Liu wrote:
> This patch enables perf-record to save btf information as headers to
> perf.data A new header type HEADER_BTF is introduced for this data.
> 
> Signed-off-by: Song Liu <songliubraving@fb.com>
> ---
>  tools/perf/util/header.c | 99 +++++++++++++++++++++++++++++++++++++++-
>  tools/perf/util/header.h |  1 +
>  2 files changed, 99 insertions(+), 1 deletion(-)
> 
> diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
> index 0889ad797940..2de4f4e9b590 100644
> --- a/tools/perf/util/header.c
> +++ b/tools/perf/util/header.c
> @@ -1127,6 +1127,45 @@ static int write_bpf_prog_info(struct feat_fd *ff,
>  	return ret;
>  }
>  
> +static int write_btf(struct feat_fd *ff,
> +		     struct perf_evlist *evlist __maybe_unused)
> +{
> +	struct perf_env *env = &ff->ph->env;
> +	struct rb_root *root;
> +	struct rb_node *next;
> +	u32 count = 0;
> +	int ret;
> +
> +	down_read(&env->bpf_progs.bpf_info_lock);
> +
> +	root = &env->bpf_progs.btfs;
> +	next = rb_first(root);
> +	while (next) {
> +		++count;
> +		next = rb_next(next);
> +	}
> +
> +	ret = do_write(ff, &count, sizeof(count));
> +
> +	if (ret < 0)
> +		goto out;
> +
> +	next = rb_first(root);
> +	while (next) {
> +		struct btf_node *node;
> +
> +		node = rb_entry(next, struct btf_node, rb_node);
> +		next = rb_next(&node->rb_node);
> +		ret = do_write(ff, node,
> +			       sizeof(struct btf_node) + node->data_size);

hm, you write the whole struct btf_node with struct rb_node? why?

thanks,
jirka

^ permalink raw reply

* Re: [PATCH v3 perf,bpf 08/11] perf, bpf: save btf information as headers to perf.data
From: Jiri Olsa @ 2019-02-17 23:06 UTC (permalink / raw)
  To: Song Liu
  Cc: netdev, linux-kernel, ast, daniel, kernel-team, peterz, acme,
	jolsa, namhyung
In-Reply-To: <20190215215354.3114006-9-songliubraving@fb.com>

On Fri, Feb 15, 2019 at 01:53:51PM -0800, Song Liu wrote:

SNIP

> +static int process_btf(struct feat_fd *ff, void *data __maybe_unused)
> +{
> +	struct perf_env *env = &ff->ph->env;
> +	u32 count, i;
> +
> +	if (do_read_u32(ff, &count))
> +		return -1;
> +
> +	down_write(&env->bpf_progs.bpf_info_lock);
> +
> +	for (i = 0; i < count; ++i) {
> +		struct btf_node btf_node;
> +		struct btf_node *node;
> +
> +		if (__do_read(ff, &btf_node, sizeof(struct btf_node)))
> +			return -1;
> +
> +		node = malloc(sizeof(struct btf_node) + btf_node.data_size);
> +		if (!node)
> +			return -1;
> +
> +		node->id = btf_node.id;
> +		node->data_size = btf_node.data_size;
> +
> +		if (__do_read(ff, node->data, btf_node.data_size)) {
> +			free(node);
> +			return -1;
> +		}

hows endianity swap handled got struct btf_node and data in here?

thanks,
jirka

^ permalink raw reply

* Re: [PATCH v3 perf,bpf 10/11] perf, bpf: enable annotation of bpf program
From: Jiri Olsa @ 2019-02-17 23:06 UTC (permalink / raw)
  To: Song Liu
  Cc: netdev, linux-kernel, ast, daniel, kernel-team, peterz, acme,
	jolsa, namhyung
In-Reply-To: <20190215215354.3114006-11-songliubraving@fb.com>

On Fri, Feb 15, 2019 at 01:53:53PM -0800, Song Liu wrote:

SNIP

> diff --git a/tools/perf/util/bpf-event.c b/tools/perf/util/bpf-event.c
> index 52507435c464..6c363adc781a 100644
> --- a/tools/perf/util/bpf-event.c
> +++ b/tools/perf/util/bpf-event.c
> @@ -25,12 +25,60 @@ static int snprintf_hex(char *buf, size_t size, unsigned char *data, size_t len)
>  	return ret;
>  }
>  

please move PERF_BPF_EVENT_PROG_LOAD/PERF_BPF_EVENT_PROG_UNLOAD
handling code below into separate patch from the bpf disassembly
code

thanks,
jirka

> +static int machine__process_bpf_event_load(struct machine *machine __maybe_unused,
> +					   union perf_event *event,
> +					   struct perf_sample *sample __maybe_unused)
> +{
> +	struct bpf_prog_info_linear *info_linear;
> +	struct bpf_prog_info_node *info_node;
> +	struct perf_env *env = machine->env;
> +	int id = event->bpf_event.id;
> +	unsigned int i;
> +
> +	/* perf-record, no need to handle bpf-event */
> +	if (env == NULL)
> +		return 0;
> +
> +	info_node = perf_env__find_bpf_prog_info(env, id);
> +	if (!info_node)
> +		return 0;
> +	info_linear = info_node->info_linear;
> +
> +	for (i = 0; i < info_linear->info.nr_jited_ksyms; i++) {
> +		u64 *addrs = (u64 *)(info_linear->info.jited_ksyms);
> +		u64 addr = addrs[i];
> +		struct map *map;
> +
> +		map = map_groups__find(&machine->kmaps, addr);
> +
> +		if (map) {
> +			map->dso->binary_type = DSO_BINARY_TYPE__BPF_PROG_INFO;
> +			map->dso->bpf_prog.id = id;
> +			map->dso->bpf_prog.sub_id = i;
> +			map->dso->bpf_prog.env = env;
> +		}
> +	}
> +	return 0;
> +}
> +
>  int machine__process_bpf_event(struct machine *machine __maybe_unused,
>  			       union perf_event *event,
>  			       struct perf_sample *sample __maybe_unused)
>  {
>  	if (dump_trace)
>  		perf_event__fprintf_bpf_event(event, stdout);
> +
> +	switch (event->bpf_event.type) {
> +	case PERF_BPF_EVENT_PROG_LOAD:
> +		return machine__process_bpf_event_load(machine, event, sample);
> +
> +	case PERF_BPF_EVENT_PROG_UNLOAD:
> +		break;
> +	default:
> +		pr_debug("unexpected bpf_event type of %d\n",
> +			 event->bpf_event.type);
> +		break;
> +	}
>  	return 0;
>  }
>  
> diff --git a/tools/perf/util/bpf-event.h b/tools/perf/util/bpf-event.h
> index b9ec394dc7c7..ab4a975b7e05 100644
> --- a/tools/perf/util/bpf-event.h
> +++ b/tools/perf/util/bpf-event.h
> @@ -2,6 +2,10 @@
>  #ifndef __PERF_BPF_EVENT_H
>  #define __PERF_BPF_EVENT_H
>  
> +#include <bpf/bpf.h>
> +#include <bpf/btf.h>
> +#include <bpf/libbpf.h>
> +#include <linux/btf.h>
>  #include <linux/compiler.h>
>  #include <linux/rbtree.h>
>  #include "event.h"
> diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
> index 62c8cf622607..1798192bf0f9 100644
> --- a/tools/perf/util/dso.c
> +++ b/tools/perf/util/dso.c
> @@ -181,6 +181,7 @@ int dso__read_binary_type_filename(const struct dso *dso,
>  	case DSO_BINARY_TYPE__KALLSYMS:
>  	case DSO_BINARY_TYPE__GUEST_KALLSYMS:
>  	case DSO_BINARY_TYPE__JAVA_JIT:
> +	case DSO_BINARY_TYPE__BPF_PROG_INFO:
>  	case DSO_BINARY_TYPE__NOT_FOUND:
>  		ret = -1;
>  		break;
> diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
> index 8c8a7abe809d..f20d319463f1 100644
> --- a/tools/perf/util/dso.h
> +++ b/tools/perf/util/dso.h
> @@ -14,6 +14,8 @@
>  #include "namespaces.h"
>  #include "build-id.h"
>  
> +struct perf_env;
> +
>  enum dso_binary_type {
>  	DSO_BINARY_TYPE__KALLSYMS = 0,
>  	DSO_BINARY_TYPE__GUEST_KALLSYMS,
> @@ -34,6 +36,7 @@ enum dso_binary_type {
>  	DSO_BINARY_TYPE__KCORE,
>  	DSO_BINARY_TYPE__GUEST_KCORE,
>  	DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO,
> +	DSO_BINARY_TYPE__BPF_PROG_INFO,
>  	DSO_BINARY_TYPE__NOT_FOUND,
>  };
>  
> @@ -177,17 +180,25 @@ struct dso {
>  	struct auxtrace_cache *auxtrace_cache;
>  	int		 comp;
>  
> -	/* dso data file */
> -	struct {
> -		struct rb_root	 cache;
> -		int		 fd;
> -		int		 status;
> -		u32		 status_seen;
> -		size_t		 file_size;
> -		struct list_head open_entry;
> -		u64		 debug_frame_offset;
> -		u64		 eh_frame_hdr_offset;
> -	} data;
> +	union {
> +		/* dso data file */
> +		struct {
> +			struct rb_root	 cache;
> +			int		 fd;
> +			int		 status;
> +			u32		 status_seen;
> +			size_t		 file_size;
> +			struct list_head open_entry;
> +			u64		 debug_frame_offset;
> +			u64		 eh_frame_hdr_offset;
> +		} data;
> +		/* bpf prog information */
> +		struct {
> +			u32		id;
> +			u32		sub_id;
> +			struct perf_env	*env;
> +		} bpf_prog;
> +	};
>  
>  	union { /* Tool specific area */
>  		void	 *priv;
> diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
> index 48efad6d0f90..33ae59e89da2 100644
> --- a/tools/perf/util/symbol.c
> +++ b/tools/perf/util/symbol.c
> @@ -1441,6 +1441,7 @@ static bool dso__is_compatible_symtab_type(struct dso *dso, bool kmod,
>  	case DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO:
>  		return true;
>  
> +	case DSO_BINARY_TYPE__BPF_PROG_INFO:
>  	case DSO_BINARY_TYPE__NOT_FOUND:
>  	default:
>  		return false;
> -- 
> 2.17.1
> 

^ permalink raw reply

* Re: [PATCH v3 perf,bpf 05/11] perf, bpf: save bpf_prog_info in a rbtree in perf_env
From: Jiri Olsa @ 2019-02-17 23:06 UTC (permalink / raw)
  To: Song Liu
  Cc: netdev, linux-kernel, ast, daniel, kernel-team, peterz, acme,
	jolsa, namhyung
In-Reply-To: <20190215215354.3114006-6-songliubraving@fb.com>

On Fri, Feb 15, 2019 at 01:53:48PM -0800, Song Liu wrote:

SNIP

> @@ -165,6 +179,19 @@ static int perf_event__synthesize_one_bpf_prog(struct perf_tool *tool,
>  		memcpy(bpf_event->tag, info->tag, BPF_TAG_SIZE);
>  		memset((void *)event + event->header.size, 0, machine->id_hdr_size);
>  		event->header.size += machine->id_hdr_size;
> +
> +		/* save bpf_prog_info to env */
> +		info_node = malloc(sizeof(struct bpf_prog_info_node));
> +		if (info_node) {
> +			info_node->info_linear = info_linear;
> +			perf_env__insert_bpf_prog_info(env, info_node);
> +			info_linear = NULL;
> +		}
> +
> +		/*
> +		 * process after saving bpf_prog_info to env, so that
> +		 * required information is ready for look up
> +		 */
>  		err = perf_tool__process_synth_event(tool, event,
>  						     machine, process);
>  	}
> @@ -175,7 +202,7 @@ static int perf_event__synthesize_one_bpf_prog(struct perf_tool *tool,
>  	return err ? -1 : 0;
>  }
>  
> -int perf_event__synthesize_bpf_events(struct perf_tool *tool,
> +int perf_event__synthesize_bpf_events(struct perf_session *session,
>  				      perf_event__handler_t process,
>  				      struct machine *machine,
>  				      struct record_opts *opts)

please move the prototype change into separate patch

thanks,
jirka

^ permalink raw reply

* Re: [PATCH RFC net-next] 6lowpan: use rbtree for IP frag queue
From: Alexander Aring @ 2019-02-17 23:08 UTC (permalink / raw)
  To: Peter Oskolkov; +Cc: David Miller, linux-wpan, netdev, Peter Oskolkov, stefan
In-Reply-To: <20190215022953.128092-1-posk@google.com>

Hi,

On Thu, Feb 14, 2019 at 06:29:53PM -0800, Peter Oskolkov wrote:
> This patch aligns IP defragmenation logic in 6lowpan with that
> of IPv4 and IPv6: see
> commit d4289fcc9b16 ("net: IP6 defrag: use rbtrees for IPv6 defrag")
> 
> Modifying ip_defrag selftest seemed like an overkill, as I suspect
> most kernel test setups do not have 6lowpan hwsim enabled. So I ran
> the following code/script manually:
> 
> 	insmod ./mac802154_hwsim.ko
> 
> 	iwpan dev wpan0 set pan_id 0xbeef
> 	ip link add link wpan0 name lowpan0 type lowpan
> 	ip link set wpan0 up
> 	ip link set lowpan0 up
> 
> 	iwpan dev wpan1 set pan_id 0xbeef
> 	ip netns add foo
> 	iwpan phy1 set netns name foo
> 	ip netns exec foo ip link add link wpan1 name lowpan1 type lowpan
> 	ip netns exec foo ip link set wpan1 up
> 	ip netns exec foo ip link set lowpan1 up
> 
> 	ip -6 addr add "fb01::1/128" nodad dev lowpan0
> 	ip -netns foo -6 addr add "fb02::1/128" nodad dev lowpan1
> 
> 	ip -6 route add "fb02::1/128" dev lowpan0
> 	ip -netns foo -6 route add "fb01::1/128" dev lowpan1
> 
> 	# then in term1:
> 	   ip netns exec foo bash
> 	   ./udp_stream -6
> 
> 	# in term2:
> 	    ./udp_stream -c -6 -H fb02::1
> 
> 	# pr_warn_once showed that the code changed by this patch
> 	# was invoked.
> 
> Signed-off-by: Peter Oskolkov <posk@google.com>

Acked-by: Alexander Aring <aring@mojatatu.com>

I tested this series and the code looks a lot simpler. Thanks.

Stefan do you see any issues?

- Alex

^ permalink raw reply

* Re: [BUG] [FIX] net: dsa: oops in br_vlan_enabled
From: Florian Fainelli @ 2019-02-17 23:20 UTC (permalink / raw)
  To: Frank Wunderlich, netdev, Andrew Lunn, Vivien Didelot
In-Reply-To: <62c1c008-8484-3e6c-239a-906efb55a6d0@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 5020 bytes --]



On 2/17/2019 9:13 AM, Florian Fainelli wrote:
> Hi Frank,
> 
> On 2/16/2019 8:22 AM, Frank Wunderlich wrote:
>> Hi,
>>
>> i've found an oops in 4.19.23/10, seems to be fixed anyhow in 5.0 (also works in 4.14.101)
>>
>> root@bpi-r2:~# ip link add link lan0 name lan0.5 type vlan id 5
>> root@bpi-r2:~# ip addr add 192.168.5.200/24 brd 192.168.5.255 dev lan0.5
>> root@bpi-r2:~# ip link set dev lan0 up
>> root@bpi-r2:~# ip link set dev lan0.5 up
> 
> So that these steps don't involve a bridge, and because we don't (yet)
> implment ndo_vlan_rx_{add,kill}_vid() netdevice_ops, there is no VLAN
> programming, it's all software
> 
>>
>> 12: lan0.5@lan0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state LOWERLAYERDOWN group default qlen 1000
>>     link/ether 02:02:02:02:02:02 brd ff:ff:ff:ff:ff:ff
>>     inet 192.168.5.200/24 brd 192.168.5.255 scope global lan0.5
>>        valid_lft forever preferred_lft forever
>>
>> root@bpi-r2:~# brctl addbr bridge_name
>> root@bpi-r2:~# brctl addif bridge_name lan0.5
> 
> Unless you changed the bridge to have VLAN filtering/awareness with:
> 
> echo 1 > /sys/class/net/bridge_name/bridge/vlan_filtering
> 
> There will be no VLAN configuration/objects pushed to DSA since commit
> 2ea7a679ca2abd251c1ec03f20508619707e1749 ("net: dsa: Don't add vlans
> when vlan filtering is disabled") so I am not sure how you got into that
> situation because prior to pushing a VLAN object, the port must be part
> of a bridge, so the steps typically look like:
> 
> - port_bridge_join which assigns dp->bridge_dev
> - port_vlan_add
> 
> Does your 4.19.23 kernel somehow change how VLAN objects are pushed down
> the switch driver?
> 
>> [  352.057128] bridge_name: port 1(lan0.5) entered blocking state
>> [  352.063065] bridge_name: port 1(lan0.5) entered disabled state
>> [  352.069181] device lan0.5 entered promiscuous mode
>> [  352.074018] device lan0 entered promiscuous mode
>> [  352.078906] Unable to handle kernel NULL pointer dereference at virtual address 00000558
>> ...
>> [  352.493085] [<bf0fde88>] (br_vlan_enabled [bridge]) from [<bf12c234>] (dsa_port_vlan_add+0x60/0xbc [dsa_core])
>> [  352.503050] [<bf12c234>] (dsa_port_vlan_add [dsa_core]) from [<bf12cb64>] (dsa_slave_port_obj_add+0x4c/0x50 [dsa_core])
>> [  352.513776] [<bf12cb64>] (dsa_slave_port_obj_add [dsa_core]) from [<c0b4e2d4>] (__switchdev_port_obj_add+0x50/0xc4)
>> [  352.524138] [<c0b4e2d4>] (__switchdev_port_obj_add) from [<c0b4e324>] (__switchdev_port_obj_add+0xa0/0xc4)
>> [  352.533721] [<c0b4e324>] (__switchdev_port_obj_add) from [<c0b4e3a8>] (switchdev_port_obj_add_now+0x60/0x130)
>> [  352.543562] [<c0b4e3a8>] (switchdev_port_obj_add_now) from [<c0b4e7e4>] (switchdev_port_obj_add+0x44/0x190)
>> [  352.553284] [<c0b4e7e4>] (switchdev_port_obj_add) from [<bf1013d0>] (br_switchdev_port_vlan_add+0x60/0x7c [bridge])
>> [  352.563733] [<bf1013d0>] (br_switchdev_port_vlan_add [bridge]) from [<bf0ff250>] (__vlan_add+0xb0/0x620 [bridge])
>> [  352.574007] [<bf0ff250>] (__vlan_add [bridge]) from [<bf0ffd04>] (nbp_vlan_add+0xc4/0x150 [bridge])
>> [  352.583073] [<bf0ffd04>] (nbp_vlan_add [bridge]) from [<bf0ffec4>] (nbp_vlan_init+0x134/0x164 [bridge])
>> [  352.592482] [<bf0ffec4>] (nbp_vlan_init [bridge]) from [<bf0edd4c>] (br_add_if+0x40c/0x5fc [bridge])
>> [  352.601632] [<bf0edd4c>] (br_add_if [bridge]) from [<bf0eeb14>] (add_del_if+0x6c/0x80 [bridge])
>> [  352.610351] [<bf0eeb14>] (add_del_if [bridge]) from [<bf0ef5b0>] (br_dev_ioctl+0x7c/0x9c [bridge])
>> [  352.619290] [<bf0ef5b0>] (br_dev_ioctl [bridge]) from [<c09583d4>] (dev_ifsioc+0x184/0x324)
>> [  352.627582] [<c09583d4>] (dev_ifsioc) from [<c09589e8>] (dev_ioctl+0x32c/0x5cc)
>> [  352.634837] [<c09589e8>] (dev_ioctl) from [<c090913c>] (sock_ioctl+0x3bc/0x580)
>>
>>
>> since my 4.19.23 kernel is modified a bit i tried with 4.19.10 without my net modifications and it is still reproducable with steps above (create a vlan on dsa-user-port and then use it in a bridge)
>>
>> i fixed it with these changes:

Your fix is undoing the commit from Andrew I just referenced, so it is
definitively not the right fix because it will push VLAN objects down to
a non-VLAN aware bridge, not that this is really a problem, but it
should not be happening anyway.

The problem appears to be the following though: you are enslaving a VLAN
device, which does not have switchdev_ops, so we recurse into the lower
device, which is the DSA network device, which does have switchdev_ops
defined. Once we are there we check the orig_dev against being a bridge
master network device, but we are not checking that it's a VLAN device
so we end-up assuming it is a DSA network device, we de-reference
garbage by checking br_vlan_enabled(dp->bridge_dev) because there is
simply no such data structure associated with the VLAN device.

The attached patch should help.

This is no longer a problem in newer kernels because the switchdev
operations use a notifier which checks the target network device to be DSA.
-- 
Florian

[-- Attachment #2: 0001-net-dsa-Prevent-oops-while-enslaving-non-DSA-devices.patch --]
[-- Type: text/plain, Size: 2684 bytes --]

From c0c60a1d1dc451a51136867b51df6a4ec34e336b Mon Sep 17 00:00:00 2001
From: Florian Fainelli <f.fainelli@gmail.com>
Date: Sun, 17 Feb 2019 15:16:22 -0800
Subject: [PATCH] net: dsa: Prevent oops while enslaving non-DSA devices

DSA currently does not check that the target network device of a switchdev operation is actually a DSA slave network device

Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
 net/dsa/slave.c | 34 ++++++++++++++++++++++++++++------
 1 file changed, 28 insertions(+), 6 deletions(-)

diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 1c45c1d6d241..3ceef299b030 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -278,9 +278,14 @@ static int dsa_slave_port_attr_set(struct net_device *dev,
 				   const struct switchdev_attr *attr,
 				   struct switchdev_trans *trans)
 {
-	struct dsa_port *dp = dsa_slave_to_port(dev);
+	struct dsa_port *dp;
 	int ret;
 
+	if (!dsa_slave_dev_check(dev))
+		return -EOPNOTSUPP;
+
+	dp = dsa_slave_to_port(dev);
+
 	switch (attr->id) {
 	case SWITCHDEV_ATTR_ID_PORT_STP_STATE:
 		ret = dsa_port_set_state(dp, attr->u.stp_state, trans);
@@ -304,9 +309,14 @@ static int dsa_slave_port_obj_add(struct net_device *dev,
 				  const struct switchdev_obj *obj,
 				  struct switchdev_trans *trans)
 {
-	struct dsa_port *dp = dsa_slave_to_port(dev);
+	struct dsa_port *dp;
 	int err;
 
+	if (!dsa_slave_dev_check(dev))
+		return -EOPNOTSUPP;
+
+	dp = dsa_slave_to_port(dev);
+
 	/* For the prepare phase, ensure the full set of changes is feasable in
 	 * one go in order to signal a failure properly. If an operation is not
 	 * supported, return -EOPNOTSUPP.
@@ -338,9 +348,14 @@ static int dsa_slave_port_obj_add(struct net_device *dev,
 static int dsa_slave_port_obj_del(struct net_device *dev,
 				  const struct switchdev_obj *obj)
 {
-	struct dsa_port *dp = dsa_slave_to_port(dev);
+	struct dsa_port *dp;
 	int err;
 
+	if (!dsa_slave_dev_check(dev))
+		return -EOPNOTSUPP;
+
+	dp = dsa_slave_to_port(dev);
+
 	switch (obj->id) {
 	case SWITCHDEV_OBJ_ID_PORT_MDB:
 		err = dsa_port_mdb_del(dp, SWITCHDEV_OBJ_PORT_MDB(obj));
@@ -365,9 +380,16 @@ static int dsa_slave_port_obj_del(struct net_device *dev,
 static int dsa_slave_port_attr_get(struct net_device *dev,
 				   struct switchdev_attr *attr)
 {
-	struct dsa_port *dp = dsa_slave_to_port(dev);
-	struct dsa_switch *ds = dp->ds;
-	struct dsa_switch_tree *dst = ds->dst;
+	struct dsa_switch_tree *dst;
+	struct dsa_switch *ds;
+	struct dsa_port *dp;
+
+	if (!dsa_slave_dev_check(dev))
+		return -EOPNOTSUPP;
+
+	dp = dsa_slave_to_port(dev);
+	ds = dp->ds;
+	dst = ds->dst;
 
 	switch (attr->id) {
 	case SWITCHDEV_ATTR_ID_PORT_PARENT_ID:
-- 
2.17.1


^ permalink raw reply related

* Re: [PATCH net-next 0/2] net: phy: improve and use phy_resolve_aneg_linkmode
From: David Miller @ 2019-02-17 23:22 UTC (permalink / raw)
  To: hkallweit1; +Cc: andrew, f.fainelli, netdev
In-Reply-To: <cc50884b-6271-6b93-605c-f451abeb0d7e@gmail.com>

From: Heiner Kallweit <hkallweit1@gmail.com>
Date: Thu, 14 Feb 2019 22:12:59 +0100

> Improve phy_resolve_aneg_linkmode and use it in genphy_read_status.

Series applied, thanks Heiner.

^ permalink raw reply

* [PATCH 00/11] Netfilter/IPVS updates for net-next
From: Pablo Neira Ayuso @ 2019-02-17 23:23 UTC (permalink / raw)
  To: netfilter-devel; +Cc: davem, netdev

Hi David,

The following patchset contains Netfilter/IPVS updates for you net-next
tree:

1) Missing NFTA_RULE_POSITION_ID netlink attribute validation,
   from Phil Sutter.

2) Restrict matching on tunnel metadata to rx/tx path, from wenxu.

3) Avoid indirect calls for IPV6=y, from Florian Westphal.

4) Add two indirections to prepare merger of IPV4 and IPV6 nat
   modules, from Florian Westphal.

5) Broken indentation in ctnetlink, from Colin Ian King.

6) Patches to use struct_size() from netfilter and IPVS,
   from Gustavo A. R. Silva.

7) Display kernel splat only once in case of racing to confirm
   conntrack from bridge plus nfqueue setups, from Chieh-Min Wang.

8) Skip checksum validation for layer 4 protocols that don't need it,
   patch from Alin Nastac.

9) Sparse warning due to symbol that should be static in CLUSTERIP,
   from Wei Yongjun.

10) Add new toggle to disable SDP payload translation when media
    endpoint is reachable though the same interface as the signalling
    peer, from Alin Nastac.

You can pull these changes from:

  git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next.git

Thanks!

----------------------------------------------------------------

The following changes since commit bbcbf2eede69c5f54a431fb96c11248a7910748c:

  enetc: include linux/vmalloc.h for vzalloc etc (2019-01-28 22:43:34 -0800)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next.git HEAD

for you to fetch changes up to a3419ce3356cf1fdc69a0524eced84cef730b3bf:

  netfilter: nf_conntrack_sip: add sip_external_media logic (2019-02-16 10:49:12 +0100)

----------------------------------------------------------------
Alin Nastac (2):
      netfilter: reject: skip csum verification for protocols that don't support it
      netfilter: nf_conntrack_sip: add sip_external_media logic

Chieh-Min Wang (1):
      netfilter: conntrack: fix cloned unconfirmed skb->_nfct race in __nf_conntrack_confirm

Colin Ian King (1):
      netfilter: conntrack: fix indentation issue

Florian Westphal (3):
      netfilter: nf_tables: add NFTA_RULE_POSITION_ID to nla_policy
      netfilter: nat: remove module dependency on ipv6 core
      netfilter: ipv6: avoid indirect calls for IPV6=y case

Gustavo A. R. Silva (2):
      ipvs: Use struct_size() helper
      netfilter: xt_recent: Use struct_size() in kvzalloc()

Wei Yongjun (1):
      netfilter: ipt_CLUSTERIP: make symbol 'cip_netdev_notifier' static

wenxu (1):
      netfilter: nft_tunnel: Add NFTA_TUNNEL_MODE options

 include/linux/netfilter_ipv6.h              | 60 +++++++++++++++++++++++++----
 include/net/netfilter/ipv4/nf_reject.h      |  1 +
 include/net/netfilter/ipv6/nf_reject.h      |  1 +
 include/net/netfilter/nf_reject.h           | 27 +++++++++++++
 include/uapi/linux/netfilter/nf_tables.h    |  9 +++++
 net/bridge/netfilter/nft_reject_bridge.c    | 10 ++---
 net/ipv4/netfilter/ipt_CLUSTERIP.c          |  2 +-
 net/ipv4/netfilter/nf_reject_ipv4.c         |  9 +----
 net/ipv6/netfilter.c                        | 13 +++++--
 net/ipv6/netfilter/nf_nat_l3proto_ipv6.c    | 17 +++++++-
 net/ipv6/netfilter/nf_nat_masquerade_ipv6.c | 21 +++++++++-
 net/ipv6/netfilter/nf_reject_ipv6.c         |  3 ++
 net/ipv6/netfilter/nft_fib_ipv6.c           |  9 +----
 net/netfilter/ipvs/ip_vs_ctl.c              |  6 +--
 net/netfilter/nf_conntrack_core.c           | 14 +++++--
 net/netfilter/nf_conntrack_netlink.c        |  2 +-
 net/netfilter/nf_conntrack_sip.c            | 42 ++++++++++++++++++++
 net/netfilter/nf_tables_api.c               |  1 +
 net/netfilter/nft_tunnel.c                  | 34 +++++++++++++++-
 net/netfilter/utils.c                       |  6 +--
 net/netfilter/xt_addrtype.c                 | 16 +++-----
 net/netfilter/xt_recent.c                   |  4 +-
 22 files changed, 244 insertions(+), 63 deletions(-)
 create mode 100644 include/net/netfilter/nf_reject.h

^ permalink raw reply

* [PATCH 01/11] netfilter: nf_tables: add NFTA_RULE_POSITION_ID to nla_policy
From: Pablo Neira Ayuso @ 2019-02-17 23:23 UTC (permalink / raw)
  To: netfilter-devel; +Cc: davem, netdev
In-Reply-To: <20190217232357.29858-1-pablo@netfilter.org>

From: Florian Westphal <fw@strlen.de>

Fixes: 75dd48e2e420a ("netfilter: nf_tables: Support RULE_ID reference in new rule")
Reported-by: Cong Wang <xiyou.wangcong@gmail.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Acked-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 net/netfilter/nf_tables_api.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index e92bedd09cde..7495f29d24e8 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -2239,6 +2239,7 @@ static const struct nla_policy nft_rule_policy[NFTA_RULE_MAX + 1] = {
 	[NFTA_RULE_USERDATA]	= { .type = NLA_BINARY,
 				    .len = NFT_USERDATA_MAXLEN },
 	[NFTA_RULE_ID]		= { .type = NLA_U32 },
+	[NFTA_RULE_POSITION_ID]	= { .type = NLA_U32 },
 };
 
 static int nf_tables_fill_rule_info(struct sk_buff *skb, struct net *net,
-- 
2.11.0


^ permalink raw reply related

* [PATCH 03/11] netfilter: nat: remove module dependency on ipv6 core
From: Pablo Neira Ayuso @ 2019-02-17 23:23 UTC (permalink / raw)
  To: netfilter-devel; +Cc: davem, netdev
In-Reply-To: <20190217232357.29858-1-pablo@netfilter.org>

From: Florian Westphal <fw@strlen.de>

nf_nat_ipv6 calls two ipv6 core functions, so add those to v6ops to avoid
the module dependency.

This is a prerequisite for merging ipv4 and ipv6 nat implementations.

Add wrappers to avoid the indirection if ipv6 is builtin.

Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 include/linux/netfilter_ipv6.h              |  6 ++++++
 net/ipv6/netfilter.c                        |  4 ++++
 net/ipv6/netfilter/nf_nat_l3proto_ipv6.c    | 17 ++++++++++++++++-
 net/ipv6/netfilter/nf_nat_masquerade_ipv6.c | 21 +++++++++++++++++++--
 4 files changed, 45 insertions(+), 3 deletions(-)

diff --git a/include/linux/netfilter_ipv6.h b/include/linux/netfilter_ipv6.h
index c0dc4dd78887..ad4223c10488 100644
--- a/include/linux/netfilter_ipv6.h
+++ b/include/linux/netfilter_ipv6.h
@@ -33,6 +33,12 @@ struct nf_ipv6_ops {
 	int (*route)(struct net *net, struct dst_entry **dst, struct flowi *fl,
 		     bool strict);
 	int (*reroute)(struct sk_buff *skb, const struct nf_queue_entry *entry);
+#if IS_MODULE(CONFIG_IPV6)
+	int (*route_me_harder)(struct net *net, struct sk_buff *skb);
+	int (*dev_get_saddr)(struct net *net, const struct net_device *dev,
+		       const struct in6_addr *daddr, unsigned int srcprefs,
+		       struct in6_addr *saddr);
+#endif
 };
 
 #ifdef CONFIG_NETFILTER
diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c
index 8b075f0bc351..0a5caf263889 100644
--- a/net/ipv6/netfilter.c
+++ b/net/ipv6/netfilter.c
@@ -112,6 +112,10 @@ static const struct nf_ipv6_ops ipv6ops = {
 	.fragment		= ip6_fragment,
 	.route			= nf_ip6_route,
 	.reroute		= nf_ip6_reroute,
+#if IS_MODULE(CONFIG_IPV6)
+	.route_me_harder	= ip6_route_me_harder,
+	.dev_get_saddr		= ipv6_dev_get_saddr,
+#endif
 };
 
 int __init ipv6_netfilter_init(void)
diff --git a/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c b/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c
index 9c914db44bec..b52026adb3e7 100644
--- a/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c
@@ -17,6 +17,7 @@
 #include <net/checksum.h>
 #include <net/ip6_checksum.h>
 #include <net/ip6_route.h>
+#include <net/xfrm.h>
 #include <net/ipv6.h>
 
 #include <net/netfilter/nf_conntrack_core.h>
@@ -317,6 +318,20 @@ nf_nat_ipv6_out(void *priv, struct sk_buff *skb,
 	return ret;
 }
 
+static int nat_route_me_harder(struct net *net, struct sk_buff *skb)
+{
+#ifdef CONFIG_IPV6_MODULE
+	const struct nf_ipv6_ops *v6_ops = nf_get_ipv6_ops();
+
+	if (!v6_ops)
+		return -EHOSTUNREACH;
+
+	return v6_ops->route_me_harder(net, skb);
+#else
+	return ip6_route_me_harder(net, skb);
+#endif
+}
+
 static unsigned int
 nf_nat_ipv6_local_fn(void *priv, struct sk_buff *skb,
 		     const struct nf_hook_state *state)
@@ -333,7 +348,7 @@ nf_nat_ipv6_local_fn(void *priv, struct sk_buff *skb,
 
 		if (!nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.dst.u3,
 				      &ct->tuplehash[!dir].tuple.src.u3)) {
-			err = ip6_route_me_harder(state->net, skb);
+			err = nat_route_me_harder(state->net, skb);
 			if (err < 0)
 				ret = NF_DROP_ERR(err);
 		}
diff --git a/net/ipv6/netfilter/nf_nat_masquerade_ipv6.c b/net/ipv6/netfilter/nf_nat_masquerade_ipv6.c
index 0ad0da5a2600..fd313b726263 100644
--- a/net/ipv6/netfilter/nf_nat_masquerade_ipv6.c
+++ b/net/ipv6/netfilter/nf_nat_masquerade_ipv6.c
@@ -24,6 +24,23 @@
 
 static atomic_t v6_worker_count;
 
+static int
+nat_ipv6_dev_get_saddr(struct net *net, const struct net_device *dev,
+		       const struct in6_addr *daddr, unsigned int srcprefs,
+		       struct in6_addr *saddr)
+{
+#ifdef CONFIG_IPV6_MODULE
+	const struct nf_ipv6_ops *v6_ops = nf_get_ipv6_ops();
+
+	if (!v6_ops)
+		return -EHOSTUNREACH;
+
+	return v6_ops->dev_get_saddr(net, dev, daddr, srcprefs, saddr);
+#else
+	return ipv6_dev_get_saddr(net, dev, daddr, srcprefs, saddr);
+#endif
+}
+
 unsigned int
 nf_nat_masquerade_ipv6(struct sk_buff *skb, const struct nf_nat_range2 *range,
 		       const struct net_device *out)
@@ -38,8 +55,8 @@ nf_nat_masquerade_ipv6(struct sk_buff *skb, const struct nf_nat_range2 *range,
 	WARN_ON(!(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED ||
 			 ctinfo == IP_CT_RELATED_REPLY)));
 
-	if (ipv6_dev_get_saddr(nf_ct_net(ct), out,
-			       &ipv6_hdr(skb)->daddr, 0, &src) < 0)
+	if (nat_ipv6_dev_get_saddr(nf_ct_net(ct), out,
+				   &ipv6_hdr(skb)->daddr, 0, &src) < 0)
 		return NF_DROP;
 
 	nat = nf_ct_nat_ext_add(ct);
-- 
2.11.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