* Re: [PATCH net] af_packet: Block execution of tasks waiting for transmit to complete in AF_PACKET
From: Neil Horman @ 2019-06-20 17:31 UTC (permalink / raw)
To: Willem de Bruijn; +Cc: Network Development, Matteo Croce, David S. Miller
In-Reply-To: <CAF=yD-KtqhHfzRtMVm17f1gfZRuSacB1M-QBSP8dY5Kz_Cn+Yw@mail.gmail.com>
On Thu, Jun 20, 2019 at 12:18:41PM -0400, Willem de Bruijn wrote:
> On Thu, Jun 20, 2019 at 12:14 PM Neil Horman <nhorman@tuxdriver.com> wrote:
> >
> > On Thu, Jun 20, 2019 at 11:16:13AM -0400, Willem de Bruijn wrote:
> > > On Thu, Jun 20, 2019 at 10:24 AM Neil Horman <nhorman@tuxdriver.com> wrote:
> > > >
> > > > On Thu, Jun 20, 2019 at 09:41:30AM -0400, Willem de Bruijn wrote:
> > > > > On Wed, Jun 19, 2019 at 4:26 PM Neil Horman <nhorman@tuxdriver.com> wrote:
> > > > > >
> > > > > > When an application is run that:
> > > > > > a) Sets its scheduler to be SCHED_FIFO
> > > > > > and
> > > > > > b) Opens a memory mapped AF_PACKET socket, and sends frames with the
> > > > > > MSG_DONTWAIT flag cleared, its possible for the application to hang
> > > > > > forever in the kernel. This occurs because when waiting, the code in
> > > > > > tpacket_snd calls schedule, which under normal circumstances allows
> > > > > > other tasks to run, including ksoftirqd, which in some cases is
> > > > > > responsible for freeing the transmitted skb (which in AF_PACKET calls a
> > > > > > destructor that flips the status bit of the transmitted frame back to
> > > > > > available, allowing the transmitting task to complete).
> > > > > >
> > > > > > However, when the calling application is SCHED_FIFO, its priority is
> > > > > > such that the schedule call immediately places the task back on the cpu,
> > > > > > preventing ksoftirqd from freeing the skb, which in turn prevents the
> > > > > > transmitting task from detecting that the transmission is complete.
> > > > > >
> > > > > > We can fix this by converting the schedule call to a completion
> > > > > > mechanism. By using a completion queue, we force the calling task, when
> > > > > > it detects there are no more frames to send, to schedule itself off the
> > > > > > cpu until such time as the last transmitted skb is freed, allowing
> > > > > > forward progress to be made.
> > > > > >
> > > > > > Tested by myself and the reporter, with good results
> > > > > >
> > > > > > Appies to the net tree
> > > > > >
> > > > > > Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
> > > > > > Reported-by: Matteo Croce <mcroce@redhat.com>
> > > > > > CC: "David S. Miller" <davem@davemloft.net>
> > > > > > ---
> > > > >
> > > > > This is a complex change for a narrow configuration. Isn't a
> > > > > SCHED_FIFO process preempting ksoftirqd a potential problem for other
> > > > > networking workloads as well? And the right configuration to always
> > > > > increase ksoftirqd priority when increasing another process's
> > > > > priority? Also, even when ksoftirqd kicks in, isn't some progress
> > > > > still made on the local_bh_enable reached from schedule()?
> > > > >
> > > >
> > > > A few questions here to answer:
> > >
> > > Thanks for the detailed explanation.
> > >
> > Gladly.
> >
> > > > Regarding other protocols having this problem, thats not the case, because non
> > > > packet sockets honor the SK_SNDTIMEO option here (i.e. they sleep for a period
> > > > of time specified by the SNDTIMEO option if MSG_DONTWAIT isn't set. We could
> > > > certainly do that, but the current implementation doesn't (opting instead to
> > > > wait indefinately until the respective packet(s) have transmitted or errored
> > > > out), and I wanted to maintain that behavior. If there is consensus that packet
> > > > sockets should honor SNDTIMEO, then I can certainly do that.
> > > >
> > > > As for progress made by calling local_bh_enable, My read of the code doesn't
> > > > have the scheduler calling local_bh_enable at all. Instead schedule uses
> > > > preempt_disable/preempt_enable_no_resched() to gain exlcusive access to the cpu,
> > > > which ignores pending softirqs on re-enablement.
> > >
> > > Ah, I'm mistaken there, then.
> > >
> > > > Perhaps that needs to change,
> > > > but I'm averse to making scheduler changes for this (the aforementioned concern
> > > > about complex changes for a narrow use case)
> > > >
> > > > Regarding raising the priority of ksoftirqd, that could be a solution, but the
> > > > priority would need to be raised to a high priority SCHED_FIFO parameter, and
> > > > that gets back to making complex changes for a narrow problem domain
> > > >
> > > > As for the comlexity of the of the solution, I think this is, given your
> > > > comments the least complex and intrusive change to solve the given problem.
> > >
> > > Could it be simpler to ensure do_softirq() gets run here? That would
> > > allow progress for this case.
> > >
> > I'm not sure. On the surface, we certainly could do it, but inserting a call to
> > do_softirq, either directly, or indirectly through some other mechanism seems
> > like a non-obvious fix, and may lead to confusion down the road. I'm hesitant
> > to pursue such a soultion without some evidence it would make a better solution.
> >
> > > > We
> > > > need to find a way to force the calling task off the cpu while the asynchronous
> > > > operations in the transmit path complete, and we can do that this way, or by
> > > > honoring SK_SNDTIMEO. I'm fine with doing the latter, but I didn't want to
> > > > alter the current protocol behavior without consensus on that.
> > >
> > > In general SCHED_FIFO is dangerous with regard to stalling other
> > > progress, incl. ksoftirqd. But it does appear that this packet socket
> > > case is special inside networking in calling schedule() directly here.
> > >
> > > If converting that, should it convert to logic more akin to other
> > > sockets, like sock_wait_for_wmem? I haven't had a chance to read up on
> > > the pros and cons of completion here yet, sorry. Didn't want to delay
> > > responding until after I get a chance.
> > >
> > That would be the solution described above (i.e. honoring SK_SNDTIMEO.
> > Basically you call sock_send_waittimeo, which returns a timeout value, or 0 if
> > MSG_DONTWAIT is set), then you block for that period of time waiting for
> > transmit completion.
>
> From an ABI point of view, starting to support SK_SNDTIMEO where it
> currently is not implemented certainly seems fine.
>
I would agree, I was just thinking since AF_PACKET is something of a unique
protocol (i.e. no real protocol), there may have been reason to ignore that
option, but I agree, it probably makes sense, barring no counter reasoning.
> > I'm happy to implement that solution, but I'd like to get
> > some clarity as to if there is a reason we don't currently honor that socket
> > option now before I change the behavior that way.
> >
> > Dave, do you have any insight into AF_PACKET history as to why we would ignore
> > the send timeout socket option here?
>
> On the point of calling schedule(): even if that is rare, there are a lot of
> other cond_resched() calls that may have the same starvation issue
> with SCHED_FIFO and ksoftirqd.
>
Agreed, but I've not found any yet
Neil
^ permalink raw reply
* Re: [PATCH v2 net-next 2/2] net: dsa: mt7530: Add MT7621 TRGMII mode support
From: Frank Wunderlich @ 2019-06-20 17:32 UTC (permalink / raw)
To: René van Dorst, sean.wang, f.fainelli, davem, matthias.bgg,
andrew, vivien.didelot
Cc: netdev, john, linux-mediatek, linux-mips
In-Reply-To: <20190620122155.32078-3-opensource@vdorst.com>
Tested on Bananapi R2 (mt7623) with 5.2-rc5 + net-next
Tested-by: Frank Wunderlich <frank-w@public-files.de>
Am 20. Juni 2019 14:21:55 MESZ schrieb "René van Dorst" <opensource@vdorst.com>:
>This patch add support TRGMII mode for MT7621 internal MT7530 switch.
>MT7621 TRGMII has only one fix speed mode of 1200MBit.
>
>Also adding support for mt7530 25MHz and 40MHz crystal clocksource.
>Values are based on Banana Pi R2 bsp [1].
>
>Don't change MT7623 registers on a MT7621 device.
>
>[1]
>https://github.com/BPI-SINOVOIP/BPI-R2-bsp/blob/master/linux-mt/drivers/net/ethernet/mediatek/gsw_mt7623.c#L769
>
>Signed-off-by: René van Dorst <opensource@vdorst.com>
>---
> drivers/net/dsa/mt7530.c | 46 +++++++++++++++++++++++++++++++---------
> drivers/net/dsa/mt7530.h | 4 ++++
> 2 files changed, 40 insertions(+), 10 deletions(-)
>
>diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
>index c7d352da5448..3181e95586d6 100644
>--- a/drivers/net/dsa/mt7530.c
>+++ b/drivers/net/dsa/mt7530.c
>@@ -428,24 +428,48 @@ static int
> mt7530_pad_clk_setup(struct dsa_switch *ds, int mode)
> {
> struct mt7530_priv *priv = ds->priv;
>- u32 ncpo1, ssc_delta, trgint, i;
>+ u32 ncpo1, ssc_delta, trgint, i, xtal;
>+
>+ xtal = mt7530_read(priv, MT7530_MHWTRAP) & HWTRAP_XTAL_MASK;
>+
>+ if (xtal == HWTRAP_XTAL_20MHZ) {
>+ dev_err(priv->dev,
>+ "%s: MT7530 with a 20MHz XTAL is not supported!\n",
>+ __func__);
>+ return -EINVAL;
>+ }
>
> switch (mode) {
> case PHY_INTERFACE_MODE_RGMII:
> trgint = 0;
>+ /* PLL frequency: 125MHz */
> ncpo1 = 0x0c80;
>- ssc_delta = 0x87;
> break;
> case PHY_INTERFACE_MODE_TRGMII:
> trgint = 1;
>- ncpo1 = 0x1400;
>- ssc_delta = 0x57;
>+ if (priv->id == ID_MT7621) {
>+ /* PLL frequency: 150MHz: 1.2GBit */
>+ if (xtal == HWTRAP_XTAL_40MHZ)
>+ ncpo1 = 0x0780;
>+ if (xtal == HWTRAP_XTAL_25MHZ)
>+ ncpo1 = 0x0a00;
>+ } else { /* PLL frequency: 250MHz: 2.0Gbit */
>+ if (xtal == HWTRAP_XTAL_40MHZ)
>+ ncpo1 = 0x0c80;
>+ if (xtal == HWTRAP_XTAL_25MHZ)
>+ ncpo1 = 0x1400;
>+ }
> break;
> default:
> dev_err(priv->dev, "xMII mode %d not supported\n", mode);
> return -EINVAL;
> }
>
>+ if (xtal == HWTRAP_XTAL_25MHZ)
>+ ssc_delta = 0x57;
>+ else
>+ ssc_delta = 0x87;
>+
> mt7530_rmw(priv, MT7530_P6ECR, P6_INTF_MODE_MASK,
> P6_INTF_MODE(trgint));
>
>@@ -507,7 +531,9 @@ mt7530_pad_clk_setup(struct dsa_switch *ds, int
>mode)
> mt7530_rmw(priv, MT7530_TRGMII_RD(i),
> RD_TAP_MASK, RD_TAP(16));
> else
>- mt7623_trgmii_set(priv, GSW_INTF_MODE, INTF_MODE_TRGMII);
>+ if (priv->id != ID_MT7621)
>+ mt7623_trgmii_set(priv, GSW_INTF_MODE,
>+ INTF_MODE_TRGMII);
>
> return 0;
> }
>@@ -613,13 +639,13 @@ static void mt7530_adjust_link(struct dsa_switch
>*ds, int port,
> struct mt7530_priv *priv = ds->priv;
>
> if (phy_is_pseudo_fixed_link(phydev)) {
>- if (priv->id == ID_MT7530) {
>- dev_dbg(priv->dev, "phy-mode for master device = %x\n",
>- phydev->interface);
>+ dev_dbg(priv->dev, "phy-mode for master device = %x\n",
>+ phydev->interface);
>
>- /* Setup TX circuit incluing relevant PAD and driving */
>- mt7530_pad_clk_setup(ds, phydev->interface);
>+ /* Setup TX circuit incluing relevant PAD and driving */
>+ mt7530_pad_clk_setup(ds, phydev->interface);
>
>+ if (priv->id == ID_MT7530) {
> /* Setup RX circuit, relevant PAD and driving on the
> * host which must be placed after the setup on the
> * device side is all finished.
>diff --git a/drivers/net/dsa/mt7530.h b/drivers/net/dsa/mt7530.h
>index 4331429969fa..bfac90f48102 100644
>--- a/drivers/net/dsa/mt7530.h
>+++ b/drivers/net/dsa/mt7530.h
>@@ -244,6 +244,10 @@ enum mt7530_vlan_port_attr {
>
> /* Register for hw trap status */
> #define MT7530_HWTRAP 0x7800
>+#define HWTRAP_XTAL_MASK (BIT(10) | BIT(9))
>+#define HWTRAP_XTAL_25MHZ (BIT(10) | BIT(9))
>+#define HWTRAP_XTAL_40MHZ (BIT(10))
>+#define HWTRAP_XTAL_20MHZ (BIT(9))
>
> /* Register for hw trap modification */
> #define MT7530_MHWTRAP 0x7804
^ permalink raw reply
* Re: [PATCH net] net/sched: flower: fix infinite loop in fl_walk()
From: Cong Wang @ 2019-06-20 17:33 UTC (permalink / raw)
To: Davide Caratti
Cc: Vlad Buslov, David S. Miller, Linux Kernel Network Developers,
Lucas Bates
In-Reply-To: <53b8c3118900b31536594e98952640c03a4456e0.camel@redhat.com>
On Thu, Jun 20, 2019 at 5:52 AM Davide Caratti <dcaratti@redhat.com> wrote:
>
> hello Cong, thanks for reading.
>
> On Wed, 2019-06-19 at 15:04 -0700, Cong Wang wrote:
> > On Wed, Jun 19, 2019 at 2:10 PM Davide Caratti <dcaratti@redhat.com> wrote:
> > > on some CPUs (e.g. i686), tcf_walker.cookie has the same size as the IDR.
> > > In this situation, the following script:
> > >
> > > # tc filter add dev eth0 ingress handle 0xffffffff flower action ok
> > > # tc filter show dev eth0 ingress
> > >
> > > results in an infinite loop. It happened also on other CPUs (e.g x86_64),
> > > before commit 061775583e35 ("net: sched: flower: introduce reference
> > > counting for filters"), because 'handle' + 1 made the u32 overflow before
> > > it was assigned to 'cookie'; but that commit replaced the assignment with
> > > a self-increment of 'cookie', so the problem was indirectly fixed.
> >
> > Interesting... Is this really specific to cls_flower? To me it looks like
> > a bug of idr_*_ul() API's, especially for idr_for_each_entry_ul().
>
> good question, I have to investigate this better (idr_for_each_entry_ul()
> expands in a iteration of idr_get_next_ul()). It surely got in cls_flower
> when it was converted to use IDRs, but it's true that there might be other
> points in TC where IDR are used and the same pattern is present (see
> below).
Yeah, this means we probably want to fix it in idr_get_next_ul() or its
callers like idr_for_each_entry_ul().
>
> > Can you test if the following command has the same problem on i386?
> >
> > tc actions add action ok index 4294967295
>
> the action is added, but then reading it back results in an infinite loop.
> And again, the infinite loop happens on i686 and not on x86_64. I will try
> to see where's the problem also here.
Right, this is what I expect, thanks for confirming it.
I am not sure it is better to handle this overflow inside idr_get_next_ul()
or just let its callers to handle it. According to the comments above
idr_get_next_ul() it sounds like it is not expected to overflow, so...
diff --git a/lib/idr.c b/lib/idr.c
index c34e256d2f01..a38f5e391cec 100644
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -267,6 +267,9 @@ void *idr_get_next_ul(struct idr *idr, unsigned
long *nextid)
if (!slot)
return NULL;
+ /* overflow */
+ if (iter.index < id)
+ return NULL;
*nextid = iter.index + base;
return rcu_dereference_raw(*slot);
}
^ permalink raw reply related
* [PATCH 4.19 10/61] sctp: Free cookie before we memdup a new one
From: Greg Kroah-Hartman @ 2019-06-20 17:57 UTC (permalink / raw)
To: linux-kernel
Cc: Greg Kroah-Hartman, stable, Neil Horman,
syzbot+f7e9153b037eac9b1df8, Marcelo Ricardo Leitner, Xin Long,
David S. Miller, netdev
In-Reply-To: <20190620174336.357373754@linuxfoundation.org>
From: Neil Horman <nhorman@tuxdriver.com>
[ Upstream commit ce950f1050cece5e406a5cde723c69bba60e1b26 ]
Based on comments from Xin, even after fixes for our recent syzbot
report of cookie memory leaks, its possible to get a resend of an INIT
chunk which would lead to us leaking cookie memory.
To ensure that we don't leak cookie memory, free any previously
allocated cookie first.
Change notes
v1->v2
update subsystem tag in subject (davem)
repeat kfree check for peer_random and peer_hmacs (xin)
v2->v3
net->sctp
also free peer_chunks
v3->v4
fix subject tags
v4->v5
remove cut line
Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
Reported-by: syzbot+f7e9153b037eac9b1df8@syzkaller.appspotmail.com
CC: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
CC: Xin Long <lucien.xin@gmail.com>
CC: "David S. Miller" <davem@davemloft.net>
CC: netdev@vger.kernel.org
Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/sctp/sm_make_chunk.c | 8 ++++++++
1 file changed, 8 insertions(+)
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -2600,6 +2600,8 @@ do_addr_param:
case SCTP_PARAM_STATE_COOKIE:
asoc->peer.cookie_len =
ntohs(param.p->length) - sizeof(struct sctp_paramhdr);
+ if (asoc->peer.cookie)
+ kfree(asoc->peer.cookie);
asoc->peer.cookie = kmemdup(param.cookie->body, asoc->peer.cookie_len, gfp);
if (!asoc->peer.cookie)
retval = 0;
@@ -2664,6 +2666,8 @@ do_addr_param:
goto fall_through;
/* Save peer's random parameter */
+ if (asoc->peer.peer_random)
+ kfree(asoc->peer.peer_random);
asoc->peer.peer_random = kmemdup(param.p,
ntohs(param.p->length), gfp);
if (!asoc->peer.peer_random) {
@@ -2677,6 +2681,8 @@ do_addr_param:
goto fall_through;
/* Save peer's HMAC list */
+ if (asoc->peer.peer_hmacs)
+ kfree(asoc->peer.peer_hmacs);
asoc->peer.peer_hmacs = kmemdup(param.p,
ntohs(param.p->length), gfp);
if (!asoc->peer.peer_hmacs) {
@@ -2692,6 +2698,8 @@ do_addr_param:
if (!ep->auth_enable)
goto fall_through;
+ if (asoc->peer.peer_chunks)
+ kfree(asoc->peer.peer_chunks);
asoc->peer.peer_chunks = kmemdup(param.p,
ntohs(param.p->length), gfp);
if (!asoc->peer.peer_chunks)
^ permalink raw reply
* [PATCH 5.1 12/98] sctp: Free cookie before we memdup a new one
From: Greg Kroah-Hartman @ 2019-06-20 17:56 UTC (permalink / raw)
To: linux-kernel
Cc: Greg Kroah-Hartman, stable, Neil Horman,
syzbot+f7e9153b037eac9b1df8, Marcelo Ricardo Leitner, Xin Long,
David S. Miller, netdev
In-Reply-To: <20190620174349.443386789@linuxfoundation.org>
From: Neil Horman <nhorman@tuxdriver.com>
[ Upstream commit ce950f1050cece5e406a5cde723c69bba60e1b26 ]
Based on comments from Xin, even after fixes for our recent syzbot
report of cookie memory leaks, its possible to get a resend of an INIT
chunk which would lead to us leaking cookie memory.
To ensure that we don't leak cookie memory, free any previously
allocated cookie first.
Change notes
v1->v2
update subsystem tag in subject (davem)
repeat kfree check for peer_random and peer_hmacs (xin)
v2->v3
net->sctp
also free peer_chunks
v3->v4
fix subject tags
v4->v5
remove cut line
Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
Reported-by: syzbot+f7e9153b037eac9b1df8@syzkaller.appspotmail.com
CC: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
CC: Xin Long <lucien.xin@gmail.com>
CC: "David S. Miller" <davem@davemloft.net>
CC: netdev@vger.kernel.org
Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/sctp/sm_make_chunk.c | 8 ++++++++
1 file changed, 8 insertions(+)
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -2600,6 +2600,8 @@ do_addr_param:
case SCTP_PARAM_STATE_COOKIE:
asoc->peer.cookie_len =
ntohs(param.p->length) - sizeof(struct sctp_paramhdr);
+ if (asoc->peer.cookie)
+ kfree(asoc->peer.cookie);
asoc->peer.cookie = kmemdup(param.cookie->body, asoc->peer.cookie_len, gfp);
if (!asoc->peer.cookie)
retval = 0;
@@ -2664,6 +2666,8 @@ do_addr_param:
goto fall_through;
/* Save peer's random parameter */
+ if (asoc->peer.peer_random)
+ kfree(asoc->peer.peer_random);
asoc->peer.peer_random = kmemdup(param.p,
ntohs(param.p->length), gfp);
if (!asoc->peer.peer_random) {
@@ -2677,6 +2681,8 @@ do_addr_param:
goto fall_through;
/* Save peer's HMAC list */
+ if (asoc->peer.peer_hmacs)
+ kfree(asoc->peer.peer_hmacs);
asoc->peer.peer_hmacs = kmemdup(param.p,
ntohs(param.p->length), gfp);
if (!asoc->peer.peer_hmacs) {
@@ -2692,6 +2698,8 @@ do_addr_param:
if (!ep->auth_enable)
goto fall_through;
+ if (asoc->peer.peer_chunks)
+ kfree(asoc->peer.peer_chunks);
asoc->peer.peer_chunks = kmemdup(param.p,
ntohs(param.p->length), gfp);
if (!asoc->peer.peer_chunks)
^ permalink raw reply
* [PATCH 4.14 08/45] sctp: Free cookie before we memdup a new one
From: Greg Kroah-Hartman @ 2019-06-20 17:57 UTC (permalink / raw)
To: linux-kernel
Cc: Greg Kroah-Hartman, stable, Neil Horman,
syzbot+f7e9153b037eac9b1df8, Marcelo Ricardo Leitner, Xin Long,
David S. Miller, netdev
In-Reply-To: <20190620174328.608036501@linuxfoundation.org>
From: Neil Horman <nhorman@tuxdriver.com>
[ Upstream commit ce950f1050cece5e406a5cde723c69bba60e1b26 ]
Based on comments from Xin, even after fixes for our recent syzbot
report of cookie memory leaks, its possible to get a resend of an INIT
chunk which would lead to us leaking cookie memory.
To ensure that we don't leak cookie memory, free any previously
allocated cookie first.
Change notes
v1->v2
update subsystem tag in subject (davem)
repeat kfree check for peer_random and peer_hmacs (xin)
v2->v3
net->sctp
also free peer_chunks
v3->v4
fix subject tags
v4->v5
remove cut line
Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
Reported-by: syzbot+f7e9153b037eac9b1df8@syzkaller.appspotmail.com
CC: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
CC: Xin Long <lucien.xin@gmail.com>
CC: "David S. Miller" <davem@davemloft.net>
CC: netdev@vger.kernel.org
Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/sctp/sm_make_chunk.c | 8 ++++++++
1 file changed, 8 insertions(+)
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -2586,6 +2586,8 @@ do_addr_param:
case SCTP_PARAM_STATE_COOKIE:
asoc->peer.cookie_len =
ntohs(param.p->length) - sizeof(struct sctp_paramhdr);
+ if (asoc->peer.cookie)
+ kfree(asoc->peer.cookie);
asoc->peer.cookie = kmemdup(param.cookie->body, asoc->peer.cookie_len, gfp);
if (!asoc->peer.cookie)
retval = 0;
@@ -2650,6 +2652,8 @@ do_addr_param:
goto fall_through;
/* Save peer's random parameter */
+ if (asoc->peer.peer_random)
+ kfree(asoc->peer.peer_random);
asoc->peer.peer_random = kmemdup(param.p,
ntohs(param.p->length), gfp);
if (!asoc->peer.peer_random) {
@@ -2663,6 +2667,8 @@ do_addr_param:
goto fall_through;
/* Save peer's HMAC list */
+ if (asoc->peer.peer_hmacs)
+ kfree(asoc->peer.peer_hmacs);
asoc->peer.peer_hmacs = kmemdup(param.p,
ntohs(param.p->length), gfp);
if (!asoc->peer.peer_hmacs) {
@@ -2678,6 +2684,8 @@ do_addr_param:
if (!ep->auth_enable)
goto fall_through;
+ if (asoc->peer.peer_chunks)
+ kfree(asoc->peer.peer_chunks);
asoc->peer.peer_chunks = kmemdup(param.p,
ntohs(param.p->length), gfp);
if (!asoc->peer.peer_chunks)
^ permalink raw reply
* [PATCH v2 3/3] net: fddi: skfp: Remove unused private PCI definitions
From: Puranjay Mohan @ 2019-06-20 18:07 UTC (permalink / raw)
To: Shuah Khan
Cc: Puranjay Mohan, Bjorn Helgaas, netdev, Linux Kernel Mailing List,
linux-kernel-mentees, linux-pci
In-Reply-To: <20190620180754.15413-1-puranjay12@gmail.com>
Remove unused and private PCI definitions from skfbi.h because generic PCI
symbols are already included from pci_regs.h.
Signed-off-by: Puranjay Mohan <puranjay12@gmail.com>
---
drivers/net/fddi/skfp/h/skfbi.h | 207 +-------------------------------
1 file changed, 1 insertion(+), 206 deletions(-)
diff --git a/drivers/net/fddi/skfp/h/skfbi.h b/drivers/net/fddi/skfp/h/skfbi.h
index a05ce16171be..a8af80148022 100644
--- a/drivers/net/fddi/skfp/h/skfbi.h
+++ b/drivers/net/fddi/skfp/h/skfbi.h
@@ -27,46 +27,6 @@
/*
* Configuration Space header
*/
-#define PCI_VENDOR_ID 0x00 /* 16 bit Vendor ID */
-#define PCI_DEVICE_ID 0x02 /* 16 bit Device ID */
-#define PCI_COMMAND 0x04 /* 16 bit Command */
-#define PCI_STATUS 0x06 /* 16 bit Status */
-#define PCI_REVISION_ID 0x08 /* 8 bit Revision ID */
-#define PCI_CLASS_CODE 0x09 /* 24 bit Class Code */
-#define PCI_CACHE_LSZ 0x0c /* 8 bit Cache Line Size */
-#define PCI_LAT_TIM 0x0d /* 8 bit Latency Timer */
-#define PCI_HEADER_T 0x0e /* 8 bit Header Type */
-#define PCI_BIST 0x0f /* 8 bit Built-in selftest */
-#define PCI_BASE_1ST 0x10 /* 32 bit 1st Base address */
-#define PCI_BASE_2ND 0x14 /* 32 bit 2nd Base address */
-/* Byte 18..2b: Reserved */
-#define PCI_SUB_VID 0x2c /* 16 bit Subsystem Vendor ID */
-#define PCI_SUB_ID 0x2e /* 16 bit Subsystem ID */
-#define PCI_BASE_ROM 0x30 /* 32 bit Expansion ROM Base Address */
-/* Byte 34..33: Reserved */
-#define PCI_CAP_PTR 0x34 /* 8 bit (ML) Capabilities Ptr */
-/* Byte 35..3b: Reserved */
-#define PCI_IRQ_LINE 0x3c /* 8 bit Interrupt Line */
-#define PCI_IRQ_PIN 0x3d /* 8 bit Interrupt Pin */
-#define PCI_MIN_GNT 0x3e /* 8 bit Min_Gnt */
-#define PCI_MAX_LAT 0x3f /* 8 bit Max_Lat */
-/* Device Dependent Region */
-#define PCI_OUR_REG 0x40 /* 32 bit (DV) Our Register */
-#define PCI_OUR_REG_1 0x40 /* 32 bit (ML) Our Register 1 */
-#define PCI_OUR_REG_2 0x44 /* 32 bit (ML) Our Register 2 */
-/* Power Management Region */
-#define PCI_PM_CAP_ID 0x48 /* 8 bit (ML) Power Management Cap. ID */
-#define PCI_PM_NITEM 0x49 /* 8 bit (ML) Next Item Ptr */
-#define PCI_PM_CAP_REG 0x4a /* 16 bit (ML) Power Management Capabilities */
-#define PCI_PM_CTL_STS 0x4c /* 16 bit (ML) Power Manag. Control/Status */
-/* Byte 0x4e: Reserved */
-#define PCI_PM_DAT_REG 0x4f /* 8 bit (ML) Power Manag. Data Register */
-/* VPD Region */
-#define PCI_VPD_CAP_ID 0x50 /* 8 bit (ML) VPD Cap. ID */
-#define PCI_VPD_NITEM 0x51 /* 8 bit (ML) Next Item Ptr */
-#define PCI_VPD_ADR_REG 0x52 /* 16 bit (ML) VPD Address Register */
-#define PCI_VPD_DAT_REG 0x54 /* 32 bit (ML) VPD Data Register */
-/* Byte 58..ff: Reserved */
/*
* I2C Address (PCI Config)
@@ -74,179 +34,14 @@
* Note: The temperature and voltage sensors are relocated on a different
* I2C bus.
*/
-#define I2C_ADDR_VPD 0xA0 /* I2C address for the VPD EEPROM */
+#define I2C_ADDR_VPD 0xA0 /* I2C address for the VPD EEPROM */
-/*
- * Define Bits and Values of the registers
- */
-/* PCI_VENDOR_ID 16 bit Vendor ID */
-/* PCI_DEVICE_ID 16 bit Device ID */
-/* Values for Vendor ID and Device ID shall be patched into the code */
-/* PCI_COMMAND 16 bit Command */
-#define PCI_FBTEN 0x0200 /* Bit 9: Fast Back-To-Back enable */
-#define PCI_SERREN 0x0100 /* Bit 8: SERR enable */
-#define PCI_ADSTEP 0x0080 /* Bit 7: Address Stepping */
-#define PCI_PERREN 0x0040 /* Bit 6: Parity Report Response enable */
-#define PCI_VGA_SNOOP 0x0020 /* Bit 5: VGA palette snoop */
-#define PCI_MWIEN 0x0010 /* Bit 4: Memory write an inv cycl ena */
-#define PCI_SCYCEN 0x0008 /* Bit 3: Special Cycle enable */
-#define PCI_BMEN 0x0004 /* Bit 2: Bus Master enable */
-#define PCI_MEMEN 0x0002 /* Bit 1: Memory Space Access enable */
-#define PCI_IOEN 0x0001 /* Bit 0: IO Space Access enable */
-
-/* PCI_STATUS 16 bit Status */
#define PCI_PERR 0x8000 /* Bit 15: Parity Error */
#define PCI_SERR 0x4000 /* Bit 14: Signaled SERR */
#define PCI_RMABORT 0x2000 /* Bit 13: Received Master Abort */
-#define PCI_RTABORT 0x1000 /* Bit 12: Received Target Abort */
#define PCI_STABORT 0x0800 /* Bit 11: Sent Target Abort */
-#define PCI_DEVSEL 0x0600 /* Bit 10..9: DEVSEL Timing */
-#define PCI_DEV_FAST (0<<9) /* fast */
-#define PCI_DEV_MEDIUM (1<<9) /* medium */
-#define PCI_DEV_SLOW (2<<9) /* slow */
#define PCI_DATAPERR 0x0100 /* Bit 8: DATA Parity error detected */
-#define PCI_FB2BCAP 0x0080 /* Bit 7: Fast Back-to-Back Capability */
-#define PCI_UDF 0x0040 /* Bit 6: User Defined Features */
-#define PCI_66MHZCAP 0x0020 /* Bit 5: 66 MHz PCI bus clock capable */
-#define PCI_NEWCAP 0x0010 /* Bit 4: New cap. list implemented */
-
#define PCI_ERRBITS (PCI_PERR|PCI_SERR|PCI_RMABORT|PCI_STABORT|PCI_DATAPERR)
-
-/* PCI_REV_ID 8 bit Revision ID */
-/* PCI_CLASS_CODE 24 bit Class Code */
-/* Byte 2: Base Class (02) */
-/* Byte 1: SubClass (02) */
-/* Byte 0: Programming Interface (00) */
-
-/* PCI_CACHE_LSZ 8 bit Cache Line Size */
-/* Possible values: 0,2,4,8,16 */
-
-/* PCI_LAT_TIM 8 bit Latency Timer */
-
-/* PCI_HEADER_T 8 bit Header Type */
-#define PCI_HD_MF_DEV 0x80 /* Bit 7: 0= single, 1= multi-func dev */
-#define PCI_HD_TYPE 0x7f /* Bit 6..0: Header Layout 0= normal */
-
-/* PCI_BIST 8 bit Built-in selftest */
-#define PCI_BIST_CAP 0x80 /* Bit 7: BIST Capable */
-#define PCI_BIST_ST 0x40 /* Bit 6: Start BIST */
-#define PCI_BIST_RET 0x0f /* Bit 3..0: Completion Code */
-
-/* PCI_BASE_1ST 32 bit 1st Base address */
-#define PCI_MEMSIZE 0x800L /* use 2 kB Memory Base */
-#define PCI_MEMBASE_BITS 0xfffff800L /* Bit 31..11: Memory Base Address */
-#define PCI_MEMSIZE_BIIS 0x000007f0L /* Bit 10..4: Memory Size Req. */
-#define PCI_PREFEN 0x00000008L /* Bit 3: Prefetchable */
-#define PCI_MEM_TYP 0x00000006L /* Bit 2..1: Memory Type */
-#define PCI_MEM32BIT (0<<1) /* Base addr anywhere in 32 Bit range */
-#define PCI_MEM1M (1<<1) /* Base addr below 1 MegaByte */
-#define PCI_MEM64BIT (2<<1) /* Base addr anywhere in 64 Bit range */
-#define PCI_MEMSPACE 0x00000001L /* Bit 0: Memory Space Indic. */
-
-/* PCI_SUB_VID 16 bit Subsystem Vendor ID */
-/* PCI_SUB_ID 16 bit Subsystem ID */
-
-/* PCI_BASE_ROM 32 bit Expansion ROM Base Address */
-#define PCI_ROMBASE 0xfffe0000L /* Bit 31..17: ROM BASE address (1st) */
-#define PCI_ROMBASZ 0x0001c000L /* Bit 16..14: Treat as BASE or SIZE */
-#define PCI_ROMSIZE 0x00003800L /* Bit 13..11: ROM Size Requirements */
-#define PCI_ROMEN 0x00000001L /* Bit 0: Address Decode enable */
-
-/* PCI_CAP_PTR 8 bit New Capabilities Pointers */
-/* PCI_IRQ_LINE 8 bit Interrupt Line */
-/* PCI_IRQ_PIN 8 bit Interrupt Pin */
-/* PCI_MIN_GNT 8 bit Min_Gnt */
-/* PCI_MAX_LAT 8 bit Max_Lat */
-/* Device Dependent Region */
-/* PCI_OUR_REG (DV) 32 bit Our Register */
-/* PCI_OUR_REG_1 (ML) 32 bit Our Register 1 */
- /* Bit 31..29: reserved */
-#define PCI_PATCH_DIR (3L<<27) /*(DV) Bit 28..27: Ext Patchs direction */
-#define PCI_PATCH_DIR_0 (1L<<27) /*(DV) Type of the pins EXT_PATCHS<1..0> */
-#define PCI_PATCH_DIR_1 (1L<<28) /* 0 = input */
- /* 1 = output */
-#define PCI_EXT_PATCHS (3L<<25) /*(DV) Bit 26..25: Extended Patches */
-#define PCI_EXT_PATCH_0 (1L<<25) /*(DV) */
-#define PCI_EXT_PATCH_1 (1L<<26) /* CLK for MicroWire (ML) */
-#define PCI_VIO (1L<<25) /*(ML) */
-#define PCI_EN_BOOT (1L<<24) /* Bit 24: Enable BOOT via ROM */
- /* 1 = Don't boot with ROM */
- /* 0 = Boot with ROM */
-#define PCI_EN_IO (1L<<23) /* Bit 23: Mapping to IO space */
-#define PCI_EN_FPROM (1L<<22) /* Bit 22: FLASH mapped to mem? */
- /* 1 = Map Flash to Memory */
- /* 0 = Disable all addr. decoding */
-#define PCI_PAGESIZE (3L<<20) /* Bit 21..20: FLASH Page Size */
-#define PCI_PAGE_16 (0L<<20) /* 16 k pages */
-#define PCI_PAGE_32K (1L<<20) /* 32 k pages */
-#define PCI_PAGE_64K (2L<<20) /* 64 k pages */
-#define PCI_PAGE_128K (3L<<20) /* 128 k pages */
- /* Bit 19: reserved (ML) and (DV) */
-#define PCI_PAGEREG (7L<<16) /* Bit 18..16: Page Register */
- /* Bit 15: reserved */
-#define PCI_FORCE_BE (1L<<14) /* Bit 14: Assert all BEs on MR */
-#define PCI_DIS_MRL (1L<<13) /* Bit 13: Disable Mem R Line */
-#define PCI_DIS_MRM (1L<<12) /* Bit 12: Disable Mem R multip */
-#define PCI_DIS_MWI (1L<<11) /* Bit 11: Disable Mem W & inv */
-#define PCI_DISC_CLS (1L<<10) /* Bit 10: Disc: cacheLsz bound */
-#define PCI_BURST_DIS (1L<<9) /* Bit 9: Burst Disable */
-#define PCI_BYTE_SWAP (1L<<8) /*(DV) Bit 8: Byte Swap in DATA */
-#define PCI_SKEW_DAS (0xfL<<4) /* Bit 7..4: Skew Ctrl, DAS Ext */
-#define PCI_SKEW_BASE (0xfL<<0) /* Bit 3..0: Skew Ctrl, Base */
-
-/* PCI_OUR_REG_2 (ML) 32 bit Our Register 2 (Monalisa only) */
-#define PCI_VPD_WR_TH (0xffL<<24) /* Bit 24..31 VPD Write Threshold */
-#define PCI_DEV_SEL (0x7fL<<17) /* Bit 17..23 EEPROM Device Select */
-#define PCI_VPD_ROM_SZ (7L<<14) /* Bit 14..16 VPD ROM Size */
- /* Bit 12..13 reserved */
-#define PCI_PATCH_DIR2 (0xfL<<8) /* Bit 8..11 Ext Patchs dir 2..5 */
-#define PCI_PATCH_DIR_2 (1L<<8) /* Bit 8 CS for MicroWire */
-#define PCI_PATCH_DIR_3 (1L<<9)
-#define PCI_PATCH_DIR_4 (1L<<10)
-#define PCI_PATCH_DIR_5 (1L<<11)
-#define PCI_EXT_PATCHS2 (0xfL<<4) /* Bit 4..7 Extended Patches */
-#define PCI_EXT_PATCH_2 (1L<<4) /* Bit 4 CS for MicroWire */
-#define PCI_EXT_PATCH_3 (1L<<5)
-#define PCI_EXT_PATCH_4 (1L<<6)
-#define PCI_EXT_PATCH_5 (1L<<7)
-#define PCI_EN_DUMMY_RD (1L<<3) /* Bit 3 Enable Dummy Read */
-#define PCI_REV_DESC (1L<<2) /* Bit 2 Reverse Desc. Bytes */
-#define PCI_USEADDR64 (1L<<1) /* Bit 1 Use 64 Bit Addresse */
-#define PCI_USEDATA64 (1L<<0) /* Bit 0 Use 64 Bit Data bus ext*/
-
-/* Power Management Region */
-/* PCI_PM_CAP_ID 8 bit (ML) Power Management Cap. ID */
-/* PCI_PM_NITEM 8 bit (ML) Next Item Ptr */
-/* PCI_PM_CAP_REG 16 bit (ML) Power Management Capabilities*/
-#define PCI_PME_SUP (0x1f<<11) /* Bit 11..15 PM Manag. Event Support*/
-#define PCI_PM_D2_SUB (1<<10) /* Bit 10 D2 Support Bit */
-#define PCI_PM_D1_SUB (1<<9) /* Bit 9 D1 Support Bit */
- /* Bit 6..8 reserved */
-#define PCI_PM_DSI (1<<5) /* Bit 5 Device Specific Init.*/
-#define PCI_PM_APS (1<<4) /* Bit 4 Auxialiary Power Src */
-#define PCI_PME_CLOCK (1<<3) /* Bit 3 PM Event Clock */
-#define PCI_PM_VER (7<<0) /* Bit 0..2 PM PCI Spec. version */
-
-/* PCI_PM_CTL_STS 16 bit (ML) Power Manag. Control/Status */
-#define PCI_PME_STATUS (1<<15) /* Bit 15 PFA doesn't sup. PME#*/
-#define PCI_PM_DAT_SCL (3<<13) /* Bit 13..14 dat reg Scaling factor */
-#define PCI_PM_DAT_SEL (0xf<<9) /* Bit 9..12 PM data selector field */
- /* Bit 7.. 2 reserved */
-#define PCI_PM_STATE (3<<0) /* Bit 0.. 1 Power Management State */
-#define PCI_PM_STATE_D0 (0<<0) /* D0: Operational (default) */
-#define PCI_PM_STATE_D1 (1<<0) /* D1: not supported */
-#define PCI_PM_STATE_D2 (2<<0) /* D2: not supported */
-#define PCI_PM_STATE_D3 (3<<0) /* D3: HOT, Power Down and Reset */
-
-/* PCI_PM_DAT_REG 8 bit (ML) Power Manag. Data Register */
-/* VPD Region */
-/* PCI_VPD_CAP_ID 8 bit (ML) VPD Cap. ID */
-/* PCI_VPD_NITEM 8 bit (ML) Next Item Ptr */
-/* PCI_VPD_ADR_REG 16 bit (ML) VPD Address Register */
-#define PCI_VPD_FLAG (1<<15) /* Bit 15 starts VPD rd/wd cycle*/
-
-/* PCI_VPD_DAT_REG 32 bit (ML) VPD Data Register */
-
/*
* Control Register File:
* Bank 0
--
2.21.0
^ permalink raw reply related
* [PATCH v2 2/3] net: fddi: skfp: Include generic PCI definitions
From: Puranjay Mohan @ 2019-06-20 18:07 UTC (permalink / raw)
To: Shuah Khan
Cc: Puranjay Mohan, Bjorn Helgaas, netdev, Linux Kernel Mailing List,
linux-kernel-mentees, linux-pci
In-Reply-To: <20190620180754.15413-1-puranjay12@gmail.com>
Include the uapi/linux/pci_regs.h header file which contains the generic
PCI defines.
Signed-off-by: Puranjay Mohan <puranjay12@gmail.com>
---
drivers/net/fddi/skfp/drvfbi.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/fddi/skfp/drvfbi.c b/drivers/net/fddi/skfp/drvfbi.c
index b324c1acf195..e8245cb281f8 100644
--- a/drivers/net/fddi/skfp/drvfbi.c
+++ b/drivers/net/fddi/skfp/drvfbi.c
@@ -20,7 +20,7 @@
#include "h/supern_2.h"
#include "h/skfbiinc.h"
#include <linux/bitrev.h>
-
+#include <linux/pci_regs.h>
#ifndef lint
static const char ID_sccs[] = "@(#)drvfbi.c 1.63 99/02/11 (C) SK " ;
#endif
--
2.21.0
^ permalink raw reply related
* [PATCH v2 1/3] net: fddi: skfp: Rename PCI_REV_ID to PCI_REVISION_ID
From: Puranjay Mohan @ 2019-06-20 18:07 UTC (permalink / raw)
To: Shuah Khan
Cc: Puranjay Mohan, Bjorn Helgaas, netdev, Linux Kernel Mailing List,
linux-kernel-mentees, linux-pci
In-Reply-To: <20190620180754.15413-1-puranjay12@gmail.com>
Rename the PCI_REV_ID define to PCI_REVISION_ID in skfbi.h
and drvfbi.c to make it compatible with the pci_regs.h
which defines it as PCI_REVISION_ID.
Signed-off-by: Puranjay Mohan <puranjay12@gmail.com>
---
drivers/net/fddi/skfp/drvfbi.c | 2 +-
drivers/net/fddi/skfp/h/skfbi.h | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/fddi/skfp/drvfbi.c b/drivers/net/fddi/skfp/drvfbi.c
index bdd5700e71fa..b324c1acf195 100644
--- a/drivers/net/fddi/skfp/drvfbi.c
+++ b/drivers/net/fddi/skfp/drvfbi.c
@@ -127,7 +127,7 @@ static void card_start(struct s_smc *smc)
* at very first before any other initialization functions is
* executed.
*/
- rev_id = inp(PCI_C(PCI_REV_ID)) ;
+ rev_id = inp(PCI_C(PCI_REVISION_ID)) ;
if ((rev_id & 0xf0) == SK_ML_ID_1 || (rev_id & 0xf0) == SK_ML_ID_2) {
smc->hw.hw_is_64bit = TRUE ;
} else {
diff --git a/drivers/net/fddi/skfp/h/skfbi.h b/drivers/net/fddi/skfp/h/skfbi.h
index 89557457b352..a05ce16171be 100644
--- a/drivers/net/fddi/skfp/h/skfbi.h
+++ b/drivers/net/fddi/skfp/h/skfbi.h
@@ -31,7 +31,7 @@
#define PCI_DEVICE_ID 0x02 /* 16 bit Device ID */
#define PCI_COMMAND 0x04 /* 16 bit Command */
#define PCI_STATUS 0x06 /* 16 bit Status */
-#define PCI_REV_ID 0x08 /* 8 bit Revision ID */
+#define PCI_REVISION_ID 0x08 /* 8 bit Revision ID */
#define PCI_CLASS_CODE 0x09 /* 24 bit Class Code */
#define PCI_CACHE_LSZ 0x0c /* 8 bit Cache Line Size */
#define PCI_LAT_TIM 0x0d /* 8 bit Latency Timer */
--
2.21.0
^ permalink raw reply related
* [PATCH v2 0/3] net: fddi: skfp: Use PCI generic definitions instead of private duplicates
From: Puranjay Mohan @ 2019-06-20 18:07 UTC (permalink / raw)
To: Shuah Khan
Cc: Puranjay Mohan, Bjorn Helgaas, netdev, Linux Kernel Mailing List,
linux-kernel-mentees, linux-pci
This patch series removes the private duplicates of PCI definitions in
favour of generic definitions defined in pci_regs.h.
This driver only uses one of the generic PCI definitons, i.e.
PCI_REVISION_ID, which is included from pci_regs.h and its private
version is removed from skfbi.h with all other private defines.
The skfbi.h defines PCI_REV_ID which is renamed to PCI_REVISION_ID in
drvfbi.c to make it compatible with the generic define in pci_regs.h.
Puranjay Mohan (3):
net: fddi: skfp: Rename PCI_REV_ID to PCI_REVISION_ID
net: fddi: skfp: Include generic PCI definitions
net: fddi: skfp: Remove unused private PCI definitions
drivers/net/fddi/skfp/drvfbi.c | 4 +-
drivers/net/fddi/skfp/h/skfbi.h | 207 +-------------------------------
2 files changed, 3 insertions(+), 208 deletions(-)
--
2.21.0
^ permalink raw reply
* Re: [PATCH v2 0/3] net: fddi: skfp: Use PCI generic definitions instead of private duplicates
From: Stephen Hemminger @ 2019-06-20 18:37 UTC (permalink / raw)
To: Puranjay Mohan
Cc: Shuah Khan, Bjorn Helgaas, netdev, Linux Kernel Mailing List,
linux-kernel-mentees, linux-pci
In-Reply-To: <20190620180754.15413-1-puranjay12@gmail.com>
On Thu, 20 Jun 2019 23:37:51 +0530
Puranjay Mohan <puranjay12@gmail.com> wrote:
> This patch series removes the private duplicates of PCI definitions in
> favour of generic definitions defined in pci_regs.h.
>
> This driver only uses one of the generic PCI definitons, i.e.
> PCI_REVISION_ID, which is included from pci_regs.h and its private
> version is removed from skfbi.h with all other private defines.
>
> The skfbi.h defines PCI_REV_ID which is renamed to PCI_REVISION_ID in
> drvfbi.c to make it compatible with the generic define in pci_regs.h.
>
> Puranjay Mohan (3):
> net: fddi: skfp: Rename PCI_REV_ID to PCI_REVISION_ID
> net: fddi: skfp: Include generic PCI definitions
> net: fddi: skfp: Remove unused private PCI definitions
>
> drivers/net/fddi/skfp/drvfbi.c | 4 +-
> drivers/net/fddi/skfp/h/skfbi.h | 207 +-------------------------------
> 2 files changed, 3 insertions(+), 208 deletions(-)
>
Does anyone still have the hardware to test this?
Maybe FDDI should be put out to pasture.
^ permalink raw reply
* Re: [PATCH net-next v6 03/11] ipv4/route: Allow NULL flowinfo in rt_fill_info()
From: Stefano Brivio @ 2019-06-20 19:00 UTC (permalink / raw)
To: David Ahern
Cc: David Miller, Jianlin Shi, Wei Wang, Martin KaFai Lau,
Eric Dumazet, Matti Vaittinen, netdev
In-Reply-To: <9efa65d3-5797-fde0-d5c2-3c7747d591ad@gmail.com>
On Thu, 20 Jun 2019 07:15:55 -0600
David Ahern <dsahern@gmail.com> wrote:
> On 6/19/19 5:59 PM, Stefano Brivio wrote:
> > In the next patch, we're going to use rt_fill_info() to dump exception
> > routes upon RTM_GETROUTE with NLM_F_ROOT, meaning userspace is requesting
> > a dump and not a specific route selection, which in turn implies the input
> > interface is not relevant. Update rt_fill_info() to handle a NULL
> > flowinfo.
> >
> > Suggested-by: David Ahern <dsahern@gmail.com>
> > Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
> > ---
> > v6: New patch
> >
> > net/ipv4/route.c | 57 ++++++++++++++++++++++++++----------------------
> > 1 file changed, 31 insertions(+), 26 deletions(-)
> >
> > diff --git a/net/ipv4/route.c b/net/ipv4/route.c
> > index 66cbe8a7a168..052a80373b1d 100644
> > --- a/net/ipv4/route.c
> > +++ b/net/ipv4/route.c
> > @@ -2699,7 +2699,8 @@ static int rt_fill_info(struct net *net, __be32 dst, __be32 src,
> > r->rtm_family = AF_INET;
> > r->rtm_dst_len = 32;
> > r->rtm_src_len = 0;
> > - r->rtm_tos = fl4->flowi4_tos;
> > + if (fl4)
> > + r->rtm_tos = fl4->flowi4_tos;
>
> tracing back to the alloc_skb it does not appear to be initialized to 0,
> so this should be:
> r->rtm_tos = fl4 ? fl4->flowi4_tos : 0;
I guess you're right, but I'm still wondering why I'm not seeing it
with KMSAN. Thanks for catching this, I'll fix it.
--
Stefano
^ permalink raw reply
* Re: [PATCH net-next v6 04/11] ipv4: Dump route exceptions if requested
From: Stefano Brivio @ 2019-06-20 19:01 UTC (permalink / raw)
To: David Ahern
Cc: David Miller, Jianlin Shi, Wei Wang, Martin KaFai Lau,
Eric Dumazet, Matti Vaittinen, netdev
In-Reply-To: <777387d8-fa15-388e-875a-02aa5df977dd@gmail.com>
On Thu, 20 Jun 2019 07:31:32 -0600
David Ahern <dsahern@gmail.com> wrote:
> On 6/19/19 5:59 PM, Stefano Brivio wrote:
> > diff --git a/include/net/route.h b/include/net/route.h
> > index 065b47754f05..e7f65388a6d4 100644
> > --- a/include/net/route.h
> > +++ b/include/net/route.h
> > @@ -44,6 +44,7 @@
> > #define RT_CONN_FLAGS_TOS(sk,tos) (RT_TOS(tos) | sock_flag(sk, SOCK_LOCALROUTE))
> >
> > struct fib_nh;
> > +struct fib_alias;
> > struct fib_info;
> > struct uncached_list;
> > struct rtable {
>
> we should not expose fib_alias to route.c.
I was also not enthusiastic about that, but...:
> > @@ -230,6 +231,9 @@ void fib_modify_prefix_metric(struct in_ifaddr *ifa, u32 new_metric);
> > void rt_add_uncached_list(struct rtable *rt);
> > void rt_del_uncached_list(struct rtable *rt);
> >
> > +int fnhe_dump_buckets(struct fib_alias *fa, int nhsel, struct sk_buff *skb,
> > + struct netlink_callback *cb, int *fa_index, int fa_start);
> > +
> > static inline void ip_rt_put(struct rtable *rt)
> > {
> > /* dst_release() accepts a NULL parameter.
> > diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
> > index 94e5d83db4db..03f51e5192e5 100644
> > --- a/net/ipv4/fib_trie.c
> > +++ b/net/ipv4/fib_trie.c
> > @@ -2078,28 +2078,51 @@ void fib_free_table(struct fib_table *tb)
> > call_rcu(&tb->rcu, __trie_free_rcu);
> > }
> >
> > +static int fib_dump_fnhe_from_leaf(struct fib_alias *fa, struct sk_buff *skb,
> > + struct netlink_callback *cb,
> > + int *fa_index, int fa_start)
> > +{
> > + struct fib_info *fi = fa->fa_info;
> > + int nhsel;
> > +
> > + if (!fi || fi->fib_flags & RTNH_F_DEAD)
> > + return 0;
> > +
> > + for (nhsel = 0; nhsel < fib_info_num_path(fi); nhsel++) {
> > + int err;
> > +
> > + err = fnhe_dump_buckets(fa, nhsel, skb, cb, fa_index, fa_start);
> > + if (err)
> > + return err;
> > + }
> > +
> > + return 0;
> > +}
>
> fib_info would be the better argument to pass in to the fnhe dump, and
...we need to pass the table ID to rt_fill_info(). Sure, I can pass
that explicitly, but doing so kind of tells me I'm not passing the
right argument, with sufficient information. What do you think?
> I think the loop over where the bucket is should be in route.c as well.
> So how about fib_info_dump_fnhe() as the helper exposed from route.c,
> and it does the loop over nexthops and calls fnhe_dump_buckets.
Yes, I could do that conveniently if I'm passing a fib_info there. I'm
stlll undecided if it's worth it, I guess I don't really have a
preference.
> As for the loop, you could fill an skb without finishing a bucket inside
> of a nexthop so you need top track which nexthop is current as well.
I think this is not a problem, and also checked that selftests trigger
this. Buckets are transparent to the counter for partial dumps (s_fa),
they are just an arbitrary grouping from that perspective, just like
items on the chain for the same bucket.
Take this example, s_i values in [], s_fa values in ():
node (fa) #1 [1]
nexthop #1
bucket #1 -> #0 in chain (1)
bucket #2 -> #0 in chain (2) -> #1 in chain (3) -> #2 in chain (4)
bucket #3 -> #0 in chain (5) -> #1 in chain (6)
nexthop #2
bucket #1 -> #0 in chain (7) -> #1 in chain (8)
bucket #2 -> #0 in chain (9)
--
node (fa) #2 [2]
nexthop #1
bucket #1 -> #0 in chain (1) -> #1 in chain (2)
bucket #2 -> #0 in chain (3)
If I stop at (3), (4), (7) for "node #1", or at (2) for "node #2", it
doesn't really matter, because nexthops and buckets are always
traversed in the same way (walking flattens all that).
For IPv4, I could even drop the in-tree/in-node distinction (s_i/s_fa).
But accounting becomes terribly inconvenient though, and it would be
inconsistent with what I needed to do for IPv6 (skip/skip_in_node): we
have 'sernum' there, which is used to mark what node we need to restart
from in case of changes. Within a node, however, I can't make any
assumptions like that, so if the fib6 tree changes, I'll restart from
the beginning of the node (see discussion with Martin on v1).
My idea would be to keep it like it is at the moment, and later make it
as "accurate" as it is on IPv6, introducing something like 'sernum'. If
we start with this, it will be more convenient to do that later.
--
Stefano
^ permalink raw reply
* Re: [PATCH net-next v6 06/11] ipv6/route: Don't match on fc_nh_id if not set in ip6_route_del()
From: Stefano Brivio @ 2019-06-20 19:01 UTC (permalink / raw)
To: David Ahern
Cc: David Miller, Jianlin Shi, Wei Wang, Martin KaFai Lau,
Eric Dumazet, Matti Vaittinen, netdev
In-Reply-To: <402be9f4-262c-b185-46a9-d5d4bb531cf1@gmail.com>
On Thu, 20 Jun 2019 08:16:28 -0600
David Ahern <dsahern@gmail.com> wrote:
> On 6/19/19 5:59 PM, Stefano Brivio wrote:
> > If fc_nh_id isn't set, we shouldn't try to match against it. This
> > actually matters just for the RTF_CACHE case below (where this is
> > already handled): if iproute2 gets a route exception and tries to
> > delete it, it won't reference its fc_nh_id, even if a nexthop
> > object might be associated to the originating route.
> >
> > Fixes: 5b98324ebe29 ("ipv6: Allow routes to use nexthop objects")
> > Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
> > ---
> > v6: New patch
> >
> > net/ipv6/route.c | 3 ++-
> > 1 file changed, 2 insertions(+), 1 deletion(-)
> >
>
> Thanks for catching that.
Your recent addition to pmtu.sh did it :)
--
Stefano
^ permalink raw reply
* Re: [PATCH net-next v6 08/11] ipv6: Dump route exceptions if requested
From: Stefano Brivio @ 2019-06-20 19:02 UTC (permalink / raw)
To: David Ahern
Cc: David Miller, Jianlin Shi, Wei Wang, Martin KaFai Lau,
Eric Dumazet, Matti Vaittinen, netdev
In-Reply-To: <26efcecf-5a96-330b-c315-5d9750c99766@gmail.com>
On Thu, 20 Jun 2019 08:24:22 -0600
David Ahern <dsahern@gmail.com> wrote:
> On 6/19/19 5:59 PM, Stefano Brivio wrote:
> > + if (filter->dump_exceptions) {
> > + struct fib6_nh_exception_dump_walker w = { .dump = arg,
> > + .rt = rt,
> > + .flags = flags,
> > + .skip = skip,
> > + .count = 0 };
> > + int err;
> > +
> > + if (rt->nh) {
> > + err = nexthop_for_each_fib6_nh(rt->nh,
> > + rt6_nh_dump_exceptions,
> > + &w);
>
> much like ipv4, the skb can fill in the middle of a fib6_nh bucket, so
> you need to track which nexthop is in progress.
Same as my comment about IPv4, except that, for IPv6, distinction
between skip and skip_in_node is strictly needed, but buckets and
nexthops are traversed in the same order and 'sernum' changes don't
affect that.
--
Stefano
^ permalink raw reply
* [PATCH net-next] ipv6: Convert gateway validation to use fib6_info
From: David Ahern @ 2019-06-20 19:05 UTC (permalink / raw)
To: davem; +Cc: netdev, kafai, weiwan, David Ahern
From: David Ahern <dsahern@gmail.com>
Gateway validation does not need a dst_entry, it only needs the fib
entry to validate the gateway resolution and egress device. So,
convert ip6_nh_lookup_table from ip6_pol_route to fib6_table_lookup
and ip6_route_check_nh to use fib6_lookup over rt6_lookup.
ip6_pol_route is a call to fib6_table_lookup and if successful a call
to fib6_select_path. From there the exception cache is searched for an
entry or a dst_entry is created to return to the caller. The exception
entry is not relevant for gateway validation, so what matters are the
calls to fib6_table_lookup and then fib6_select_path.
Similarly, rt6_lookup can be replaced with a call to fib6_lookup with
RT6_LOOKUP_F_IFACE set in flags (saddr is not set for gateway validation,
so RT6_LOOKUP_F_HAS_SADDR is not relevant). From there ip6_pol_route_lookup
lookup function is flipped to fib6_table_lookup for the per-table search.
Again, the exception cache search is not relevant, only the lookup with
path selection.
Adjust the users, ip6_route_check_nh_onlink and ip6_route_check_nh to
handle a fib6_info vs a rt6_info when performing validation checks.
Existing selftests fib-onlink-tests.sh and fib_tests.sh used to verify
the changes.
Signed-off-by: David Ahern <dsahern@gmail.com>
---
net/ipv6/route.c | 119 ++++++++++++++++++++++++++-----------------------------
1 file changed, 57 insertions(+), 62 deletions(-)
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index c4d285fe0adc..4937084610b5 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -3131,10 +3131,9 @@ static int ip6_dst_gc(struct dst_ops *ops)
return entries > rt_max_size;
}
-static struct rt6_info *ip6_nh_lookup_table(struct net *net,
- struct fib6_config *cfg,
- const struct in6_addr *gw_addr,
- u32 tbid, int flags)
+static int ip6_nh_lookup_table(struct net *net, struct fib6_config *cfg,
+ const struct in6_addr *gw_addr, u32 tbid,
+ int flags, struct fib6_result *res)
{
struct flowi6 fl6 = {
.flowi6_oif = cfg->fc_ifindex,
@@ -3142,25 +3141,23 @@ static struct rt6_info *ip6_nh_lookup_table(struct net *net,
.saddr = cfg->fc_prefsrc,
};
struct fib6_table *table;
- struct rt6_info *rt;
+ int err;
table = fib6_get_table(net, tbid);
if (!table)
- return NULL;
+ return -EINVAL;
if (!ipv6_addr_any(&cfg->fc_prefsrc))
flags |= RT6_LOOKUP_F_HAS_SADDR;
flags |= RT6_LOOKUP_F_IGNORE_LINKSTATE;
- rt = ip6_pol_route(net, table, cfg->fc_ifindex, &fl6, NULL, flags);
- /* if table lookup failed, fall back to full lookup */
- if (rt == net->ipv6.ip6_null_entry) {
- ip6_rt_put(rt);
- rt = NULL;
- }
+ err = fib6_table_lookup(net, table, cfg->fc_ifindex, &fl6, res, flags);
+ if (!err && res->f6i != net->ipv6.fib6_null_entry)
+ fib6_select_path(net, res, &fl6, cfg->fc_ifindex,
+ cfg->fc_ifindex != 0, NULL, flags);
- return rt;
+ return err;
}
static int ip6_route_check_nh_onlink(struct net *net,
@@ -3168,29 +3165,19 @@ static int ip6_route_check_nh_onlink(struct net *net,
const struct net_device *dev,
struct netlink_ext_ack *extack)
{
- u32 tbid = l3mdev_fib_table(dev) ? : RT_TABLE_MAIN;
+ u32 tbid = l3mdev_fib_table_rcu(dev) ? : RT_TABLE_MAIN;
const struct in6_addr *gw_addr = &cfg->fc_gateway;
- u32 flags = RTF_LOCAL | RTF_ANYCAST | RTF_REJECT;
- struct fib6_info *from;
- struct rt6_info *grt;
+ struct fib6_result res = {};
int err;
- err = 0;
- grt = ip6_nh_lookup_table(net, cfg, gw_addr, tbid, 0);
- if (grt) {
- rcu_read_lock();
- from = rcu_dereference(grt->from);
- if (!grt->dst.error &&
- /* ignore match if it is the default route */
- from && !ipv6_addr_any(&from->fib6_dst.addr) &&
- (grt->rt6i_flags & flags || dev != grt->dst.dev)) {
- NL_SET_ERR_MSG(extack,
- "Nexthop has invalid gateway or device mismatch");
- err = -EINVAL;
- }
- rcu_read_unlock();
-
- ip6_rt_put(grt);
+ err = ip6_nh_lookup_table(net, cfg, gw_addr, tbid, 0, &res);
+ if (!err && !(res.fib6_flags & RTF_REJECT) &&
+ /* ignore match if it is the default route */
+ !ipv6_addr_any(&res.f6i->fib6_dst.addr) &&
+ (res.fib6_type != RTN_UNICAST || dev != res.nh->fib_nh_dev)) {
+ NL_SET_ERR_MSG(extack,
+ "Nexthop has invalid gateway or device mismatch");
+ err = -EINVAL;
}
return err;
@@ -3203,47 +3190,51 @@ static int ip6_route_check_nh(struct net *net,
{
const struct in6_addr *gw_addr = &cfg->fc_gateway;
struct net_device *dev = _dev ? *_dev : NULL;
- struct rt6_info *grt = NULL;
+ int flags = RT6_LOOKUP_F_IFACE;
+ struct fib6_result res = {};
int err = -EHOSTUNREACH;
if (cfg->fc_table) {
- int flags = RT6_LOOKUP_F_IFACE;
-
- grt = ip6_nh_lookup_table(net, cfg, gw_addr,
- cfg->fc_table, flags);
- if (grt) {
- if (grt->rt6i_flags & RTF_GATEWAY ||
- (dev && dev != grt->dst.dev)) {
- ip6_rt_put(grt);
- grt = NULL;
- }
- }
+ err = ip6_nh_lookup_table(net, cfg, gw_addr,
+ cfg->fc_table, flags, &res);
+ /* gw_addr can not require a gateway or resolve to a reject
+ * route. If a device is given, it must match the result.
+ */
+ if (err || res.fib6_flags & RTF_REJECT ||
+ res.nh->fib_nh_gw_family ||
+ (dev && dev != res.nh->fib_nh_dev))
+ err = -EHOSTUNREACH;
}
- if (!grt)
- grt = rt6_lookup(net, gw_addr, NULL, cfg->fc_ifindex, NULL, 1);
+ if (err < 0) {
+ struct flowi6 fl6 = {
+ .flowi6_oif = cfg->fc_ifindex,
+ .daddr = *gw_addr,
+ };
- if (!grt)
- goto out;
+ err = fib6_lookup(net, cfg->fc_ifindex, &fl6, &res, flags);
+ if (err || res.fib6_flags & RTF_REJECT ||
+ res.nh->fib_nh_gw_family)
+ err = -EHOSTUNREACH;
+
+ if (err)
+ return err;
+
+ fib6_select_path(net, &res, &fl6, cfg->fc_ifindex,
+ cfg->fc_ifindex != 0, NULL, flags);
+ }
+ err = 0;
if (dev) {
- if (dev != grt->dst.dev) {
- ip6_rt_put(grt);
- goto out;
- }
+ if (dev != res.nh->fib_nh_dev)
+ err = -EHOSTUNREACH;
} else {
- *_dev = dev = grt->dst.dev;
- *idev = grt->rt6i_idev;
+ *_dev = dev = res.nh->fib_nh_dev;
+ *idev = __in6_dev_get(dev);
dev_hold(dev);
- in6_dev_hold(grt->rt6i_idev);
+ in6_dev_hold(*idev);
}
- if (!(grt->rt6i_flags & RTF_GATEWAY))
- err = 0;
-
- ip6_rt_put(grt);
-
-out:
return err;
}
@@ -3284,11 +3275,15 @@ static int ip6_validate_gw(struct net *net, struct fib6_config *cfg,
goto out;
}
+ rcu_read_lock();
+
if (cfg->fc_flags & RTNH_F_ONLINK)
err = ip6_route_check_nh_onlink(net, cfg, dev, extack);
else
err = ip6_route_check_nh(net, cfg, _dev, idev);
+ rcu_read_unlock();
+
if (err)
goto out;
}
--
2.11.0
^ permalink raw reply related
* Re: [PATCH net-next v6 04/11] ipv4: Dump route exceptions if requested
From: David Ahern @ 2019-06-20 19:21 UTC (permalink / raw)
To: Stefano Brivio
Cc: David Miller, Jianlin Shi, Wei Wang, Martin KaFai Lau,
Eric Dumazet, Matti Vaittinen, netdev
In-Reply-To: <20190620210113.6aa2c022@redhat.com>
On 6/20/19 1:01 PM, Stefano Brivio wrote:
>>> diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
>>> index 94e5d83db4db..03f51e5192e5 100644
>>> --- a/net/ipv4/fib_trie.c
>>> +++ b/net/ipv4/fib_trie.c
>>> @@ -2078,28 +2078,51 @@ void fib_free_table(struct fib_table *tb)
>>> call_rcu(&tb->rcu, __trie_free_rcu);
>>> }
>>>
>>> +static int fib_dump_fnhe_from_leaf(struct fib_alias *fa, struct sk_buff *skb,
>>> + struct netlink_callback *cb,
>>> + int *fa_index, int fa_start)
>>> +{
>>> + struct fib_info *fi = fa->fa_info;
>>> + int nhsel;
>>> +
>>> + if (!fi || fi->fib_flags & RTNH_F_DEAD)
>>> + return 0;
>>> +
>>> + for (nhsel = 0; nhsel < fib_info_num_path(fi); nhsel++) {
>>> + int err;
>>> +
>>> + err = fnhe_dump_buckets(fa, nhsel, skb, cb, fa_index, fa_start);
>>> + if (err)
>>> + return err;
>>> + }
>>> +
>>> + return 0;
>>> +}
>>
>> fib_info would be the better argument to pass in to the fnhe dump, and
>
> ...we need to pass the table ID to rt_fill_info(). Sure, I can pass
> that explicitly, but doing so kind of tells me I'm not passing the
> right argument, with sufficient information. What do you think?
I think that is preferable to passing fib_alias.
>
>> I think the loop over where the bucket is should be in route.c as well.
>> So how about fib_info_dump_fnhe() as the helper exposed from route.c,
>> and it does the loop over nexthops and calls fnhe_dump_buckets.
>
> Yes, I could do that conveniently if I'm passing a fib_info there. I'm
> stlll undecided if it's worth it, I guess I don't really have a
> preference.
>
>> As for the loop, you could fill an skb without finishing a bucket inside
>> of a nexthop so you need top track which nexthop is current as well.
>
> I think this is not a problem, and also checked that selftests trigger
> this. Buckets are transparent to the counter for partial dumps (s_fa),
> they are just an arbitrary grouping from that perspective, just like
> items on the chain for the same bucket.
>
> Take this example, s_i values in [], s_fa values in ():
>
> node (fa) #1 [1]
> nexthop #1
> bucket #1 -> #0 in chain (1)
> bucket #2 -> #0 in chain (2) -> #1 in chain (3) -> #2 in chain (4)
> bucket #3 -> #0 in chain (5) -> #1 in chain (6)
>
> nexthop #2
> bucket #1 -> #0 in chain (7) -> #1 in chain (8)
> bucket #2 -> #0 in chain (9)
> --
> node (fa) #2 [2]
> nexthop #1
> bucket #1 -> #0 in chain (1) -> #1 in chain (2)
> bucket #2 -> #0 in chain (3)
>
>
> If I stop at (3), (4), (7) for "node #1", or at (2) for "node #2", it
> doesn't really matter, because nexthops and buckets are always
> traversed in the same way (walking flattens all that).
>
> For IPv4, I could even drop the in-tree/in-node distinction (s_i/s_fa).
> But accounting becomes terribly inconvenient though, and it would be
> inconsistent with what I needed to do for IPv6 (skip/skip_in_node): we
> have 'sernum' there, which is used to mark what node we need to restart
> from in case of changes. Within a node, however, I can't make any
> assumptions like that, so if the fib6 tree changes, I'll restart from
> the beginning of the node (see discussion with Martin on v1).
>
> My idea would be to keep it like it is at the moment, and later make it
> as "accurate" as it is on IPv6, introducing something like 'sernum'. If
> we start with this, it will be more convenient to do that later.
>
ok, if you have it covered. can you add that description above to the
commit message. Be good to capture how it is covered.
^ permalink raw reply
* Re: [PATCH net-next v6 08/11] ipv6: Dump route exceptions if requested
From: David Ahern @ 2019-06-20 19:22 UTC (permalink / raw)
To: Stefano Brivio
Cc: David Miller, Jianlin Shi, Wei Wang, Martin KaFai Lau,
Eric Dumazet, Matti Vaittinen, netdev
In-Reply-To: <20190620210226.724c2893@redhat.com>
On 6/20/19 1:02 PM, Stefano Brivio wrote:
> Same as my comment about IPv4, except that, for IPv6, distinction
> between skip and skip_in_node is strictly needed, but buckets and
> nexthops are traversed in the same order and 'sernum' changes don't
> affect that.
ok
^ permalink raw reply
* Re: KASAN: slab-out-of-bounds Read in p54u_load_firmware_cb
From: Alan Stern @ 2019-06-20 19:46 UTC (permalink / raw)
To: syzbot
Cc: andreyknvl, chunkeey, davem, kvalo, Kernel development list,
USB list, linux-wireless, netdev, syzkaller-bugs
In-Reply-To: <000000000000f00cf1058bb7fb56@google.com>
On Wed, 19 Jun 2019, syzbot wrote:
> syzbot has found a reproducer for the following crash on:
>
> HEAD commit: 9939f56e usb-fuzzer: main usb gadget fuzzer driver
> git tree: https://github.com/google/kasan.git usb-fuzzer
> console output: https://syzkaller.appspot.com/x/log.txt?x=135e29faa00000
> kernel config: https://syzkaller.appspot.com/x/.config?x=df134eda130bb43a
> dashboard link: https://syzkaller.appspot.com/bug?extid=6d237e74cdc13f036473
> compiler: gcc (GCC) 9.0.0 20181231 (experimental)
> syz repro: https://syzkaller.appspot.com/x/repro.syz?x=175d946ea00000
>
> IMPORTANT: if you fix the bug, please add the following tag to the commit:
> Reported-by: syzbot+6d237e74cdc13f036473@syzkaller.appspotmail.com
>
> usb 3-1: Direct firmware load for isl3887usb failed with error -2
> usb 3-1: Firmware not found.
> ==================================================================
> BUG: KASAN: slab-out-of-bounds in p54u_load_firmware_cb.cold+0x97/0x13d
> drivers/net/wireless/intersil/p54/p54usb.c:936
> Read of size 8 at addr ffff8881c9cf7588 by task kworker/1:5/2759
>
> CPU: 1 PID: 2759 Comm: kworker/1:5 Not tainted 5.2.0-rc5+ #11
> Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
> Google 01/01/2011
> Workqueue: events request_firmware_work_func
> Call Trace:
> __dump_stack lib/dump_stack.c:77 [inline]
> dump_stack+0xca/0x13e lib/dump_stack.c:113
> print_address_description+0x67/0x231 mm/kasan/report.c:188
> __kasan_report.cold+0x1a/0x32 mm/kasan/report.c:317
> kasan_report+0xe/0x20 mm/kasan/common.c:614
> p54u_load_firmware_cb.cold+0x97/0x13d
> drivers/net/wireless/intersil/p54/p54usb.c:936
> request_firmware_work_func+0x126/0x242
> drivers/base/firmware_loader/main.c:785
> process_one_work+0x905/0x1570 kernel/workqueue.c:2269
> worker_thread+0x96/0xe20 kernel/workqueue.c:2415
> kthread+0x30b/0x410 kernel/kthread.c:255
> ret_from_fork+0x24/0x30 arch/x86/entry/entry_64.S:352
>
> Allocated by task 1612:
> save_stack+0x1b/0x80 mm/kasan/common.c:71
> set_track mm/kasan/common.c:79 [inline]
> __kasan_kmalloc mm/kasan/common.c:489 [inline]
> __kasan_kmalloc.constprop.0+0xbf/0xd0 mm/kasan/common.c:462
> kmalloc include/linux/slab.h:547 [inline]
> syslog_print kernel/printk/printk.c:1346 [inline]
> do_syslog kernel/printk/printk.c:1519 [inline]
> do_syslog+0x4f4/0x12e0 kernel/printk/printk.c:1493
> kmsg_read+0x8a/0xb0 fs/proc/kmsg.c:40
> proc_reg_read+0x1c1/0x280 fs/proc/inode.c:221
> __vfs_read+0x76/0x100 fs/read_write.c:425
> vfs_read+0x18e/0x3d0 fs/read_write.c:461
> ksys_read+0x127/0x250 fs/read_write.c:587
> do_syscall_64+0xb7/0x560 arch/x86/entry/common.c:301
> entry_SYSCALL_64_after_hwframe+0x49/0xbe
>
> Freed by task 1612:
> save_stack+0x1b/0x80 mm/kasan/common.c:71
> set_track mm/kasan/common.c:79 [inline]
> __kasan_slab_free+0x130/0x180 mm/kasan/common.c:451
> slab_free_hook mm/slub.c:1421 [inline]
> slab_free_freelist_hook mm/slub.c:1448 [inline]
> slab_free mm/slub.c:2994 [inline]
> kfree+0xd7/0x280 mm/slub.c:3949
> syslog_print kernel/printk/printk.c:1405 [inline]
> do_syslog kernel/printk/printk.c:1519 [inline]
> do_syslog+0xff3/0x12e0 kernel/printk/printk.c:1493
> kmsg_read+0x8a/0xb0 fs/proc/kmsg.c:40
> proc_reg_read+0x1c1/0x280 fs/proc/inode.c:221
> __vfs_read+0x76/0x100 fs/read_write.c:425
> vfs_read+0x18e/0x3d0 fs/read_write.c:461
> ksys_read+0x127/0x250 fs/read_write.c:587
> do_syscall_64+0xb7/0x560 arch/x86/entry/common.c:301
> entry_SYSCALL_64_after_hwframe+0x49/0xbe
>
> The buggy address belongs to the object at ffff8881c9cf7180
> which belongs to the cache kmalloc-1k of size 1024
> The buggy address is located 8 bytes to the right of
> 1024-byte region [ffff8881c9cf7180, ffff8881c9cf7580)
> The buggy address belongs to the page:
> page:ffffea0007273d00 refcount:1 mapcount:0 mapping:ffff8881dac02a00
> index:0x0 compound_mapcount: 0
> flags: 0x200000000010200(slab|head)
> raw: 0200000000010200 dead000000000100 dead000000000200 ffff8881dac02a00
> raw: 0000000000000000 00000000000e000e 00000001ffffffff 0000000000000000
> page dumped because: kasan: bad access detected
>
> Memory state around the buggy address:
> ffff8881c9cf7480: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
> ffff8881c9cf7500: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
> > ffff8881c9cf7580: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
> ^
> ffff8881c9cf7600: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
> ffff8881c9cf7680: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
> ==================================================================
Isn't this the same as syzkaller bug 200d4bb11b23d929335f ? Doesn't
the same patch fix it?
Alan Stern
^ permalink raw reply
* [PATCH net-next 00/12] netfilter: add hardware offload infrastructure
From: Pablo Neira Ayuso @ 2019-06-20 19:49 UTC (permalink / raw)
To: netdev
Cc: netfilter-devel, davem, thomas.lendacky, f.fainelli, ariel.elior,
michael.chan, santosh, madalin.bucur, yisen.zhuang, salil.mehta,
jeffrey.t.kirsher, tariqt, saeedm, jiri, idosch, jakub.kicinski,
peppe.cavallaro, grygorii.strashko, andrew, vivien.didelot,
alexandre.torgue, joabreu, linux-net-drivers, ganeshgr, ogerlitz,
Manish.Chopra, marcelo.leitner, mkubecek, venkatkumar.duvvuru,
cphealy
Hi,
This patchset adds support for Netfilter hardware offloads.
This patchset reuses the existing block infrastructure, the
netdev_ops->ndo_setup_tc() interface, TC_SETUP_CLSFLOWER classifier and
the flow rule API.
Patch #1 moves tcf_block_cb code before the indirect block
infrastructure to avoid forward declarations in the next
patches. This is just a preparation patch.
Patch #2 adds tcf_block_cb_alloc() to allocate flow block callbacks.
Patch #3 adds tcf_block_cb_free() to release flow block callbacks.
Patch #4 adds the tcf_block_setup() infrastructure, which allows drivers
to set up flow block callbacks. This infrastructure transports
these objects via list (through the tc_block_offload object)
back to the core for registration.
CLS_API DRIVER
TC_SETUP_BLOCK ----------> setup flow_block_cb object &
it adds object to flow_block_offload->cb_list
|
CLS_API <-----------------------'
registers list if flow block
flow_block_cb & travels back to
calls ->reoffload the core for registration
Patch #5 extends tcf_block_cb_alloc() to allow drivers to set a release
callback that is invoked from tcf_block_cb_free() to release
private driver block information.
Patch #6 adds tcf_setup_block_offload(), this helper function is used by
most drivers to setup the block, including common bind and
unbind operations.
Patch #7 adapts drivers to use the infrastructure introduced in Patch #4.
Patch #8 stops exposing the tc block structure to drivers, by caching
the only information that drivers need, ie. block is shared
flag.
Patch #9 removes the tcf_block_cb_register() / _unregister()
infrastructure, since it is now unused after Patch #7.
Patch #10 moves the flow_block API to the net/core/flow_offload.c core.
This renames tcf_block_cb to flow_block_cb as well as the
functions to allocate, release, lookup and setup flow block
callbacks.
Patch #11 makes sure that only one flow block callback per device is
possible by now. This means only one of the ethtool / tc /
netfilter subsystems can use hardware offloads, until drivers
are updated to remove this limitation.
Patch #12 introduces basic netfilter hardware offload infrastructure
for the ingress chain. This includes 5-tuple matching and
accept / drop actions. Only basechains are supported at this
stage, no .reoffload callback is implemented either.
Please, apply, thanks.
Pablo Neira Ayuso (12):
net: sched: move tcf_block_cb before indr_block
net: sched: add tcf_block_cb_alloc()
net: sched: add tcf_block_cb_free()
net: sched: add tcf_block_setup()
net: sched: add release callback to struct tcf_block_cb
net: sched: add tcf_setup_block_offload()
net: use tcf_block_setup() infrastructure
net: cls_api: do not expose tcf_block to drivers
net: sched: remove tcf_block_cb_{register,unregister}()
net: flow_offload: add flow_block_cb API
net: flow_offload: don't allow block sharing until drivers support this
netfilter: nf_tables: add hardware offload support
drivers/net/ethernet/broadcom/bnxt/bnxt.c | 26 +-
drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c | 28 +-
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 26 +-
drivers/net/ethernet/intel/i40e/i40e_main.c | 26 +-
drivers/net/ethernet/intel/iavf/iavf_main.c | 35 +-
drivers/net/ethernet/intel/igb/igb_main.c | 24 +-
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 27 +-
drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 27 +-
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 62 ++-
drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 87 ++--
drivers/net/ethernet/mscc/ocelot_ace.h | 4 +-
drivers/net/ethernet/mscc/ocelot_flower.c | 45 +-
drivers/net/ethernet/mscc/ocelot_tc.c | 28 +-
drivers/net/ethernet/netronome/nfp/abm/cls.c | 19 +-
drivers/net/ethernet/netronome/nfp/abm/main.h | 2 +-
drivers/net/ethernet/netronome/nfp/bpf/main.c | 29 +-
.../net/ethernet/netronome/nfp/flower/offload.c | 63 ++-
drivers/net/ethernet/qlogic/qede/qede_main.c | 23 +-
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 22 +-
drivers/net/netdevsim/netdev.c | 26 +-
include/net/flow_offload.h | 52 +++
include/net/netfilter/nf_tables.h | 13 +
include/net/netfilter/nf_tables_offload.h | 76 ++++
include/net/pkt_cls.h | 90 +---
include/uapi/linux/netfilter/nf_tables.h | 2 +
net/core/flow_offload.c | 121 +++++
net/dsa/slave.c | 16 +-
net/netfilter/Makefile | 2 +-
net/netfilter/nf_tables_api.c | 22 +-
net/netfilter/nf_tables_offload.c | 233 ++++++++++
net/netfilter/nft_cmp.c | 53 +++
net/netfilter/nft_immediate.c | 31 ++
net/netfilter/nft_meta.c | 27 ++
net/netfilter/nft_payload.c | 187 ++++++++
net/sched/cls_api.c | 502 ++++++++++-----------
35 files changed, 1305 insertions(+), 751 deletions(-)
create mode 100644 include/net/netfilter/nf_tables_offload.h
create mode 100644 net/netfilter/nf_tables_offload.c
--
2.11.0
^ permalink raw reply
* [PATCH net-next 02/12] net: sched: add tcf_block_cb_alloc()
From: Pablo Neira Ayuso @ 2019-06-20 19:49 UTC (permalink / raw)
To: netdev
Cc: netfilter-devel, davem, thomas.lendacky, f.fainelli, ariel.elior,
michael.chan, santosh, madalin.bucur, yisen.zhuang, salil.mehta,
jeffrey.t.kirsher, tariqt, saeedm, jiri, idosch, jakub.kicinski,
peppe.cavallaro, grygorii.strashko, andrew, vivien.didelot,
alexandre.torgue, joabreu, linux-net-drivers, ganeshgr, ogerlitz,
Manish.Chopra, marcelo.leitner, mkubecek, venkatkumar.duvvuru,
cphealy
In-Reply-To: <20190620194917.2298-1-pablo@netfilter.org>
Add a new helper function to allocate tcf_block_cb objects.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/net/pkt_cls.h | 8 ++++++++
net/sched/cls_api.c | 23 +++++++++++++++++++----
2 files changed, 27 insertions(+), 4 deletions(-)
diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index 720f2b32fc2f..276a17a3547b 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -72,6 +72,8 @@ static inline struct Qdisc *tcf_block_q(struct tcf_block *block)
return block->q;
}
+struct tcf_block_cb *tcf_block_cb_alloc(tc_setup_cb_t *cb,
+ void *cb_ident, void *cb_priv);
void *tcf_block_cb_priv(struct tcf_block_cb *block_cb);
struct tcf_block_cb *tcf_block_cb_lookup(struct tcf_block *block,
tc_setup_cb_t *cb, void *cb_ident);
@@ -150,6 +152,12 @@ void tc_setup_cb_block_unregister(struct tcf_block *block, tc_setup_cb_t *cb,
{
}
+static inline struct tcf_block_cb *
+tcf_block_cb_alloc(tc_setup_cb_t *cb, void *cb_ident, void *cb_priv)
+{
+ return NULL;
+}
+
static inline
void *tcf_block_cb_priv(struct tcf_block_cb *block_cb)
{
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index b2417fda26ec..c01d825edab5 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -746,6 +746,23 @@ unsigned int tcf_block_cb_decref(struct tcf_block_cb *block_cb)
}
EXPORT_SYMBOL(tcf_block_cb_decref);
+struct tcf_block_cb *tcf_block_cb_alloc(tc_setup_cb_t *cb,
+ void *cb_ident, void *cb_priv)
+{
+ struct tcf_block_cb *block_cb;
+
+ block_cb = kzalloc(sizeof(*block_cb), GFP_KERNEL);
+ if (!block_cb)
+ return NULL;
+
+ block_cb->cb = cb;
+ block_cb->cb_ident = cb_ident;
+ block_cb->cb_priv = cb_priv;
+
+ return block_cb;
+}
+EXPORT_SYMBOL(tcf_block_cb_alloc);
+
struct tcf_block_cb *__tcf_block_cb_register(struct tcf_block *block,
tc_setup_cb_t *cb, void *cb_ident,
void *cb_priv,
@@ -761,12 +778,10 @@ struct tcf_block_cb *__tcf_block_cb_register(struct tcf_block *block,
if (err)
return ERR_PTR(err);
- block_cb = kzalloc(sizeof(*block_cb), GFP_KERNEL);
+ block_cb = tcf_block_cb_alloc(cb, cb_ident, cb_priv);
if (!block_cb)
return ERR_PTR(-ENOMEM);
- block_cb->cb = cb;
- block_cb->cb_ident = cb_ident;
- block_cb->cb_priv = cb_priv;
+
list_add(&block_cb->list, &block->cb_list);
return block_cb;
}
--
2.11.0
^ permalink raw reply related
* [PATCH net-next 03/12] net: sched: add tcf_block_cb_free()
From: Pablo Neira Ayuso @ 2019-06-20 19:49 UTC (permalink / raw)
To: netdev
Cc: netfilter-devel, davem, thomas.lendacky, f.fainelli, ariel.elior,
michael.chan, santosh, madalin.bucur, yisen.zhuang, salil.mehta,
jeffrey.t.kirsher, tariqt, saeedm, jiri, idosch, jakub.kicinski,
peppe.cavallaro, grygorii.strashko, andrew, vivien.didelot,
alexandre.torgue, joabreu, linux-net-drivers, ganeshgr, ogerlitz,
Manish.Chopra, marcelo.leitner, mkubecek, venkatkumar.duvvuru,
cphealy
In-Reply-To: <20190620194917.2298-1-pablo@netfilter.org>
Just a stub to release tcf_block_cb objects, follow up patch extends it
to have a release callback in it for the private data.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/net/pkt_cls.h | 5 +++++
net/sched/cls_api.c | 6 ++++++
2 files changed, 11 insertions(+)
diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index 276a17a3547b..2816297449ee 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -74,6 +74,7 @@ static inline struct Qdisc *tcf_block_q(struct tcf_block *block)
struct tcf_block_cb *tcf_block_cb_alloc(tc_setup_cb_t *cb,
void *cb_ident, void *cb_priv);
+void tcf_block_cb_free(struct tcf_block_cb *block_cb);
void *tcf_block_cb_priv(struct tcf_block_cb *block_cb);
struct tcf_block_cb *tcf_block_cb_lookup(struct tcf_block *block,
tc_setup_cb_t *cb, void *cb_ident);
@@ -158,6 +159,10 @@ tcf_block_cb_alloc(tc_setup_cb_t *cb, void *cb_ident, void *cb_priv)
return NULL;
}
+static inline void tcf_block_cb_free(struct tcf_block_cb *block_cb)
+{
+}
+
static inline
void *tcf_block_cb_priv(struct tcf_block_cb *block_cb)
{
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index c01d825edab5..b86475ab8f63 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -763,6 +763,12 @@ struct tcf_block_cb *tcf_block_cb_alloc(tc_setup_cb_t *cb,
}
EXPORT_SYMBOL(tcf_block_cb_alloc);
+void tcf_block_cb_free(struct tcf_block_cb *block_cb)
+{
+ kfree(block_cb);
+}
+EXPORT_SYMBOL(tcf_block_cb_free);
+
struct tcf_block_cb *__tcf_block_cb_register(struct tcf_block *block,
tc_setup_cb_t *cb, void *cb_ident,
void *cb_priv,
--
2.11.0
^ permalink raw reply related
* [PATCH net-next 01/12] net: sched: move tcf_block_cb before indr_block
From: Pablo Neira Ayuso @ 2019-06-20 19:49 UTC (permalink / raw)
To: netdev
Cc: netfilter-devel, davem, thomas.lendacky, f.fainelli, ariel.elior,
michael.chan, santosh, madalin.bucur, yisen.zhuang, salil.mehta,
jeffrey.t.kirsher, tariqt, saeedm, jiri, idosch, jakub.kicinski,
peppe.cavallaro, grygorii.strashko, andrew, vivien.didelot,
alexandre.torgue, joabreu, linux-net-drivers, ganeshgr, ogerlitz,
Manish.Chopra, marcelo.leitner, mkubecek, venkatkumar.duvvuru,
cphealy
In-Reply-To: <20190620194917.2298-1-pablo@netfilter.org>
The indr_block infrastructure will depend on the tcf_block_cb object,
move this code on top to avoid forward declarations.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
net/sched/cls_api.c | 484 ++++++++++++++++++++++++++--------------------------
1 file changed, 242 insertions(+), 242 deletions(-)
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index ad36bbcc583e..b2417fda26ec 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -565,6 +565,248 @@ static struct tcf_block *tc_dev_ingress_block(struct net_device *dev)
return cops->tcf_block(qdisc, TC_H_MIN_INGRESS, NULL);
}
+static struct tcf_chain *
+__tcf_get_next_chain(struct tcf_block *block, struct tcf_chain *chain)
+{
+ mutex_lock(&block->lock);
+ if (chain)
+ chain = list_is_last(&chain->list, &block->chain_list) ?
+ NULL : list_next_entry(chain, list);
+ else
+ chain = list_first_entry_or_null(&block->chain_list,
+ struct tcf_chain, list);
+
+ /* skip all action-only chains */
+ while (chain && tcf_chain_held_by_acts_only(chain))
+ chain = list_is_last(&chain->list, &block->chain_list) ?
+ NULL : list_next_entry(chain, list);
+
+ if (chain)
+ tcf_chain_hold(chain);
+ mutex_unlock(&block->lock);
+
+ return chain;
+}
+
+/* Function to be used by all clients that want to iterate over all chains on
+ * block. It properly obtains block->lock and takes reference to chain before
+ * returning it. Users of this function must be tolerant to concurrent chain
+ * insertion/deletion or ensure that no concurrent chain modification is
+ * possible. Note that all netlink dump callbacks cannot guarantee to provide
+ * consistent dump because rtnl lock is released each time skb is filled with
+ * data and sent to user-space.
+ */
+
+struct tcf_chain *
+tcf_get_next_chain(struct tcf_block *block, struct tcf_chain *chain)
+{
+ struct tcf_chain *chain_next = __tcf_get_next_chain(block, chain);
+
+ if (chain)
+ tcf_chain_put(chain);
+
+ return chain_next;
+}
+EXPORT_SYMBOL(tcf_get_next_chain);
+
+static struct tcf_proto *
+__tcf_get_next_proto(struct tcf_chain *chain, struct tcf_proto *tp)
+{
+ u32 prio = 0;
+
+ ASSERT_RTNL();
+ mutex_lock(&chain->filter_chain_lock);
+
+ if (!tp) {
+ tp = tcf_chain_dereference(chain->filter_chain, chain);
+ } else if (tcf_proto_is_deleting(tp)) {
+ /* 'deleting' flag is set and chain->filter_chain_lock was
+ * unlocked, which means next pointer could be invalid. Restart
+ * search.
+ */
+ prio = tp->prio + 1;
+ tp = tcf_chain_dereference(chain->filter_chain, chain);
+
+ for (; tp; tp = tcf_chain_dereference(tp->next, chain))
+ if (!tp->deleting && tp->prio >= prio)
+ break;
+ } else {
+ tp = tcf_chain_dereference(tp->next, chain);
+ }
+
+ if (tp)
+ tcf_proto_get(tp);
+
+ mutex_unlock(&chain->filter_chain_lock);
+
+ return tp;
+}
+
+/* Function to be used by all clients that want to iterate over all tp's on
+ * chain. Users of this function must be tolerant to concurrent tp
+ * insertion/deletion or ensure that no concurrent chain modification is
+ * possible. Note that all netlink dump callbacks cannot guarantee to provide
+ * consistent dump because rtnl lock is released each time skb is filled with
+ * data and sent to user-space.
+ */
+
+struct tcf_proto *
+tcf_get_next_proto(struct tcf_chain *chain, struct tcf_proto *tp,
+ bool rtnl_held)
+{
+ struct tcf_proto *tp_next = __tcf_get_next_proto(chain, tp);
+
+ if (tp)
+ tcf_proto_put(tp, rtnl_held, NULL);
+
+ return tp_next;
+}
+EXPORT_SYMBOL(tcf_get_next_proto);
+
+static int
+tcf_block_playback_offloads(struct tcf_block *block, tc_setup_cb_t *cb,
+ void *cb_priv, bool add, bool offload_in_use,
+ struct netlink_ext_ack *extack)
+{
+ struct tcf_chain *chain, *chain_prev;
+ struct tcf_proto *tp, *tp_prev;
+ int err;
+
+ for (chain = __tcf_get_next_chain(block, NULL);
+ chain;
+ chain_prev = chain,
+ chain = __tcf_get_next_chain(block, chain),
+ tcf_chain_put(chain_prev)) {
+ for (tp = __tcf_get_next_proto(chain, NULL); tp;
+ tp_prev = tp,
+ tp = __tcf_get_next_proto(chain, tp),
+ tcf_proto_put(tp_prev, true, NULL)) {
+ if (tp->ops->reoffload) {
+ err = tp->ops->reoffload(tp, add, cb, cb_priv,
+ extack);
+ if (err && add)
+ goto err_playback_remove;
+ } else if (add && offload_in_use) {
+ err = -EOPNOTSUPP;
+ NL_SET_ERR_MSG(extack, "Filter HW offload failed - classifier without re-offloading support");
+ goto err_playback_remove;
+ }
+ }
+ }
+
+ return 0;
+
+err_playback_remove:
+ tcf_proto_put(tp, true, NULL);
+ tcf_chain_put(chain);
+ tcf_block_playback_offloads(block, cb, cb_priv, false, offload_in_use,
+ extack);
+ return err;
+}
+
+static bool tcf_block_offload_in_use(struct tcf_block *block)
+{
+ return block->offloadcnt;
+}
+
+struct tcf_block_cb {
+ struct list_head list;
+ tc_setup_cb_t *cb;
+ void *cb_ident;
+ void *cb_priv;
+ unsigned int refcnt;
+};
+
+void *tcf_block_cb_priv(struct tcf_block_cb *block_cb)
+{
+ return block_cb->cb_priv;
+}
+EXPORT_SYMBOL(tcf_block_cb_priv);
+
+struct tcf_block_cb *tcf_block_cb_lookup(struct tcf_block *block,
+ tc_setup_cb_t *cb, void *cb_ident)
+{ struct tcf_block_cb *block_cb;
+
+ list_for_each_entry(block_cb, &block->cb_list, list)
+ if (block_cb->cb == cb && block_cb->cb_ident == cb_ident)
+ return block_cb;
+ return NULL;
+}
+EXPORT_SYMBOL(tcf_block_cb_lookup);
+
+void tcf_block_cb_incref(struct tcf_block_cb *block_cb)
+{
+ block_cb->refcnt++;
+}
+EXPORT_SYMBOL(tcf_block_cb_incref);
+
+unsigned int tcf_block_cb_decref(struct tcf_block_cb *block_cb)
+{
+ return --block_cb->refcnt;
+}
+EXPORT_SYMBOL(tcf_block_cb_decref);
+
+struct tcf_block_cb *__tcf_block_cb_register(struct tcf_block *block,
+ tc_setup_cb_t *cb, void *cb_ident,
+ void *cb_priv,
+ struct netlink_ext_ack *extack)
+{
+ struct tcf_block_cb *block_cb;
+ int err;
+
+ /* Replay any already present rules */
+ err = tcf_block_playback_offloads(block, cb, cb_priv, true,
+ tcf_block_offload_in_use(block),
+ extack);
+ if (err)
+ return ERR_PTR(err);
+
+ block_cb = kzalloc(sizeof(*block_cb), GFP_KERNEL);
+ if (!block_cb)
+ return ERR_PTR(-ENOMEM);
+ block_cb->cb = cb;
+ block_cb->cb_ident = cb_ident;
+ block_cb->cb_priv = cb_priv;
+ list_add(&block_cb->list, &block->cb_list);
+ return block_cb;
+}
+EXPORT_SYMBOL(__tcf_block_cb_register);
+
+int tcf_block_cb_register(struct tcf_block *block,
+ tc_setup_cb_t *cb, void *cb_ident,
+ void *cb_priv, struct netlink_ext_ack *extack)
+{
+ struct tcf_block_cb *block_cb;
+
+ block_cb = __tcf_block_cb_register(block, cb, cb_ident, cb_priv,
+ extack);
+ return PTR_ERR_OR_ZERO(block_cb);
+}
+EXPORT_SYMBOL(tcf_block_cb_register);
+
+void __tcf_block_cb_unregister(struct tcf_block *block,
+ struct tcf_block_cb *block_cb)
+{
+ tcf_block_playback_offloads(block, block_cb->cb, block_cb->cb_priv,
+ false, tcf_block_offload_in_use(block),
+ NULL);
+ list_del(&block_cb->list);
+ kfree(block_cb);
+}
+EXPORT_SYMBOL(__tcf_block_cb_unregister);
+
+void tcf_block_cb_unregister(struct tcf_block *block,
+ tc_setup_cb_t *cb, void *cb_ident)
+{
+ struct tcf_block_cb *block_cb;
+
+ block_cb = tcf_block_cb_lookup(block, cb, cb_ident);
+ if (!block_cb)
+ return;
+ __tcf_block_cb_unregister(block, block_cb);
+}
+EXPORT_SYMBOL(tcf_block_cb_unregister);
+
static struct rhashtable indr_setup_block_ht;
struct tc_indr_block_dev {
@@ -782,11 +1024,6 @@ static void tc_indr_block_call(struct tcf_block *block, struct net_device *dev,
&bo);
}
-static bool tcf_block_offload_in_use(struct tcf_block *block)
-{
- return block->offloadcnt;
-}
-
static int tcf_block_offload_cmd(struct tcf_block *block,
struct net_device *dev,
struct tcf_block_ext_info *ei,
@@ -1003,104 +1240,6 @@ static struct tcf_block *tcf_block_refcnt_get(struct net *net, u32 block_index)
return block;
}
-static struct tcf_chain *
-__tcf_get_next_chain(struct tcf_block *block, struct tcf_chain *chain)
-{
- mutex_lock(&block->lock);
- if (chain)
- chain = list_is_last(&chain->list, &block->chain_list) ?
- NULL : list_next_entry(chain, list);
- else
- chain = list_first_entry_or_null(&block->chain_list,
- struct tcf_chain, list);
-
- /* skip all action-only chains */
- while (chain && tcf_chain_held_by_acts_only(chain))
- chain = list_is_last(&chain->list, &block->chain_list) ?
- NULL : list_next_entry(chain, list);
-
- if (chain)
- tcf_chain_hold(chain);
- mutex_unlock(&block->lock);
-
- return chain;
-}
-
-/* Function to be used by all clients that want to iterate over all chains on
- * block. It properly obtains block->lock and takes reference to chain before
- * returning it. Users of this function must be tolerant to concurrent chain
- * insertion/deletion or ensure that no concurrent chain modification is
- * possible. Note that all netlink dump callbacks cannot guarantee to provide
- * consistent dump because rtnl lock is released each time skb is filled with
- * data and sent to user-space.
- */
-
-struct tcf_chain *
-tcf_get_next_chain(struct tcf_block *block, struct tcf_chain *chain)
-{
- struct tcf_chain *chain_next = __tcf_get_next_chain(block, chain);
-
- if (chain)
- tcf_chain_put(chain);
-
- return chain_next;
-}
-EXPORT_SYMBOL(tcf_get_next_chain);
-
-static struct tcf_proto *
-__tcf_get_next_proto(struct tcf_chain *chain, struct tcf_proto *tp)
-{
- u32 prio = 0;
-
- ASSERT_RTNL();
- mutex_lock(&chain->filter_chain_lock);
-
- if (!tp) {
- tp = tcf_chain_dereference(chain->filter_chain, chain);
- } else if (tcf_proto_is_deleting(tp)) {
- /* 'deleting' flag is set and chain->filter_chain_lock was
- * unlocked, which means next pointer could be invalid. Restart
- * search.
- */
- prio = tp->prio + 1;
- tp = tcf_chain_dereference(chain->filter_chain, chain);
-
- for (; tp; tp = tcf_chain_dereference(tp->next, chain))
- if (!tp->deleting && tp->prio >= prio)
- break;
- } else {
- tp = tcf_chain_dereference(tp->next, chain);
- }
-
- if (tp)
- tcf_proto_get(tp);
-
- mutex_unlock(&chain->filter_chain_lock);
-
- return tp;
-}
-
-/* Function to be used by all clients that want to iterate over all tp's on
- * chain. Users of this function must be tolerant to concurrent tp
- * insertion/deletion or ensure that no concurrent chain modification is
- * possible. Note that all netlink dump callbacks cannot guarantee to provide
- * consistent dump because rtnl lock is released each time skb is filled with
- * data and sent to user-space.
- */
-
-struct tcf_proto *
-tcf_get_next_proto(struct tcf_chain *chain, struct tcf_proto *tp,
- bool rtnl_held)
-{
- struct tcf_proto *tp_next = __tcf_get_next_proto(chain, tp);
-
- if (tp)
- tcf_proto_put(tp, rtnl_held, NULL);
-
- return tp_next;
-}
-EXPORT_SYMBOL(tcf_get_next_proto);
-
static void tcf_block_flush_all_chains(struct tcf_block *block, bool rtnl_held)
{
struct tcf_chain *chain;
@@ -1494,145 +1633,6 @@ void tcf_block_put(struct tcf_block *block)
EXPORT_SYMBOL(tcf_block_put);
-struct tcf_block_cb {
- struct list_head list;
- tc_setup_cb_t *cb;
- void *cb_ident;
- void *cb_priv;
- unsigned int refcnt;
-};
-
-void *tcf_block_cb_priv(struct tcf_block_cb *block_cb)
-{
- return block_cb->cb_priv;
-}
-EXPORT_SYMBOL(tcf_block_cb_priv);
-
-struct tcf_block_cb *tcf_block_cb_lookup(struct tcf_block *block,
- tc_setup_cb_t *cb, void *cb_ident)
-{ struct tcf_block_cb *block_cb;
-
- list_for_each_entry(block_cb, &block->cb_list, list)
- if (block_cb->cb == cb && block_cb->cb_ident == cb_ident)
- return block_cb;
- return NULL;
-}
-EXPORT_SYMBOL(tcf_block_cb_lookup);
-
-void tcf_block_cb_incref(struct tcf_block_cb *block_cb)
-{
- block_cb->refcnt++;
-}
-EXPORT_SYMBOL(tcf_block_cb_incref);
-
-unsigned int tcf_block_cb_decref(struct tcf_block_cb *block_cb)
-{
- return --block_cb->refcnt;
-}
-EXPORT_SYMBOL(tcf_block_cb_decref);
-
-static int
-tcf_block_playback_offloads(struct tcf_block *block, tc_setup_cb_t *cb,
- void *cb_priv, bool add, bool offload_in_use,
- struct netlink_ext_ack *extack)
-{
- struct tcf_chain *chain, *chain_prev;
- struct tcf_proto *tp, *tp_prev;
- int err;
-
- for (chain = __tcf_get_next_chain(block, NULL);
- chain;
- chain_prev = chain,
- chain = __tcf_get_next_chain(block, chain),
- tcf_chain_put(chain_prev)) {
- for (tp = __tcf_get_next_proto(chain, NULL); tp;
- tp_prev = tp,
- tp = __tcf_get_next_proto(chain, tp),
- tcf_proto_put(tp_prev, true, NULL)) {
- if (tp->ops->reoffload) {
- err = tp->ops->reoffload(tp, add, cb, cb_priv,
- extack);
- if (err && add)
- goto err_playback_remove;
- } else if (add && offload_in_use) {
- err = -EOPNOTSUPP;
- NL_SET_ERR_MSG(extack, "Filter HW offload failed - classifier without re-offloading support");
- goto err_playback_remove;
- }
- }
- }
-
- return 0;
-
-err_playback_remove:
- tcf_proto_put(tp, true, NULL);
- tcf_chain_put(chain);
- tcf_block_playback_offloads(block, cb, cb_priv, false, offload_in_use,
- extack);
- return err;
-}
-
-struct tcf_block_cb *__tcf_block_cb_register(struct tcf_block *block,
- tc_setup_cb_t *cb, void *cb_ident,
- void *cb_priv,
- struct netlink_ext_ack *extack)
-{
- struct tcf_block_cb *block_cb;
- int err;
-
- /* Replay any already present rules */
- err = tcf_block_playback_offloads(block, cb, cb_priv, true,
- tcf_block_offload_in_use(block),
- extack);
- if (err)
- return ERR_PTR(err);
-
- block_cb = kzalloc(sizeof(*block_cb), GFP_KERNEL);
- if (!block_cb)
- return ERR_PTR(-ENOMEM);
- block_cb->cb = cb;
- block_cb->cb_ident = cb_ident;
- block_cb->cb_priv = cb_priv;
- list_add(&block_cb->list, &block->cb_list);
- return block_cb;
-}
-EXPORT_SYMBOL(__tcf_block_cb_register);
-
-int tcf_block_cb_register(struct tcf_block *block,
- tc_setup_cb_t *cb, void *cb_ident,
- void *cb_priv, struct netlink_ext_ack *extack)
-{
- struct tcf_block_cb *block_cb;
-
- block_cb = __tcf_block_cb_register(block, cb, cb_ident, cb_priv,
- extack);
- return PTR_ERR_OR_ZERO(block_cb);
-}
-EXPORT_SYMBOL(tcf_block_cb_register);
-
-void __tcf_block_cb_unregister(struct tcf_block *block,
- struct tcf_block_cb *block_cb)
-{
- tcf_block_playback_offloads(block, block_cb->cb, block_cb->cb_priv,
- false, tcf_block_offload_in_use(block),
- NULL);
- list_del(&block_cb->list);
- kfree(block_cb);
-}
-EXPORT_SYMBOL(__tcf_block_cb_unregister);
-
-void tcf_block_cb_unregister(struct tcf_block *block,
- tc_setup_cb_t *cb, void *cb_ident)
-{
- struct tcf_block_cb *block_cb;
-
- block_cb = tcf_block_cb_lookup(block, cb, cb_ident);
- if (!block_cb)
- return;
- __tcf_block_cb_unregister(block, block_cb);
-}
-EXPORT_SYMBOL(tcf_block_cb_unregister);
-
/* Main classifier routine: scans classifier chain attached
* to this qdisc, (optionally) tests for protocol and asks
* specific classifiers.
--
2.11.0
^ permalink raw reply related
* [PATCH net-next 04/12] net: sched: add tcf_block_setup()
From: Pablo Neira Ayuso @ 2019-06-20 19:49 UTC (permalink / raw)
To: netdev
Cc: netfilter-devel, davem, thomas.lendacky, f.fainelli, ariel.elior,
michael.chan, santosh, madalin.bucur, yisen.zhuang, salil.mehta,
jeffrey.t.kirsher, tariqt, saeedm, jiri, idosch, jakub.kicinski,
peppe.cavallaro, grygorii.strashko, andrew, vivien.didelot,
alexandre.torgue, joabreu, linux-net-drivers, ganeshgr, ogerlitz,
Manish.Chopra, marcelo.leitner, mkubecek, venkatkumar.duvvuru,
cphealy
In-Reply-To: <20190620194917.2298-1-pablo@netfilter.org>
This new function allows us to handle tcf_block_cb registrations /
unregistrations from the core, in order to remove a dependency with the
tcf_block object and the .reoffload cls_api callback.
The tcf_block_cb_add() call places the tcf_block_cb object, which has
been set up by the driver, in the tc_block_offload->cb_list. This is a
temporary list that is used to convey the tcf_block_cb objects back to
the core for registration. This patch adds a global tcf_block_cb_list.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/net/pkt_cls.h | 19 ++++++++++
net/sched/cls_api.c | 102 +++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 120 insertions(+), 1 deletion(-)
diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index 2816297449ee..4fbed2ccfa6b 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -75,6 +75,13 @@ static inline struct Qdisc *tcf_block_q(struct tcf_block *block)
struct tcf_block_cb *tcf_block_cb_alloc(tc_setup_cb_t *cb,
void *cb_ident, void *cb_priv);
void tcf_block_cb_free(struct tcf_block_cb *block_cb);
+
+struct tc_block_offload;
+void tcf_block_cb_add(struct tcf_block_cb *block_cb,
+ struct tc_block_offload *offload);
+void tcf_block_cb_remove(struct tcf_block_cb *block_cb,
+ struct tc_block_offload *offload);
+
void *tcf_block_cb_priv(struct tcf_block_cb *block_cb);
struct tcf_block_cb *tcf_block_cb_lookup(struct tcf_block *block,
tc_setup_cb_t *cb, void *cb_ident);
@@ -163,6 +170,17 @@ static inline void tcf_block_cb_free(struct tcf_block_cb *block_cb)
{
}
+struct tc_block_offload;
+static inline void tcf_block_cb_add(struct tcf_block_cb *block_cb,
+ struct tc_block_offload *offload)
+{
+}
+
+static inline void tcf_block_cb_remove(struct tcf_block_cb *block_cb,
+ struct tc_block_offload *offload)
+{
+}
+
static inline
void *tcf_block_cb_priv(struct tcf_block_cb *block_cb)
{
@@ -631,6 +649,7 @@ enum tc_block_command {
struct tc_block_offload {
enum tc_block_command command;
enum tcf_block_binder_type binder_type;
+ struct list_head cb_list;
struct tcf_block *block;
struct netlink_ext_ack *extack;
};
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index b86475ab8f63..78050d16ff74 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -710,6 +710,7 @@ static bool tcf_block_offload_in_use(struct tcf_block *block)
}
struct tcf_block_cb {
+ struct list_head global_list;
struct list_head list;
tc_setup_cb_t *cb;
void *cb_ident;
@@ -723,6 +724,8 @@ void *tcf_block_cb_priv(struct tcf_block_cb *block_cb)
}
EXPORT_SYMBOL(tcf_block_cb_priv);
+static LIST_HEAD(tcf_block_cb_list);
+
struct tcf_block_cb *tcf_block_cb_lookup(struct tcf_block *block,
tc_setup_cb_t *cb, void *cb_ident)
{ struct tcf_block_cb *block_cb;
@@ -769,6 +772,20 @@ void tcf_block_cb_free(struct tcf_block_cb *block_cb)
}
EXPORT_SYMBOL(tcf_block_cb_free);
+void tcf_block_cb_add(struct tcf_block_cb *block_cb,
+ struct tc_block_offload *offload)
+{
+ list_add_tail(&block_cb->global_list, &offload->cb_list);
+}
+EXPORT_SYMBOL(tcf_block_cb_add);
+
+void tcf_block_cb_remove(struct tcf_block_cb *block_cb,
+ struct tc_block_offload *offload)
+{
+ list_move(&block_cb->global_list, &offload->cb_list);
+}
+EXPORT_SYMBOL(tcf_block_cb_remove);
+
struct tcf_block_cb *__tcf_block_cb_register(struct tcf_block *block,
tc_setup_cb_t *cb, void *cb_ident,
void *cb_priv,
@@ -828,6 +845,77 @@ void tcf_block_cb_unregister(struct tcf_block *block,
}
EXPORT_SYMBOL(tcf_block_cb_unregister);
+static int tcf_block_bind(struct tcf_block *block, struct tc_block_offload *bo)
+{
+ struct tcf_block_cb *block_cb, *next;
+ int err, i = 0;
+
+ list_for_each_entry(block_cb, &bo->cb_list, global_list) {
+ err = tcf_block_playback_offloads(block, block_cb->cb,
+ block_cb->cb_priv, true,
+ tcf_block_offload_in_use(block),
+ bo->extack);
+ if (err)
+ goto err_unroll;
+
+ list_add(&block_cb->list, &block->cb_list);
+ i++;
+ }
+ list_splice(&bo->cb_list, &tcf_block_cb_list);
+
+ return 0;
+
+err_unroll:
+ list_for_each_entry_safe(block_cb, next, &bo->cb_list, global_list) {
+ if (i-- > 0) {
+ list_del(&block_cb->list);
+ tcf_block_playback_offloads(block, block_cb->cb,
+ block_cb->cb_priv, false,
+ tcf_block_offload_in_use(block),
+ NULL);
+ }
+ kfree(block_cb);
+ }
+
+ return err;
+}
+
+static void tcf_block_unbind(struct tcf_block *block,
+ struct tc_block_offload *bo)
+{
+ struct tcf_block_cb *block_cb, *next;
+
+ list_for_each_entry_safe(block_cb, next, &bo->cb_list, global_list) {
+ list_del(&block_cb->global_list);
+ tcf_block_playback_offloads(block, block_cb->cb,
+ block_cb->cb_priv, false,
+ tcf_block_offload_in_use(block),
+ NULL);
+ list_del(&block_cb->list);
+ tcf_block_cb_free(block_cb);
+ }
+}
+
+static int tcf_block_setup(struct tcf_block *block, struct tc_block_offload *bo)
+{
+ int err;
+
+ switch (bo->command) {
+ case TC_BLOCK_BIND:
+ err = tcf_block_bind(block, bo);
+ break;
+ case TC_BLOCK_UNBIND:
+ err = 0;
+ tcf_block_unbind(block, bo);
+ break;
+ default:
+ WARN_ON_ONCE(1);
+ err = -EOPNOTSUPP;
+ }
+
+ return err;
+}
+
static struct rhashtable indr_setup_block_ht;
struct tc_indr_block_dev {
@@ -944,12 +1032,14 @@ static void tc_indr_block_ing_cmd(struct tc_indr_block_dev *indr_dev,
.binder_type = TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS,
.block = indr_dev->block,
};
+ INIT_LIST_HEAD(&bo.cb_list);
if (!indr_dev->block)
return;
indr_block_cb->cb(indr_dev->dev, indr_block_cb->cb_priv, TC_SETUP_BLOCK,
&bo);
+ tcf_block_setup(indr_dev->block, &bo);
}
int __tc_indr_block_cb_register(struct net_device *dev, void *cb_priv,
@@ -1033,6 +1123,7 @@ static void tc_indr_block_call(struct tcf_block *block, struct net_device *dev,
.block = block,
.extack = extack,
};
+ INIT_LIST_HEAD(&bo.cb_list);
indr_dev = tc_indr_block_dev_lookup(dev);
if (!indr_dev)
@@ -1043,6 +1134,8 @@ static void tc_indr_block_call(struct tcf_block *block, struct net_device *dev,
list_for_each_entry(indr_block_cb, &indr_dev->cb_list, list)
indr_block_cb->cb(dev, indr_block_cb->cb_priv, TC_SETUP_BLOCK,
&bo);
+
+ tcf_block_setup(block, &bo);
}
static int tcf_block_offload_cmd(struct tcf_block *block,
@@ -1052,12 +1145,19 @@ static int tcf_block_offload_cmd(struct tcf_block *block,
struct netlink_ext_ack *extack)
{
struct tc_block_offload bo = {};
+ int err;
bo.command = command;
bo.binder_type = ei->binder_type;
bo.block = block;
bo.extack = extack;
- return dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_BLOCK, &bo);
+ INIT_LIST_HEAD(&bo.cb_list);
+
+ err = dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_BLOCK, &bo);
+ if (err < 0)
+ return err;
+
+ return tcf_block_setup(block, &bo);
}
static int tcf_block_offload_bind(struct tcf_block *block, struct Qdisc *q,
--
2.11.0
^ permalink raw reply related
* [PATCH net-next 05/12] net: sched: add release callback to struct tcf_block_cb
From: Pablo Neira Ayuso @ 2019-06-20 19:49 UTC (permalink / raw)
To: netdev
Cc: netfilter-devel, davem, thomas.lendacky, f.fainelli, ariel.elior,
michael.chan, santosh, madalin.bucur, yisen.zhuang, salil.mehta,
jeffrey.t.kirsher, tariqt, saeedm, jiri, idosch, jakub.kicinski,
peppe.cavallaro, grygorii.strashko, andrew, vivien.didelot,
alexandre.torgue, joabreu, linux-net-drivers, ganeshgr, ogerlitz,
Manish.Chopra, marcelo.leitner, mkubecek, venkatkumar.duvvuru,
cphealy
In-Reply-To: <20190620194917.2298-1-pablo@netfilter.org>
Call it on tcf_block_cb object to release the driver private block area.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/net/pkt_cls.h | 6 ++++--
net/sched/cls_api.c | 10 ++++++++--
2 files changed, 12 insertions(+), 4 deletions(-)
diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index 4fbed2ccfa6b..db4d32266a03 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -73,7 +73,8 @@ static inline struct Qdisc *tcf_block_q(struct tcf_block *block)
}
struct tcf_block_cb *tcf_block_cb_alloc(tc_setup_cb_t *cb,
- void *cb_ident, void *cb_priv);
+ void *cb_ident, void *cb_priv,
+ void (*release)(void *cb_priv));
void tcf_block_cb_free(struct tcf_block_cb *block_cb);
struct tc_block_offload;
@@ -161,7 +162,8 @@ void tc_setup_cb_block_unregister(struct tcf_block *block, tc_setup_cb_t *cb,
}
static inline struct tcf_block_cb *
-tcf_block_cb_alloc(tc_setup_cb_t *cb, void *cb_ident, void *cb_priv)
+tcf_block_cb_alloc(tc_setup_cb_t *cb, void *cb_ident, void *cb_priv,
+ void (*release)(void *cb_priv))
{
return NULL;
}
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 78050d16ff74..707c2ae0a15f 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -713,6 +713,7 @@ struct tcf_block_cb {
struct list_head global_list;
struct list_head list;
tc_setup_cb_t *cb;
+ void (*release)(void *cb_priv);
void *cb_ident;
void *cb_priv;
unsigned int refcnt;
@@ -750,7 +751,8 @@ unsigned int tcf_block_cb_decref(struct tcf_block_cb *block_cb)
EXPORT_SYMBOL(tcf_block_cb_decref);
struct tcf_block_cb *tcf_block_cb_alloc(tc_setup_cb_t *cb,
- void *cb_ident, void *cb_priv)
+ void *cb_ident, void *cb_priv,
+ void (*release)(void *cb_priv))
{
struct tcf_block_cb *block_cb;
@@ -760,6 +762,7 @@ struct tcf_block_cb *tcf_block_cb_alloc(tc_setup_cb_t *cb,
block_cb->cb = cb;
block_cb->cb_ident = cb_ident;
+ block_cb->release = release;
block_cb->cb_priv = cb_priv;
return block_cb;
@@ -768,6 +771,9 @@ EXPORT_SYMBOL(tcf_block_cb_alloc);
void tcf_block_cb_free(struct tcf_block_cb *block_cb)
{
+ if (block_cb->release)
+ block_cb->release(block_cb->cb_priv);
+
kfree(block_cb);
}
EXPORT_SYMBOL(tcf_block_cb_free);
@@ -801,7 +807,7 @@ struct tcf_block_cb *__tcf_block_cb_register(struct tcf_block *block,
if (err)
return ERR_PTR(err);
- block_cb = tcf_block_cb_alloc(cb, cb_ident, cb_priv);
+ block_cb = tcf_block_cb_alloc(cb, cb_ident, cb_priv, NULL);
if (!block_cb)
return ERR_PTR(-ENOMEM);
--
2.11.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox