* Re: [PATCH v3 net-next 3/6] tcp: add SACK compression
From: Yuchung Cheng @ 2018-05-17 22:14 UTC (permalink / raw)
To: Neal Cardwell
Cc: Eric Dumazet, David Miller, Netdev,
Toke Høiland-Jørgensen, Soheil Hassas Yeganeh,
Eric Dumazet
In-Reply-To: <CADVnQykUpdC+2e94_x9v9iX6RC7ro=bkvH5Q7-p0pbtBhHyU=A@mail.gmail.com>
On Thu, May 17, 2018 at 2:57 PM, Neal Cardwell <ncardwell@google.com> wrote:
> On Thu, May 17, 2018 at 5:47 PM Eric Dumazet <edumazet@google.com> wrote:
>
>> When TCP receives an out-of-order packet, it immediately sends
>> a SACK packet, generating network load but also forcing the
>> receiver to send 1-MSS pathological packets, increasing its
>> RTX queue length/depth, and thus processing time.
>
>> Wifi networks suffer from this aggressive behavior, but generally
>> speaking, all these SACK packets add fuel to the fire when networks
>> are under congestion.
>
>> This patch adds a high resolution timer and tp->compressed_ack counter.
>
>> Instead of sending a SACK, we program this timer with a small delay,
>> based on RTT and capped to 1 ms :
>
>> delay = min ( 5 % of RTT, 1 ms)
>
>> If subsequent SACKs need to be sent while the timer has not yet
>> expired, we simply increment tp->compressed_ack.
>
>> When timer expires, a SACK is sent with the latest information.
>> Whenever an ACK is sent (if data is sent, or if in-order
>> data is received) timer is canceled.
>
>> Note that tcp_sack_new_ofo_skb() is able to force a SACK to be sent
>> if the sack blocks need to be shuffled, even if the timer has not
>> expired.
>
>> A new SNMP counter is added in the following patch.
>
>> Two other patches add sysctls to allow changing the 1,000,000 and 44
>> values that this commit hard-coded.
>
>> Signed-off-by: Eric Dumazet <edumazet@google.com>
>> ---
>
> Very nice. I like the constants and the min(rcv_rtt, srtt).
>
> Acked-by: Neal Cardwell <ncardwell@google.com>
Acked-by: Yuchung Cheng <ycheng@google.com>
Great work. Hopefully this would save middle-boxes' from handling
TCP-ACK themselves.
>
> Thanks!
>
> neal
^ permalink raw reply
* Re: [patch net-next RFC 04/12] dsa: set devlink port attrs for dsa ports
From: Florian Fainelli @ 2018-05-17 22:06 UTC (permalink / raw)
To: Andrew Lunn, Jiri Pirko
Cc: netdev, davem, idosch, jakub.kicinski, mlxsw, vivien.didelot,
michael.chan, ganeshgr, saeedm, simon.horman,
pieter.jansenvanvuuren, john.hurley, dirk.vandermerwe,
alexander.h.duyck, ogerlitz, dsahern, vijaya.guvva,
satananda.burla, raghu.vatsavayi, felix.manlunas, gospo,
sathya.perla, vasundhara-v.volam, tariqt, eranbe,
jeffrey.t.kirsher
In-Reply-To: <20180517210856.GJ23601@lunn.ch>
On 05/17/2018 02:08 PM, Andrew Lunn wrote:
> On Thu, May 17, 2018 at 10:48:55PM +0200, Jiri Pirko wrote:
>> Thu, May 17, 2018 at 09:14:32PM CEST, f.fainelli@gmail.com wrote:
>>> On 05/17/2018 10:39 AM, Jiri Pirko wrote:
>>>>>> That is compiled inside "fixed_phy", isn't it?
>>>>>
>>>>> It matches what CONFIG_FIXED_PHY is, so if it's built-in it also becomes
>>>>> built-in, if is modular, it is also modular, this was fixed with
>>>>> 40013ff20b1beed31184935fc0aea6a859d4d4ef ("net: dsa: Fix functional
>>>>> dsa-loop dependency on FIXED_PHY")
>>>>
>>>> Now I have it compiled as module, and after modprobe dsa_loop I see:
>>>> [ 1168.129202] libphy: Fixed MDIO Bus: probed
>>>> [ 1168.222716] dsa-loop fixed-0:1f: DSA mockup driver: 0x1f
>>>>
>>>> This messages I did not see when I had fixed_phy compiled as buildin.
>>>>
>>>> But I still see no netdevs :/
>>>
>>> The platform data assumes there is a network device named "eth0" as the
>>
>> Oups, I missed, I created dummy device and modprobed again. Now I see:
>>
>> $ sudo devlink port
>> mdio_bus/fixed-0:1f/0: type eth netdev lan1
>> mdio_bus/fixed-0:1f/1: type eth netdev lan2
>> mdio_bus/fixed-0:1f/2: type eth netdev lan3
>> mdio_bus/fixed-0:1f/3: type eth netdev lan4
>> mdio_bus/fixed-0:1f/4: type notset
>> mdio_bus/fixed-0:1f/5: type notset
>> mdio_bus/fixed-0:1f/6: type notset
>> mdio_bus/fixed-0:1f/7: type notset
>> mdio_bus/fixed-0:1f/8: type notset
>> mdio_bus/fixed-0:1f/9: type notset
>> mdio_bus/fixed-0:1f/10: type notset
>> mdio_bus/fixed-0:1f/11: type notset
>>
>> I wonder why there are ports 4-11
>
> Hi Jiri
>
> ds = dsa_switch_alloc(&mdiodev->dev, DSA_MAX_PORTS);
>
> It is allocating a switch with 12 ports. However only 4 of them have
> names. So the core only creates slave devices for those 4.
>
> This is a useful test. Real hardware often has unused ports. A WiFi AP
> with a 7 port switch which only uses 6 ports is often seen.
The following patch should fix this:
diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
index adf50fbc4c13..a06c29ec91f0 100644
--- a/net/dsa/dsa2.c
+++ b/net/dsa/dsa2.c
@@ -262,13 +262,14 @@ static int dsa_port_setup(struct dsa_port *dp)
memset(&dp->devlink_port, 0, sizeof(dp->devlink_port));
+ if (dp->type == DSA_PORT_TYPE_UNUSED)
+ return 0;
+
err = devlink_port_register(ds->devlink, &dp->devlink_port,
dp->index);
if (err)
return err;
switch (dp->type) {
- case DSA_PORT_TYPE_UNUSED:
- break;
case DSA_PORT_TYPE_CPU:
case DSA_PORT_TYPE_DSA:
err = dsa_port_link_register_of(dp);
@@ -286,6 +287,8 @@ static int dsa_port_setup(struct dsa_port *dp)
else
devlink_port_type_eth_set(&dp->devlink_port,
dp->slave);
break;
+ default:
+ break;
}
return 0;
@@ -293,11 +296,12 @@ static int dsa_port_setup(struct dsa_port *dp)
static void dsa_port_teardown(struct dsa_port *dp)
{
+ if (dp->type == DSA_PORT_TYPE_UNUSED)
+ return;
+
devlink_port_unregister(&dp->devlink_port);
switch (dp->type) {
- case DSA_PORT_TYPE_UNUSED:
- break;
case DSA_PORT_TYPE_CPU:
case DSA_PORT_TYPE_DSA:
dsa_port_link_unregister_of(dp);
@@ -308,6 +312,8 @@ static void dsa_port_teardown(struct dsa_port *dp)
dp->slave = NULL;
}
break;
+ default:
+ break;
}
}
--
Florian
^ permalink raw reply related
* Re: [PATCH v3 net-next 6/6] tcp: add tcp_comp_sack_nr sysctl
From: Neal Cardwell @ 2018-05-17 22:01 UTC (permalink / raw)
To: Eric Dumazet
Cc: David Miller, Netdev, Toke Høiland-Jørgensen,
Yuchung Cheng, Soheil Hassas Yeganeh, Eric Dumazet
In-Reply-To: <20180517214729.186094-7-edumazet@google.com>
On Thu, May 17, 2018 at 5:47 PM Eric Dumazet <edumazet@google.com> wrote:
> This per netns sysctl allows for TCP SACK compression fine-tuning.
> This limits number of SACK that can be compressed.
> Using 0 disables SACK compression.
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> ---
Acked-by: Neal Cardwell <ncardwell@google.com>
Thanks!
neal
^ permalink raw reply
* Re: [PATCH v3 net-next 5/6] tcp: add tcp_comp_sack_delay_ns sysctl
From: Neal Cardwell @ 2018-05-17 21:59 UTC (permalink / raw)
To: Eric Dumazet
Cc: David Miller, Netdev, Toke Høiland-Jørgensen,
Yuchung Cheng, Soheil Hassas Yeganeh, Eric Dumazet
In-Reply-To: <20180517214729.186094-6-edumazet@google.com>
On Thu, May 17, 2018 at 5:47 PM Eric Dumazet <edumazet@google.com> wrote:
> This per netns sysctl allows for TCP SACK compression fine-tuning.
> Its default value is 1,000,000, or 1 ms to meet TSO autosizing period.
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> ---
Acked-by: Neal Cardwell <ncardwell@google.com>
Thanks!
neal
^ permalink raw reply
* Re: [PATCH v3 net-next 3/6] tcp: add SACK compression
From: Neal Cardwell @ 2018-05-17 21:57 UTC (permalink / raw)
To: Eric Dumazet
Cc: David Miller, Netdev, Toke Høiland-Jørgensen,
Yuchung Cheng, Soheil Hassas Yeganeh, Eric Dumazet
In-Reply-To: <20180517214729.186094-4-edumazet@google.com>
On Thu, May 17, 2018 at 5:47 PM Eric Dumazet <edumazet@google.com> wrote:
> When TCP receives an out-of-order packet, it immediately sends
> a SACK packet, generating network load but also forcing the
> receiver to send 1-MSS pathological packets, increasing its
> RTX queue length/depth, and thus processing time.
> Wifi networks suffer from this aggressive behavior, but generally
> speaking, all these SACK packets add fuel to the fire when networks
> are under congestion.
> This patch adds a high resolution timer and tp->compressed_ack counter.
> Instead of sending a SACK, we program this timer with a small delay,
> based on RTT and capped to 1 ms :
> delay = min ( 5 % of RTT, 1 ms)
> If subsequent SACKs need to be sent while the timer has not yet
> expired, we simply increment tp->compressed_ack.
> When timer expires, a SACK is sent with the latest information.
> Whenever an ACK is sent (if data is sent, or if in-order
> data is received) timer is canceled.
> Note that tcp_sack_new_ofo_skb() is able to force a SACK to be sent
> if the sack blocks need to be shuffled, even if the timer has not
> expired.
> A new SNMP counter is added in the following patch.
> Two other patches add sysctls to allow changing the 1,000,000 and 44
> values that this commit hard-coded.
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> ---
Very nice. I like the constants and the min(rcv_rtt, srtt).
Acked-by: Neal Cardwell <ncardwell@google.com>
Thanks!
neal
^ permalink raw reply
* Re: [RFC PATCH ghak32 V2 01/13] audit: add container id
From: Richard Guy Briggs @ 2018-05-17 21:56 UTC (permalink / raw)
To: Steve Grubb
Cc: cgroups, containers, linux-api, Linux-Audit Mailing List,
linux-fsdevel, LKML, netdev, ebiederm, luto, jlayton, carlos,
dhowells, viro, simo, eparis, serge
In-Reply-To: <20180517170053.7d4afa87@ivy-bridge>
On 2018-05-17 17:00, Steve Grubb wrote:
> On Fri, 16 Mar 2018 05:00:28 -0400
> Richard Guy Briggs <rgb@redhat.com> wrote:
>
> > Implement the proc fs write to set the audit container ID of a
> > process, emitting an AUDIT_CONTAINER record to document the event.
> >
> > This is a write from the container orchestrator task to a proc entry
> > of the form /proc/PID/containerid where PID is the process ID of the
> > newly created task that is to become the first task in a container,
> > or an additional task added to a container.
> >
> > The write expects up to a u64 value (unset: 18446744073709551615).
> >
> > This will produce a record such as this:
> > type=CONTAINER msg=audit(1519903238.968:261): op=set pid=596 uid=0
> > subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 auid=0
> > tty=pts0 ses=1 opid=596 old-contid=18446744073709551615 contid=123455
> > res=0
>
> The was one thing I was wondering about. Currently when we set the
> loginuid, the record is AUDIT_LOGINUID. The corollary is that when we
> set the container id, the event should be AUDIT_CONTAINERID or
> AUDIT_CONTAINER_ID.
The record type is actually AUDIT_LOGIN. The field type is
AUDIT_LOGINUID. Given that correction, I think we're fine and could
potentially violently agree. The existing naming is consistent.
> During syscall events, the path info is returned in a a record simply
> called AUDIT_PATH, cwd info is returned in AUDIT_CWD. So, rather than
> calling the record that gets attached to everything
> AUDIT_CONTAINER_INFO, how about simply AUDIT_CONTAINER.
Considering the container initiation record is different than the record
to document the container involved in an otherwise normal syscall, we
need two names. I don't have a strong opinion what they are.
I'd prefer AUDIT_CONTAINER and AUDIT_CONTAINER_INFO so that the two are
different enough to be visually distinct while leaving
AUDIT_CONTAINERID for the field type in patch 4 ("audit: add containerid
filtering")
> > The "op" field indicates an initial set. The "pid" to "ses" fields
> > are the orchestrator while the "opid" field is the object's PID, the
> > process being "contained". Old and new container ID values are given
> > in the "contid" fields, while res indicates its success.
> >
> > It is not permitted to self-set, unset or re-set the container ID. A
> > child inherits its parent's container ID, but then can be set only
> > once after.
> >
> > See: https://github.com/linux-audit/audit-kernel/issues/32
> >
> > Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> > ---
> > fs/proc/base.c | 37 ++++++++++++++++++++
> > include/linux/audit.h | 16 +++++++++
> > include/linux/init_task.h | 4 ++-
> > include/linux/sched.h | 1 +
> > include/uapi/linux/audit.h | 2 ++
> > kernel/auditsc.c | 84
> > ++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 143
> > insertions(+), 1 deletion(-)
> >
> > diff --git a/fs/proc/base.c b/fs/proc/base.c
> > index 60316b5..6ce4fbe 100644
> > --- a/fs/proc/base.c
> > +++ b/fs/proc/base.c
> > @@ -1299,6 +1299,41 @@ static ssize_t proc_sessionid_read(struct file
> > * file, char __user * buf, .read = proc_sessionid_read,
> > .llseek = generic_file_llseek,
> > };
> > +
> > +static ssize_t proc_containerid_write(struct file *file, const char
> > __user *buf,
> > + size_t count, loff_t *ppos)
> > +{
> > + struct inode *inode = file_inode(file);
> > + u64 containerid;
> > + int rv;
> > + struct task_struct *task = get_proc_task(inode);
> > +
> > + if (!task)
> > + return -ESRCH;
> > + if (*ppos != 0) {
> > + /* No partial writes. */
> > + put_task_struct(task);
> > + return -EINVAL;
> > + }
> > +
> > + rv = kstrtou64_from_user(buf, count, 10, &containerid);
> > + if (rv < 0) {
> > + put_task_struct(task);
> > + return rv;
> > + }
> > +
> > + rv = audit_set_containerid(task, containerid);
> > + put_task_struct(task);
> > + if (rv < 0)
> > + return rv;
> > + return count;
> > +}
> > +
> > +static const struct file_operations proc_containerid_operations = {
> > + .write = proc_containerid_write,
> > + .llseek = generic_file_llseek,
> > +};
> > +
> > #endif
> >
> > #ifdef CONFIG_FAULT_INJECTION
> > @@ -2961,6 +2996,7 @@ static int proc_pid_patch_state(struct seq_file
> > *m, struct pid_namespace *ns, #ifdef CONFIG_AUDITSYSCALL
> > REG("loginuid", S_IWUSR|S_IRUGO, proc_loginuid_operations),
> > REG("sessionid", S_IRUGO, proc_sessionid_operations),
> > + REG("containerid", S_IWUSR, proc_containerid_operations),
> > #endif
> > #ifdef CONFIG_FAULT_INJECTION
> > REG("make-it-fail", S_IRUGO|S_IWUSR,
> > proc_fault_inject_operations), @@ -3355,6 +3391,7 @@ static int
> > proc_tid_comm_permission(struct inode *inode, int mask) #ifdef
> > CONFIG_AUDITSYSCALL REG("loginuid", S_IWUSR|S_IRUGO,
> > proc_loginuid_operations), REG("sessionid", S_IRUGO,
> > proc_sessionid_operations),
> > + REG("containerid", S_IWUSR, proc_containerid_operations),
> > #endif
> > #ifdef CONFIG_FAULT_INJECTION
> > REG("make-it-fail", S_IRUGO|S_IWUSR,
> > proc_fault_inject_operations), diff --git a/include/linux/audit.h
> > b/include/linux/audit.h index af410d9..fe4ba3f 100644
> > --- a/include/linux/audit.h
> > +++ b/include/linux/audit.h
> > @@ -29,6 +29,7 @@
> >
> > #define AUDIT_INO_UNSET ((unsigned long)-1)
> > #define AUDIT_DEV_UNSET ((dev_t)-1)
> > +#define INVALID_CID AUDIT_CID_UNSET
> >
> > struct audit_sig_info {
> > uid_t uid;
> > @@ -321,6 +322,7 @@ static inline void audit_ptrace(struct
> > task_struct *t) extern int auditsc_get_stamp(struct audit_context
> > *ctx, struct timespec64 *t, unsigned int *serial);
> > extern int audit_set_loginuid(kuid_t loginuid);
> > +extern int audit_set_containerid(struct task_struct *tsk, u64
> > containerid);
> > static inline kuid_t audit_get_loginuid(struct task_struct *tsk)
> > {
> > @@ -332,6 +334,11 @@ static inline unsigned int
> > audit_get_sessionid(struct task_struct *tsk) return tsk->sessionid;
> > }
> >
> > +static inline u64 audit_get_containerid(struct task_struct *tsk)
> > +{
> > + return tsk->containerid;
> > +}
> > +
> > extern void __audit_ipc_obj(struct kern_ipc_perm *ipcp);
> > extern void __audit_ipc_set_perm(unsigned long qbytes, uid_t uid,
> > gid_t gid, umode_t mode); extern void __audit_bprm(struct
> > linux_binprm *bprm); @@ -517,6 +524,10 @@ static inline unsigned int
> > audit_get_sessionid(struct task_struct *tsk) {
> > return -1;
> > }
> > +static inline kuid_t audit_get_containerid(struct task_struct *tsk)
> > +{
> > + return INVALID_CID;
> > +}
> > static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp)
> > { }
> > static inline void audit_ipc_set_perm(unsigned long qbytes, uid_t
> > uid, @@ -581,6 +592,11 @@ static inline bool
> > audit_loginuid_set(struct task_struct *tsk) return
> > uid_valid(audit_get_loginuid(tsk)); }
> >
> > +static inline bool audit_containerid_set(struct task_struct *tsk)
> > +{
> > + return audit_get_containerid(tsk) != INVALID_CID;
> > +}
> > +
> > static inline void audit_log_string(struct audit_buffer *ab, const
> > char *buf) {
> > audit_log_n_string(ab, buf, strlen(buf));
> > diff --git a/include/linux/init_task.h b/include/linux/init_task.h
> > index 6a53262..046bd0a 100644
> > --- a/include/linux/init_task.h
> > +++ b/include/linux/init_task.h
> > @@ -18,6 +18,7 @@
> > #include <linux/sched/rt.h>
> > #include <linux/livepatch.h>
> > #include <linux/mm_types.h>
> > +#include <linux/audit.h>
> >
> > #include <asm/thread_info.h>
> >
> > @@ -120,7 +121,8 @@
> > #ifdef CONFIG_AUDITSYSCALL
> > #define INIT_IDS \
> > .loginuid = INVALID_UID, \
> > - .sessionid = (unsigned int)-1,
> > + .sessionid = (unsigned int)-1, \
> > + .containerid = INVALID_CID,
> > #else
> > #define INIT_IDS
> > #endif
> > diff --git a/include/linux/sched.h b/include/linux/sched.h
> > index d258826..1b82191 100644
> > --- a/include/linux/sched.h
> > +++ b/include/linux/sched.h
> > @@ -796,6 +796,7 @@ struct task_struct {
> > #ifdef CONFIG_AUDITSYSCALL
> > kuid_t loginuid;
> > unsigned int sessionid;
> > + u64 containerid;
> > #endif
> > struct seccomp seccomp;
> >
> > diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
> > index 4e61a9e..921a71f 100644
> > --- a/include/uapi/linux/audit.h
> > +++ b/include/uapi/linux/audit.h
> > @@ -71,6 +71,7 @@
> > #define AUDIT_TTY_SET 1017 /* Set TTY auditing
> > status */ #define AUDIT_SET_FEATURE 1018 /* Turn an
> > audit feature on or off */ #define AUDIT_GET_FEATURE
> > 1019 /* Get which features are enabled */ +#define
> > AUDIT_CONTAINER 1020 /* Define the container id
> > and information */ #define AUDIT_FIRST_USER_MSG 1100 /*
> > Userspace messages mostly uninteresting to kernel */ #define
> > AUDIT_USER_AVC 1107 /* We filter this
> > differently */ @@ -465,6 +466,7 @@ struct audit_tty_status { };
> >
> > #define AUDIT_UID_UNSET (unsigned int)-1
> > +#define AUDIT_CID_UNSET ((u64)-1)
> >
> > /* audit_rule_data supports filter rules with both integer and string
> > * fields. It corresponds with AUDIT_ADD_RULE, AUDIT_DEL_RULE and
> > diff --git a/kernel/auditsc.c b/kernel/auditsc.c
> > index 4e0a4ac..29c8482 100644
> > --- a/kernel/auditsc.c
> > +++ b/kernel/auditsc.c
> > @@ -2073,6 +2073,90 @@ int audit_set_loginuid(kuid_t loginuid)
> > return rc;
> > }
> >
> > +static int audit_set_containerid_perm(struct task_struct *task, u64
> > containerid) +{
> > + struct task_struct *parent;
> > + u64 pcontainerid, ccontainerid;
> > +
> > + /* Don't allow to set our own containerid */
> > + if (current == task)
> > + return -EPERM;
> > + /* Don't allow the containerid to be unset */
> > + if (!cid_valid(containerid))
> > + return -EINVAL;
> > + /* if we don't have caps, reject */
> > + if (!capable(CAP_AUDIT_CONTROL))
> > + return -EPERM;
> > + /* if containerid is unset, allow */
> > + if (!audit_containerid_set(task))
> > + return 0;
> > + /* it is already set, and not inherited from the parent,
> > reject */
> > + ccontainerid = audit_get_containerid(task);
> > + rcu_read_lock();
> > + parent = rcu_dereference(task->real_parent);
> > + rcu_read_unlock();
> > + task_lock(parent);
> > + pcontainerid = audit_get_containerid(parent);
> > + task_unlock(parent);
> > + if (ccontainerid != pcontainerid)
> > + return -EPERM;
> > + return 0;
> > +}
> > +
> > +static void audit_log_set_containerid(struct task_struct *task, u64
> > oldcontainerid,
> > + u64 containerid, int rc)
> > +{
> > + struct audit_buffer *ab;
> > + uid_t uid;
> > + struct tty_struct *tty;
> > +
> > + if (!audit_enabled)
> > + return;
> > +
> > + ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONTAINER);
> > + if (!ab)
> > + return;
> > +
> > + uid = from_kuid(&init_user_ns, task_uid(current));
> > + tty = audit_get_tty(current);
> > +
> > + audit_log_format(ab, "op=set pid=%d uid=%u",
> > task_tgid_nr(current), uid);
> > + audit_log_task_context(ab);
> > + audit_log_format(ab, " auid=%u tty=%s ses=%u opid=%d
> > old-contid=%llu contid=%llu res=%d",
>
> The preferred ordering would be: op, opid, old-contid, contid, pid, uid,
> tty, ses, subj, comm, exe, res. This groups the searchable fields
> together using the most common ordering so that parsing is simple.
There has been a suggestion to make this a syscall-connected record, and
if that is the case, we'd simply drop all the fields that would be
duplicated by the syscall record. Otherwise, I'll use your suggested
order.
As you may recall this suggestion was also made for the AUDIT_LOGIN
record.
> Thanks,
> -Steve
>
> > + from_kuid(&init_user_ns,
> > audit_get_loginuid(current)),
> > + tty ? tty_name(tty) : "(none)",
> > audit_get_sessionid(current),
> > + task_tgid_nr(task), oldcontainerid,
> > containerid, !rc); +
> > + audit_put_tty(tty);
> > + audit_log_end(ab);
> > +}
> > +
> > +/**
> > + * audit_set_containerid - set current task's audit_context
> > containerid
> > + * @containerid: containerid value
> > + *
> > + * Returns 0 on success, -EPERM on permission failure.
> > + *
> > + * Called (set) from fs/proc/base.c::proc_containerid_write().
> > + */
> > +int audit_set_containerid(struct task_struct *task, u64 containerid)
> > +{
> > + u64 oldcontainerid;
> > + int rc;
> > +
> > + oldcontainerid = audit_get_containerid(task);
> > +
> > + rc = audit_set_containerid_perm(task, containerid);
> > + if (!rc) {
> > + task_lock(task);
> > + task->containerid = containerid;
> > + task_unlock(task);
> > + }
> > +
> > + audit_log_set_containerid(task, oldcontainerid, containerid,
> > rc);
> > + return rc;
> > +}
> > +
> > /**
> > * __audit_mq_open - record audit data for a POSIX MQ open
> > * @oflag: open flag
>
- RGB
--
Richard Guy Briggs <rgb@redhat.com>
Sr. S/W Engineer, Kernel Security, Base Operating Systems
Remote, Ottawa, Red Hat Canada
IRC: rgb, SunRaycer
Voice: +1.647.777.2635, Internal: (81) 32635
^ permalink raw reply
* [net PATCH] net: Fix a bug in removing queues from XPS map
From: Amritha Nambiar @ 2018-05-17 21:50 UTC (permalink / raw)
To: netdev, davem
Cc: alexander.h.duyck, f.fainelli, amritha.nambiar, sridhar.samudrala,
edumazet, hannes, tom
While removing queues from the XPS map, the individual CPU ID
alone was used to index the CPUs map, this should be changed to also
factor in the traffic class mapping for the CPU-to-queue lookup.
Fixes: 184c449f91fe ("net: Add support for XPS with QoS via traffic classes")
Signed-off-by: Amritha Nambiar <amritha.nambiar@intel.com>
Acked-by: Alexander Duyck <alexander.h.duyck@intel.com>
---
net/core/dev.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/core/dev.c b/net/core/dev.c
index 9f43901..9397577 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2125,7 +2125,7 @@ static bool remove_xps_queue_cpu(struct net_device *dev,
int i, j;
for (i = count, j = offset; i--; j++) {
- if (!remove_xps_queue(dev_maps, cpu, j))
+ if (!remove_xps_queue(dev_maps, tci, j))
break;
}
^ permalink raw reply related
* Re: [PATCH net 0/7] net: ip6_gre: Fixes in headroom handling
From: Petr Machata @ 2018-05-17 21:53 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <20180517.171816.2160600204640507047.davem@davemloft.net>
David Miller <davem@davemloft.net> writes:
> Luckily for you, your Fixes: tags went out before I pushed, so I could
> actually fix up the commit messages and add the tags.
I was hoping that would be the case.
Thanks,
Petr
^ permalink raw reply
* [PATCH v3 net-next 6/6] tcp: add tcp_comp_sack_nr sysctl
From: Eric Dumazet @ 2018-05-17 21:47 UTC (permalink / raw)
To: David S . Miller
Cc: netdev, Toke Høiland-Jørgensen, Neal Cardwell,
Yuchung Cheng, Soheil Hassas Yeganeh, Eric Dumazet, Eric Dumazet
In-Reply-To: <20180517214729.186094-1-edumazet@google.com>
This per netns sysctl allows for TCP SACK compression fine-tuning.
This limits number of SACK that can be compressed.
Using 0 disables SACK compression.
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
Documentation/networking/ip-sysctl.txt | 6 ++++++
include/net/netns/ipv4.h | 1 +
net/ipv4/sysctl_net_ipv4.c | 10 ++++++++++
net/ipv4/tcp_input.c | 3 ++-
net/ipv4/tcp_ipv4.c | 1 +
5 files changed, 20 insertions(+), 1 deletion(-)
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index 7ba952959bca0eee4ecf81fb5837e17790db0fde..924bd51327b7a8dff3503d7afccdd54e1eb5c29b 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -532,6 +532,12 @@ tcp_comp_sack_delay_ns - LONG INTEGER
Default : 1,000,000 ns (1 ms)
+tcp_comp_sack_nr - INTEGER
+ Max numer of SACK that can be compressed.
+ Using 0 disables SACK compression.
+
+ Detault : 44
+
tcp_slow_start_after_idle - BOOLEAN
If set, provide RFC2861 behavior and time out the congestion
window after an idle period. An idle period is defined at
diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h
index 927318243cfaa2ddd8eb423c6ba6e66253f771d3..661348f23ea5a3a9320b2cafcd17e23960214771 100644
--- a/include/net/netns/ipv4.h
+++ b/include/net/netns/ipv4.h
@@ -160,6 +160,7 @@ struct netns_ipv4 {
int sysctl_tcp_pacing_ca_ratio;
int sysctl_tcp_wmem[3];
int sysctl_tcp_rmem[3];
+ int sysctl_tcp_comp_sack_nr;
unsigned long sysctl_tcp_comp_sack_delay_ns;
struct inet_timewait_death_row tcp_death_row;
int sysctl_max_syn_backlog;
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index 11fbfdc1566eca95f91360522178295318277588..d2eed3ddcb0a1ad9778d96d46c685f6c60b93d8d 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -46,6 +46,7 @@ static int tcp_syn_retries_min = 1;
static int tcp_syn_retries_max = MAX_TCP_SYNCNT;
static int ip_ping_group_range_min[] = { 0, 0 };
static int ip_ping_group_range_max[] = { GID_T_MAX, GID_T_MAX };
+static int comp_sack_nr_max = 255;
/* obsolete */
static int sysctl_tcp_low_latency __read_mostly;
@@ -1158,6 +1159,15 @@ static struct ctl_table ipv4_net_table[] = {
.mode = 0644,
.proc_handler = proc_doulongvec_minmax,
},
+ {
+ .procname = "tcp_comp_sack_nr",
+ .data = &init_net.ipv4.sysctl_tcp_comp_sack_nr,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec_minmax,
+ .extra1 = &zero,
+ .extra2 = &comp_sack_nr_max,
+ },
{
.procname = "udp_rmem_min",
.data = &init_net.ipv4.sysctl_udp_rmem_min,
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 6a1dae38c9558c7bc9dd31e9f16c4e8ea8c78149..aebb29ab2fdf2ceaa182cd11928f145a886149ff 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -5106,7 +5106,8 @@ static void __tcp_ack_snd_check(struct sock *sk, int ofo_possible)
return;
}
- if (!tcp_is_sack(tp) || tp->compressed_ack >= 44)
+ if (!tcp_is_sack(tp) ||
+ tp->compressed_ack >= sock_net(sk)->ipv4.sysctl_tcp_comp_sack_nr)
goto send_now;
tp->compressed_ack++;
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index a3f4647341db2eb5a63c3e9f1e8b93099aedadab..adbdb503db0c983ef4185f83b138aa51bafd15bf 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -2573,6 +2573,7 @@ static int __net_init tcp_sk_init(struct net *net)
sizeof(init_net.ipv4.sysctl_tcp_wmem));
}
net->ipv4.sysctl_tcp_comp_sack_delay_ns = NSEC_PER_MSEC;
+ net->ipv4.sysctl_tcp_comp_sack_nr = 44;
net->ipv4.sysctl_tcp_fastopen = TFO_CLIENT_ENABLE;
spin_lock_init(&net->ipv4.tcp_fastopen_ctx_lock);
net->ipv4.sysctl_tcp_fastopen_blackhole_timeout = 60 * 60;
--
2.17.0.441.gb46fe60e1d-goog
^ permalink raw reply related
* [PATCH v3 net-next 5/6] tcp: add tcp_comp_sack_delay_ns sysctl
From: Eric Dumazet @ 2018-05-17 21:47 UTC (permalink / raw)
To: David S . Miller
Cc: netdev, Toke Høiland-Jørgensen, Neal Cardwell,
Yuchung Cheng, Soheil Hassas Yeganeh, Eric Dumazet, Eric Dumazet
In-Reply-To: <20180517214729.186094-1-edumazet@google.com>
This per netns sysctl allows for TCP SACK compression fine-tuning.
Its default value is 1,000,000, or 1 ms to meet TSO autosizing period.
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
Documentation/networking/ip-sysctl.txt | 7 +++++++
include/net/netns/ipv4.h | 1 +
net/ipv4/sysctl_net_ipv4.c | 7 +++++++
net/ipv4/tcp_input.c | 4 ++--
net/ipv4/tcp_ipv4.c | 1 +
5 files changed, 18 insertions(+), 2 deletions(-)
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index ea304a23c8d72c92a925d0c107bfd2bcfbbb92ec..7ba952959bca0eee4ecf81fb5837e17790db0fde 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -525,6 +525,13 @@ tcp_rmem - vector of 3 INTEGERs: min, default, max
tcp_sack - BOOLEAN
Enable select acknowledgments (SACKS).
+tcp_comp_sack_delay_ns - LONG INTEGER
+ TCP tries to reduce number of SACK sent, using a timer
+ based on 5% of SRTT, capped by this sysctl, in nano seconds.
+ The default is 1ms, based on TSO autosizing period.
+
+ Default : 1,000,000 ns (1 ms)
+
tcp_slow_start_after_idle - BOOLEAN
If set, provide RFC2861 behavior and time out the congestion
window after an idle period. An idle period is defined at
diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h
index 8491bc9c86b1553ab603e4363e8e38ca7ff547e0..927318243cfaa2ddd8eb423c6ba6e66253f771d3 100644
--- a/include/net/netns/ipv4.h
+++ b/include/net/netns/ipv4.h
@@ -160,6 +160,7 @@ struct netns_ipv4 {
int sysctl_tcp_pacing_ca_ratio;
int sysctl_tcp_wmem[3];
int sysctl_tcp_rmem[3];
+ unsigned long sysctl_tcp_comp_sack_delay_ns;
struct inet_timewait_death_row tcp_death_row;
int sysctl_max_syn_backlog;
int sysctl_tcp_fastopen;
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index 4b195bac8ac0eefe0a224528ad854338c4f8e6e3..11fbfdc1566eca95f91360522178295318277588 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -1151,6 +1151,13 @@ static struct ctl_table ipv4_net_table[] = {
.proc_handler = proc_dointvec_minmax,
.extra1 = &one,
},
+ {
+ .procname = "tcp_comp_sack_delay_ns",
+ .data = &init_net.ipv4.sysctl_tcp_comp_sack_delay_ns,
+ .maxlen = sizeof(unsigned long),
+ .mode = 0644,
+ .proc_handler = proc_doulongvec_minmax,
+ },
{
.procname = "udp_rmem_min",
.data = &init_net.ipv4.sysctl_udp_rmem_min,
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index cc2ac5346b92b968593f919192d543384865bcb8..6a1dae38c9558c7bc9dd31e9f16c4e8ea8c78149 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -5113,13 +5113,13 @@ static void __tcp_ack_snd_check(struct sock *sk, int ofo_possible)
if (hrtimer_is_queued(&tp->compressed_ack_timer))
return;
- /* compress ack timer : 5 % of rtt, but no more than 1 ms */
+ /* compress ack timer : 5 % of rtt, but no more than tcp_comp_sack_delay_ns */
rtt = tp->rcv_rtt_est.rtt_us;
if (tp->srtt_us && tp->srtt_us < rtt)
rtt = tp->srtt_us;
- delay = min_t(unsigned long, NSEC_PER_MSEC,
+ delay = min_t(unsigned long, sock_net(sk)->ipv4.sysctl_tcp_comp_sack_delay_ns,
rtt * (NSEC_PER_USEC >> 3)/20);
sock_hold(sk);
hrtimer_start(&tp->compressed_ack_timer, ns_to_ktime(delay),
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index caf23de88f8a369c2038cecd34ce42c522487e90..a3f4647341db2eb5a63c3e9f1e8b93099aedadab 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -2572,6 +2572,7 @@ static int __net_init tcp_sk_init(struct net *net)
init_net.ipv4.sysctl_tcp_wmem,
sizeof(init_net.ipv4.sysctl_tcp_wmem));
}
+ net->ipv4.sysctl_tcp_comp_sack_delay_ns = NSEC_PER_MSEC;
net->ipv4.sysctl_tcp_fastopen = TFO_CLIENT_ENABLE;
spin_lock_init(&net->ipv4.tcp_fastopen_ctx_lock);
net->ipv4.sysctl_tcp_fastopen_blackhole_timeout = 60 * 60;
--
2.17.0.441.gb46fe60e1d-goog
^ permalink raw reply related
* [PATCH v3 net-next 4/6] tcp: add TCPAckCompressed SNMP counter
From: Eric Dumazet @ 2018-05-17 21:47 UTC (permalink / raw)
To: David S . Miller
Cc: netdev, Toke Høiland-Jørgensen, Neal Cardwell,
Yuchung Cheng, Soheil Hassas Yeganeh, Eric Dumazet, Eric Dumazet
In-Reply-To: <20180517214729.186094-1-edumazet@google.com>
This counter tracks number of ACK packets that the host has not sent,
thanks to ACK compression.
Sample output :
$ nstat -n;sleep 1;nstat|egrep "IpInReceives|IpOutRequests|TcpInSegs|TcpOutSegs|TcpExtTCPAckCompressed"
IpInReceives 123250 0.0
IpOutRequests 3684 0.0
TcpInSegs 123251 0.0
TcpOutSegs 3684 0.0
TcpExtTCPAckCompressed 119252 0.0
Signed-off-by: Eric Dumazet <edumazet@google.com>
Acked-by: Neal Cardwell <ncardwell@google.com>
---
include/uapi/linux/snmp.h | 1 +
net/ipv4/proc.c | 1 +
net/ipv4/tcp_output.c | 2 ++
3 files changed, 4 insertions(+)
diff --git a/include/uapi/linux/snmp.h b/include/uapi/linux/snmp.h
index d02e859301ff499dd72a1c0e1b56bed10a9397a6..750d89120335eb489f698191edb6c5110969fa8c 100644
--- a/include/uapi/linux/snmp.h
+++ b/include/uapi/linux/snmp.h
@@ -278,6 +278,7 @@ enum
LINUX_MIB_TCPMTUPSUCCESS, /* TCPMTUPSuccess */
LINUX_MIB_TCPDELIVERED, /* TCPDelivered */
LINUX_MIB_TCPDELIVEREDCE, /* TCPDeliveredCE */
+ LINUX_MIB_TCPACKCOMPRESSED, /* TCPAckCompressed */
__LINUX_MIB_MAX
};
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
index 261b71d0ccc5c17c6032bf67eb8f842006766e64..6c1ff89a60fa0a3485dcc71fafc799e798d5dc11 100644
--- a/net/ipv4/proc.c
+++ b/net/ipv4/proc.c
@@ -298,6 +298,7 @@ static const struct snmp_mib snmp4_net_list[] = {
SNMP_MIB_ITEM("TCPMTUPSuccess", LINUX_MIB_TCPMTUPSUCCESS),
SNMP_MIB_ITEM("TCPDelivered", LINUX_MIB_TCPDELIVERED),
SNMP_MIB_ITEM("TCPDeliveredCE", LINUX_MIB_TCPDELIVEREDCE),
+ SNMP_MIB_ITEM("TCPAckCompressed", LINUX_MIB_TCPACKCOMPRESSED),
SNMP_MIB_SENTINEL
};
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 7ee98aad82b758674ca7f3e90bd3fc165e8fcd45..437bb7ceba7fd388abac1c12f2920b02be77bad9 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -165,6 +165,8 @@ static inline void tcp_event_ack_sent(struct sock *sk, unsigned int pkts)
struct tcp_sock *tp = tcp_sk(sk);
if (unlikely(tp->compressed_ack)) {
+ NET_ADD_STATS(sock_net(sk), LINUX_MIB_TCPACKCOMPRESSED,
+ tp->compressed_ack);
tp->compressed_ack = 0;
if (hrtimer_try_to_cancel(&tp->compressed_ack_timer) == 1)
__sock_put(sk);
--
2.17.0.441.gb46fe60e1d-goog
^ permalink raw reply related
* [PATCH v3 net-next 3/6] tcp: add SACK compression
From: Eric Dumazet @ 2018-05-17 21:47 UTC (permalink / raw)
To: David S . Miller
Cc: netdev, Toke Høiland-Jørgensen, Neal Cardwell,
Yuchung Cheng, Soheil Hassas Yeganeh, Eric Dumazet, Eric Dumazet
In-Reply-To: <20180517214729.186094-1-edumazet@google.com>
When TCP receives an out-of-order packet, it immediately sends
a SACK packet, generating network load but also forcing the
receiver to send 1-MSS pathological packets, increasing its
RTX queue length/depth, and thus processing time.
Wifi networks suffer from this aggressive behavior, but generally
speaking, all these SACK packets add fuel to the fire when networks
are under congestion.
This patch adds a high resolution timer and tp->compressed_ack counter.
Instead of sending a SACK, we program this timer with a small delay,
based on RTT and capped to 1 ms :
delay = min ( 5 % of RTT, 1 ms)
If subsequent SACKs need to be sent while the timer has not yet
expired, we simply increment tp->compressed_ack.
When timer expires, a SACK is sent with the latest information.
Whenever an ACK is sent (if data is sent, or if in-order
data is received) timer is canceled.
Note that tcp_sack_new_ofo_skb() is able to force a SACK to be sent
if the sack blocks need to be shuffled, even if the timer has not
expired.
A new SNMP counter is added in the following patch.
Two other patches add sysctls to allow changing the 1,000,000 and 44
values that this commit hard-coded.
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
include/linux/tcp.h | 2 ++
include/net/tcp.h | 3 +++
net/ipv4/tcp.c | 1 +
net/ipv4/tcp_input.c | 35 +++++++++++++++++++++++++++++------
net/ipv4/tcp_output.c | 7 +++++++
net/ipv4/tcp_timer.c | 25 +++++++++++++++++++++++++
6 files changed, 67 insertions(+), 6 deletions(-)
diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index 807776928cb8610fe97121fbc3c600b08d5d2991..72705eaf4b84060a45bf04d5170f389a18010eac 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -218,6 +218,7 @@ struct tcp_sock {
reord:1; /* reordering detected */
} rack;
u16 advmss; /* Advertised MSS */
+ u8 compressed_ack;
u32 chrono_start; /* Start time in jiffies of a TCP chrono */
u32 chrono_stat[3]; /* Time in jiffies for chrono_stat stats */
u8 chrono_type:2, /* current chronograph type */
@@ -297,6 +298,7 @@ struct tcp_sock {
u32 sacked_out; /* SACK'd packets */
struct hrtimer pacing_timer;
+ struct hrtimer compressed_ack_timer;
/* from STCP, retrans queue hinting */
struct sk_buff* lost_skb_hint;
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 511bd0fde1dc1dd842598d083905b0425bcb05f8..952d842a604a3ed79e1bf87a712db20a461c35a9 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -561,6 +561,9 @@ static inline void tcp_clear_xmit_timers(struct sock *sk)
if (hrtimer_try_to_cancel(&tcp_sk(sk)->pacing_timer) == 1)
__sock_put(sk);
+ if (hrtimer_try_to_cancel(&tcp_sk(sk)->compressed_ack_timer) == 1)
+ __sock_put(sk);
+
inet_csk_clear_xmit_timers(sk);
}
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 62b776f9003798eaf06992a4eb0914d17646aa61..0a2ea0bbf867271db05aedd7d48b193677664321 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -2595,6 +2595,7 @@ int tcp_disconnect(struct sock *sk, int flags)
dst_release(sk->sk_rx_dst);
sk->sk_rx_dst = NULL;
tcp_saved_syn_free(tp);
+ tp->compressed_ack = 0;
/* Clean up fastopen related fields */
tcp_free_fastopen_req(tp);
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index f5622b250665178e44460fa2cd4a11af23dfb23d..cc2ac5346b92b968593f919192d543384865bcb8 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -4249,6 +4249,8 @@ static void tcp_sack_new_ofo_skb(struct sock *sk, u32 seq, u32 end_seq)
* If the sack array is full, forget about the last one.
*/
if (this_sack >= TCP_NUM_SACKS) {
+ if (tp->compressed_ack)
+ tcp_send_ack(sk);
this_sack--;
tp->rx_opt.num_sacks--;
sp--;
@@ -5081,6 +5083,7 @@ static inline void tcp_data_snd_check(struct sock *sk)
static void __tcp_ack_snd_check(struct sock *sk, int ofo_possible)
{
struct tcp_sock *tp = tcp_sk(sk);
+ unsigned long rtt, delay;
/* More than one full frame received... */
if (((tp->rcv_nxt - tp->rcv_wup) > inet_csk(sk)->icsk_ack.rcv_mss &&
@@ -5092,15 +5095,35 @@ static void __tcp_ack_snd_check(struct sock *sk, int ofo_possible)
(tp->rcv_nxt - tp->copied_seq < sk->sk_rcvlowat ||
__tcp_select_window(sk) >= tp->rcv_wnd)) ||
/* We ACK each frame or... */
- tcp_in_quickack_mode(sk) ||
- /* We have out of order data. */
- (ofo_possible && !RB_EMPTY_ROOT(&tp->out_of_order_queue))) {
- /* Then ack it now */
+ tcp_in_quickack_mode(sk)) {
+send_now:
tcp_send_ack(sk);
- } else {
- /* Else, send delayed ack. */
+ return;
+ }
+
+ if (!ofo_possible || RB_EMPTY_ROOT(&tp->out_of_order_queue)) {
tcp_send_delayed_ack(sk);
+ return;
}
+
+ if (!tcp_is_sack(tp) || tp->compressed_ack >= 44)
+ goto send_now;
+ tp->compressed_ack++;
+
+ if (hrtimer_is_queued(&tp->compressed_ack_timer))
+ return;
+
+ /* compress ack timer : 5 % of rtt, but no more than 1 ms */
+
+ rtt = tp->rcv_rtt_est.rtt_us;
+ if (tp->srtt_us && tp->srtt_us < rtt)
+ rtt = tp->srtt_us;
+
+ delay = min_t(unsigned long, NSEC_PER_MSEC,
+ rtt * (NSEC_PER_USEC >> 3)/20);
+ sock_hold(sk);
+ hrtimer_start(&tp->compressed_ack_timer, ns_to_ktime(delay),
+ HRTIMER_MODE_REL_PINNED_SOFT);
}
static inline void tcp_ack_snd_check(struct sock *sk)
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 0d8f950a9006598c70dbf51e281a3fe32dfaa234..7ee98aad82b758674ca7f3e90bd3fc165e8fcd45 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -162,6 +162,13 @@ static void tcp_event_data_sent(struct tcp_sock *tp,
/* Account for an ACK we sent. */
static inline void tcp_event_ack_sent(struct sock *sk, unsigned int pkts)
{
+ struct tcp_sock *tp = tcp_sk(sk);
+
+ if (unlikely(tp->compressed_ack)) {
+ tp->compressed_ack = 0;
+ if (hrtimer_try_to_cancel(&tp->compressed_ack_timer) == 1)
+ __sock_put(sk);
+ }
tcp_dec_quickack_mode(sk, pkts);
inet_csk_clear_xmit_timer(sk, ICSK_TIME_DACK);
}
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
index 92bdf64fffae3a5be291ca419eb21276b4c8cbae..3b3611729928f77934e0298bb248e55c7a7c5def 100644
--- a/net/ipv4/tcp_timer.c
+++ b/net/ipv4/tcp_timer.c
@@ -708,6 +708,27 @@ static void tcp_keepalive_timer (struct timer_list *t)
sock_put(sk);
}
+static enum hrtimer_restart tcp_compressed_ack_kick(struct hrtimer *timer)
+{
+ struct tcp_sock *tp = container_of(timer, struct tcp_sock, compressed_ack_timer);
+ struct sock *sk = (struct sock *)tp;
+
+ bh_lock_sock(sk);
+ if (!sock_owned_by_user(sk)) {
+ if (tp->compressed_ack)
+ tcp_send_ack(sk);
+ } else {
+ if (!test_and_set_bit(TCP_DELACK_TIMER_DEFERRED,
+ &sk->sk_tsq_flags))
+ sock_hold(sk);
+ }
+ bh_unlock_sock(sk);
+
+ sock_put(sk);
+
+ return HRTIMER_NORESTART;
+}
+
void tcp_init_xmit_timers(struct sock *sk)
{
inet_csk_init_xmit_timers(sk, &tcp_write_timer, &tcp_delack_timer,
@@ -715,4 +736,8 @@ void tcp_init_xmit_timers(struct sock *sk)
hrtimer_init(&tcp_sk(sk)->pacing_timer, CLOCK_MONOTONIC,
HRTIMER_MODE_ABS_PINNED_SOFT);
tcp_sk(sk)->pacing_timer.function = tcp_pace_kick;
+
+ hrtimer_init(&tcp_sk(sk)->compressed_ack_timer, CLOCK_MONOTONIC,
+ HRTIMER_MODE_REL_PINNED_SOFT);
+ tcp_sk(sk)->compressed_ack_timer.function = tcp_compressed_ack_kick;
}
--
2.17.0.441.gb46fe60e1d-goog
^ permalink raw reply related
* [PATCH v3 net-next 2/6] tcp: do not force quickack when receiving out-of-order packets
From: Eric Dumazet @ 2018-05-17 21:47 UTC (permalink / raw)
To: David S . Miller
Cc: netdev, Toke Høiland-Jørgensen, Neal Cardwell,
Yuchung Cheng, Soheil Hassas Yeganeh, Eric Dumazet, Eric Dumazet
In-Reply-To: <20180517214729.186094-1-edumazet@google.com>
As explained in commit 9f9843a751d0 ("tcp: properly handle stretch
acks in slow start"), TCP stacks have to consider how many packets
are acknowledged in one single ACK, because of GRO, but also
because of ACK compression or losses.
We plan to add SACK compression in the following patch, we
must therefore not call tcp_enter_quickack_mode()
Signed-off-by: Eric Dumazet <edumazet@google.com>
Acked-by: Neal Cardwell <ncardwell@google.com>
Acked-by: Soheil Hassas Yeganeh <soheil@google.com>
---
net/ipv4/tcp_input.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 0bf032839548f8dccb7f24a6fb5a7d47ea29208b..f5622b250665178e44460fa2cd4a11af23dfb23d 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -4715,8 +4715,6 @@ static void tcp_data_queue(struct sock *sk, struct sk_buff *skb)
if (!before(TCP_SKB_CB(skb)->seq, tp->rcv_nxt + tcp_receive_window(tp)))
goto out_of_window;
- tcp_enter_quickack_mode(sk);
-
if (before(TCP_SKB_CB(skb)->seq, tp->rcv_nxt)) {
/* Partial packet, seq < rcv_next < end_seq */
SOCK_DEBUG(sk, "partial packet: rcv_next %X seq %X - %X\n",
--
2.17.0.441.gb46fe60e1d-goog
^ permalink raw reply related
* [PATCH v3 net-next 1/6] tcp: use __sock_put() instead of sock_put() in tcp_clear_xmit_timers()
From: Eric Dumazet @ 2018-05-17 21:47 UTC (permalink / raw)
To: David S . Miller
Cc: netdev, Toke Høiland-Jørgensen, Neal Cardwell,
Yuchung Cheng, Soheil Hassas Yeganeh, Eric Dumazet, Eric Dumazet
In-Reply-To: <20180517214729.186094-1-edumazet@google.com>
Socket can not disappear under us.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Acked-by: Neal Cardwell <ncardwell@google.com>
---
include/net/tcp.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 6deb540297ccaa1f05ce633efe313d1ca2c15dd9..511bd0fde1dc1dd842598d083905b0425bcb05f8 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -559,7 +559,7 @@ void tcp_init_xmit_timers(struct sock *);
static inline void tcp_clear_xmit_timers(struct sock *sk)
{
if (hrtimer_try_to_cancel(&tcp_sk(sk)->pacing_timer) == 1)
- sock_put(sk);
+ __sock_put(sk);
inet_csk_clear_xmit_timers(sk);
}
--
2.17.0.441.gb46fe60e1d-goog
^ permalink raw reply related
* [PATCH v3 net-next 0/6] tcp: implement SACK compression
From: Eric Dumazet @ 2018-05-17 21:47 UTC (permalink / raw)
To: David S . Miller
Cc: netdev, Toke Høiland-Jørgensen, Neal Cardwell,
Yuchung Cheng, Soheil Hassas Yeganeh, Eric Dumazet, Eric Dumazet
When TCP receives an out-of-order packet, it immediately sends
a SACK packet, generating network load but also forcing the
receiver to send 1-MSS pathological packets, increasing its
RTX queue length/depth, and thus processing time.
Wifi networks suffer from this aggressive behavior, but generally
speaking, all these SACK packets add fuel to the fire when networks
are under congestion.
This patch series adds SACK compression, but the infrastructure
could be leveraged to also compress ACK in the future.
v2: Addressed Neal feedback.
Added two sysctls to allow fine tuning, or even disabling the feature.
v3: take rtt = min(srtt, rcv_rtt) as Yuchung suggested, because rcv_rtt
can be over estimated for RPC (or sender limited)
Eric Dumazet (6):
tcp: use __sock_put() instead of sock_put() in tcp_clear_xmit_timers()
tcp: do not force quickack when receiving out-of-order packets
tcp: add SACK compression
tcp: add TCPAckCompressed SNMP counter
tcp: add tcp_comp_sack_delay_ns sysctl
tcp: add tcp_comp_sack_nr sysctl
Documentation/networking/ip-sysctl.txt | 13 +++++++++
include/linux/tcp.h | 2 ++
include/net/netns/ipv4.h | 2 ++
include/net/tcp.h | 5 +++-
include/uapi/linux/snmp.h | 1 +
net/ipv4/proc.c | 1 +
net/ipv4/sysctl_net_ipv4.c | 17 ++++++++++++
net/ipv4/tcp.c | 1 +
net/ipv4/tcp_input.c | 38 ++++++++++++++++++++------
net/ipv4/tcp_ipv4.c | 2 ++
net/ipv4/tcp_output.c | 9 ++++++
net/ipv4/tcp_timer.c | 25 +++++++++++++++++
12 files changed, 107 insertions(+), 9 deletions(-)
--
2.17.0.441.gb46fe60e1d-goog
^ permalink raw reply
* Re: [PATCH v3 1/2] media: rc: introduce BPF_PROG_RAWIR_EVENT
From: Sean Young @ 2018-05-17 21:45 UTC (permalink / raw)
To: Y Song
Cc: linux-media, linux-kernel, Alexei Starovoitov,
Mauro Carvalho Chehab, Daniel Borkmann, netdev, Matthias Reichl,
Devin Heitmueller
In-Reply-To: <CAH3MdRUqpenhK0hCzMfRyJU5Dz=k83Vxw0HFtyL1qa7aO5vDBA@mail.gmail.com>
Hi,
Again thanks for a thoughtful review. This will definitely will improve
the code.
On Thu, May 17, 2018 at 10:02:52AM -0700, Y Song wrote:
> On Wed, May 16, 2018 at 2:04 PM, Sean Young <sean@mess.org> wrote:
> > Add support for BPF_PROG_RAWIR_EVENT. This type of BPF program can call
> > rc_keydown() to reported decoded IR scancodes, or rc_repeat() to report
> > that the last key should be repeated.
> >
> > The bpf program can be attached to using the bpf(BPF_PROG_ATTACH) syscall;
> > the target_fd must be the /dev/lircN device.
> >
> > Signed-off-by: Sean Young <sean@mess.org>
> > ---
> > drivers/media/rc/Kconfig | 13 ++
> > drivers/media/rc/Makefile | 1 +
> > drivers/media/rc/bpf-rawir-event.c | 363 +++++++++++++++++++++++++++++
> > drivers/media/rc/lirc_dev.c | 24 ++
> > drivers/media/rc/rc-core-priv.h | 24 ++
> > drivers/media/rc/rc-ir-raw.c | 14 +-
> > include/linux/bpf_rcdev.h | 30 +++
> > include/linux/bpf_types.h | 3 +
> > include/uapi/linux/bpf.h | 55 ++++-
> > kernel/bpf/syscall.c | 7 +
> > 10 files changed, 531 insertions(+), 3 deletions(-)
> > create mode 100644 drivers/media/rc/bpf-rawir-event.c
> > create mode 100644 include/linux/bpf_rcdev.h
> >
> > diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig
> > index eb2c3b6eca7f..2172d65b0213 100644
> > --- a/drivers/media/rc/Kconfig
> > +++ b/drivers/media/rc/Kconfig
> > @@ -25,6 +25,19 @@ config LIRC
> > passes raw IR to and from userspace, which is needed for
> > IR transmitting (aka "blasting") and for the lirc daemon.
> >
> > +config BPF_RAWIR_EVENT
> > + bool "Support for eBPF programs attached to lirc devices"
> > + depends on BPF_SYSCALL
> > + depends on RC_CORE=y
> > + depends on LIRC
> > + help
> > + Allow attaching eBPF programs to a lirc device using the bpf(2)
> > + syscall command BPF_PROG_ATTACH. This is supported for raw IR
> > + receivers.
> > +
> > + These eBPF programs can be used to decode IR into scancodes, for
> > + IR protocols not supported by the kernel decoders.
> > +
> > menuconfig RC_DECODERS
> > bool "Remote controller decoders"
> > depends on RC_CORE
> > diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile
> > index 2e1c87066f6c..74907823bef8 100644
> > --- a/drivers/media/rc/Makefile
> > +++ b/drivers/media/rc/Makefile
> > @@ -5,6 +5,7 @@ obj-y += keymaps/
> > obj-$(CONFIG_RC_CORE) += rc-core.o
> > rc-core-y := rc-main.o rc-ir-raw.o
> > rc-core-$(CONFIG_LIRC) += lirc_dev.o
> > +rc-core-$(CONFIG_BPF_RAWIR_EVENT) += bpf-rawir-event.o
> > obj-$(CONFIG_IR_NEC_DECODER) += ir-nec-decoder.o
> > obj-$(CONFIG_IR_RC5_DECODER) += ir-rc5-decoder.o
> > obj-$(CONFIG_IR_RC6_DECODER) += ir-rc6-decoder.o
> > diff --git a/drivers/media/rc/bpf-rawir-event.c b/drivers/media/rc/bpf-rawir-event.c
> > new file mode 100644
> > index 000000000000..7cb48b8d87b5
> > --- /dev/null
> > +++ b/drivers/media/rc/bpf-rawir-event.c
> > @@ -0,0 +1,363 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +// bpf-rawir-event.c - handles bpf
> > +//
> > +// Copyright (C) 2018 Sean Young <sean@mess.org>
> > +
> > +#include <linux/bpf.h>
> > +#include <linux/filter.h>
> > +#include <linux/bpf_rcdev.h>
> > +#include "rc-core-priv.h"
> > +
> > +/*
> > + * BPF interface for raw IR
> > + */
> > +const struct bpf_prog_ops rawir_event_prog_ops = {
> > +};
> > +
> > +BPF_CALL_1(bpf_rc_repeat, struct bpf_rawir_event*, event)
> > +{
> > + struct ir_raw_event_ctrl *ctrl;
> > +
> > + ctrl = container_of(event, struct ir_raw_event_ctrl, bpf_rawir_event);
> > +
> > + rc_repeat(ctrl->dev);
> > +
> > + return 0;
> > +}
> > +
> > +static const struct bpf_func_proto rc_repeat_proto = {
> > + .func = bpf_rc_repeat,
> > + .gpl_only = true, /* rc_repeat is EXPORT_SYMBOL_GPL */
> > + .ret_type = RET_INTEGER,
> > + .arg1_type = ARG_PTR_TO_CTX,
> > +};
> > +
> > +BPF_CALL_4(bpf_rc_keydown, struct bpf_rawir_event*, event, u32, protocol,
> > + u32, scancode, u32, toggle)
> > +{
> > + struct ir_raw_event_ctrl *ctrl;
> > +
> > + ctrl = container_of(event, struct ir_raw_event_ctrl, bpf_rawir_event);
> > +
> > + rc_keydown(ctrl->dev, protocol, scancode, toggle != 0);
> > +
> > + return 0;
> > +}
> > +
> > +static const struct bpf_func_proto rc_keydown_proto = {
> > + .func = bpf_rc_keydown,
> > + .gpl_only = true, /* rc_keydown is EXPORT_SYMBOL_GPL */
> > + .ret_type = RET_INTEGER,
> > + .arg1_type = ARG_PTR_TO_CTX,
> > + .arg2_type = ARG_ANYTHING,
> > + .arg3_type = ARG_ANYTHING,
> > + .arg4_type = ARG_ANYTHING,
> > +};
> > +
> > +static const struct bpf_func_proto *
> > +rawir_event_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
> > +{
> > + switch (func_id) {
> > + case BPF_FUNC_rc_repeat:
> > + return &rc_repeat_proto;
> > + case BPF_FUNC_rc_keydown:
> > + return &rc_keydown_proto;
> > + case BPF_FUNC_map_lookup_elem:
> > + return &bpf_map_lookup_elem_proto;
> > + case BPF_FUNC_map_update_elem:
> > + return &bpf_map_update_elem_proto;
> > + case BPF_FUNC_map_delete_elem:
> > + return &bpf_map_delete_elem_proto;
> > + case BPF_FUNC_ktime_get_ns:
> > + return &bpf_ktime_get_ns_proto;
> > + case BPF_FUNC_tail_call:
> > + return &bpf_tail_call_proto;
> > + case BPF_FUNC_get_prandom_u32:
> > + return &bpf_get_prandom_u32_proto;
> > + case BPF_FUNC_trace_printk:
> > + if (capable(CAP_SYS_ADMIN))
> > + return bpf_get_trace_printk_proto();
> > + /* fall through */
> > + default:
> > + return NULL;
> > + }
> > +}
> > +
> > +static bool rawir_event_is_valid_access(int off, int size,
> > + enum bpf_access_type type,
> > + const struct bpf_prog *prog,
> > + struct bpf_insn_access_aux *info)
> > +{
> > + /* struct bpf_rawir_event has two u32 fields */
> > + if (type == BPF_WRITE)
> > + return false;
> > +
> > + if (size != sizeof(__u32))
> > + return false;
> > +
> > + if (!(off == offsetof(struct bpf_rawir_event, duration) ||
> > + off == offsetof(struct bpf_rawir_event, type)))
> > + return false;
> > +
> > + return true;
> > +}
> > +
> > +const struct bpf_verifier_ops rawir_event_verifier_ops = {
> > + .get_func_proto = rawir_event_func_proto,
> > + .is_valid_access = rawir_event_is_valid_access
> > +};
> > +
> > +#define BPF_MAX_PROGS 64
> > +
> > +static int rc_dev_bpf_attach(struct rc_dev *rcdev, struct bpf_prog *prog)
> > +{
> > + struct ir_raw_event_ctrl *raw;
> > + struct bpf_prog_list *pl;
> > + int ret, size;
> > +
> > + if (rcdev->driver_type != RC_DRIVER_IR_RAW)
> > + return -EINVAL;
> > +
> > + ret = mutex_lock_interruptible(&ir_raw_handler_lock);
> > + if (ret)
> > + return ret;
> > +
> > + raw = rcdev->raw;
> > + if (!raw) {
> > + ret = -ENODEV;
> > + goto out;
> > + }
> > +
> > + size = 0;
> > + list_for_each_entry(pl, &raw->progs, node) {
> > + if (pl->prog == prog) {
> > + ret = -EEXIST;
> > + goto out;
> > + }
> > +
> > + size++;
> > + }
> > +
> > + if (size >= BPF_MAX_PROGS) {
> > + ret = -E2BIG;
> > + goto out;
> > + }
> > +
> > + pl = kmalloc(sizeof(*pl), GFP_KERNEL);
> > + if (!pl) {
> > + ret = -ENOMEM;
> > + goto out;
> > + }
> > +
> > + pl->prog = prog;
> > + list_add(&pl->node, &raw->progs);
> > +out:
> > + mutex_unlock(&ir_raw_handler_lock);
> > + return ret;
> > +}
> > +
> > +static int rc_dev_bpf_detach(struct rc_dev *rcdev, struct bpf_prog *prog)
> > +{
> > + struct ir_raw_event_ctrl *raw;
> > + struct bpf_prog_list *pl, *tmp;
> > + int ret;
> > +
> > + if (rcdev->driver_type != RC_DRIVER_IR_RAW)
> > + return -EINVAL;
> > +
> > + ret = mutex_lock_interruptible(&ir_raw_handler_lock);
> > + if (ret)
> > + return ret;
> > +
> > + raw = rcdev->raw;
> > + if (!raw) {
> > + ret = -ENODEV;
> > + goto out;
> > + }
> > +
> > + ret = -ENOENT;
> > +
> > + list_for_each_entry_safe(pl, tmp, &raw->progs, node) {
> > + if (pl->prog == prog) {
> > + list_del(&pl->node);
> > + kfree(pl);
> > + bpf_prog_put(prog);
> > + ret = 0;
> > + goto out;
> > + }
> > + }
> > +out:
> > + mutex_unlock(&ir_raw_handler_lock);
> > + return ret;
> > +}
> > +
> > +void rc_dev_bpf_init(struct rc_dev *rcdev)
> > +{
> > + INIT_LIST_HEAD(&rcdev->raw->progs);
> > +}
> > +
> > +void rc_dev_bpf_run(struct rc_dev *rcdev, struct ir_raw_event ev)
> > +{
> > + struct ir_raw_event_ctrl *raw = rcdev->raw;
> > + struct bpf_prog_list *pl;
> > +
> > + if (list_empty(&raw->progs))
> > + return;
> > +
> > + if (unlikely(ev.carrier_report)) {
> > + raw->bpf_rawir_event.carrier = ev.carrier;
> > + raw->bpf_rawir_event.type = BPF_RAWIR_EVENT_CARRIER;
> > + } else {
> > + raw->bpf_rawir_event.duration = ev.duration;
> > +
> > + if (ev.pulse)
> > + raw->bpf_rawir_event.type = BPF_RAWIR_EVENT_PULSE;
> > + else if (ev.timeout)
> > + raw->bpf_rawir_event.type = BPF_RAWIR_EVENT_TIMEOUT;
> > + else if (ev.reset)
> > + raw->bpf_rawir_event.type = BPF_RAWIR_EVENT_RESET;
> > + else
> > + raw->bpf_rawir_event.type = BPF_RAWIR_EVENT_SPACE;
> > + }
> > +
> > + list_for_each_entry(pl, &raw->progs, node)
> > + BPF_PROG_RUN(pl->prog, &raw->bpf_rawir_event);
>
> Is the raw->progs protected by locks? It is possible that attaching/detaching
> could manipulate raw->progs at the same time? In perf/cgroup prog array
> case, the prog array run is protected by rcu and the dummy prog idea is
> to avoid the prog is skipped by reshuffling.
Yes, it is. The caller takes the appropriate lock. These functions could do
with some comments.
> Also, the original idea about using prog array is the least overhead since you
> want to BPF programs to execute as soon as possible.
Now, for our purposes the we're not bothered by a few milliseconds delay,
so I would pick whatever uses less cpu/memory overall. There is some overhead
in using rcu but the array is nice since it uses less memory than the
double-linked list, and less cache misses.
So I wanted bpf_prog_detach() to return -ENOENT if the prog was not in the list,
however bpf_prog_array_copy() and bpf_prog_array_delete_safe() do not return
anything useful for that.
Maybe I should look at adding a count-delta return to bpf_prog_array_copy(),
and a bool return to bpf_prog_array_delete_safe(). Or I could scan the array
an extra time to see if it is present. Any other ideas?
Also, BPF_F_OVERRIDE is not relevant for this but possibly BPF_F_ALLOW_MULTI
could invoke the same behaviour as for cgroups. What do you think?
> > +}
> > +
> > +void rc_dev_bpf_free(struct rc_dev *rcdev)
> > +{
> > + struct bpf_prog_list *pl, *tmp;
> > +
> > + list_for_each_entry_safe(pl, tmp, &rcdev->raw->progs, node) {
> > + list_del(&pl->node);
> > + bpf_prog_put(pl->prog);
> > + kfree(pl);
> > + }
> > +}
> > +
> > +int rc_dev_prog_attach(const union bpf_attr *attr)
> > +{
> > + struct bpf_prog *prog;
> > + struct rc_dev *rcdev;
> > + int ret;
> > +
> > + if (attr->attach_flags)
> > + return -EINVAL;
> > +
> > + prog = bpf_prog_get_type(attr->attach_bpf_fd,
> > + BPF_PROG_TYPE_RAWIR_EVENT);
> > + if (IS_ERR(prog))
> > + return PTR_ERR(prog);
> > +
> > + rcdev = rc_dev_get_from_fd(attr->target_fd);
> > + if (IS_ERR(rcdev)) {
> > + bpf_prog_put(prog);
> > + return PTR_ERR(rcdev);
> > + }
> > +
> > + ret = rc_dev_bpf_attach(rcdev, prog);
> > + if (ret)
> > + bpf_prog_put(prog);
> > +
> > + put_device(&rcdev->dev);
> > +
> > + return ret;
> > +}
> > +
> > +int rc_dev_prog_detach(const union bpf_attr *attr)
> > +{
> > + struct bpf_prog *prog;
> > + struct rc_dev *rcdev;
> > + int ret;
> > +
> > + if (attr->attach_flags)
> > + return -EINVAL;
> > +
> > + prog = bpf_prog_get_type(attr->attach_bpf_fd,
> > + BPF_PROG_TYPE_RAWIR_EVENT);
> > + if (IS_ERR(prog))
> > + return PTR_ERR(prog);
> > +
> > + rcdev = rc_dev_get_from_fd(attr->target_fd);
> > + if (IS_ERR(rcdev)) {
> > + bpf_prog_put(prog);
> > + return PTR_ERR(rcdev);
> > + }
> > +
> > + ret = rc_dev_bpf_detach(rcdev, prog);
> > +
> > + bpf_prog_put(prog);
> > + put_device(&rcdev->dev);
> > +
> > + return ret;
> > +}
> > +
> > +int rc_dev_prog_query(const union bpf_attr *attr, union bpf_attr __user *uattr)
> > +{
> > + __u32 __user *prog_ids = u64_to_user_ptr(attr->query.prog_ids);
> > + struct ir_raw_event_ctrl *raw;
> > + struct bpf_prog_list *pl;
> > + struct rc_dev *rcdev;
> > + u32 cnt, flags = 0, *ids, i;
> > + int ret;
> > +
> > + if (attr->query.query_flags)
> > + return -EINVAL;
> > +
> > + rcdev = rc_dev_get_from_fd(attr->query.target_fd);
> > + if (IS_ERR(rcdev))
> > + return PTR_ERR(rcdev);
> > +
> > + if (rcdev->driver_type != RC_DRIVER_IR_RAW) {
> > + ret = -EINVAL;
> > + goto out;
>
> mutex_lock_interruptible() has not been called. You can just return here.
Yep.
> > + }
> > +
> > + ret = mutex_lock_interruptible(&ir_raw_handler_lock);
> > + if (ret)
> > + goto out;
>
> Maybe you can rename label "out" to "unlock" since it
> is really an unlock and out?
Good point.
> > +
> > + raw = rcdev->raw;
> > + if (!raw) {
> > + ret = -ENODEV;
> > + goto out;
> > + }
> > +
> > + cnt = 0;
> > + list_for_each_entry(pl, &raw->progs, node)
> > + cnt++;
> > +
> > + if (copy_to_user(&uattr->query.prog_cnt, &cnt, sizeof(cnt))) {
> > + ret = -EFAULT;
> > + goto out;
> > + }
> > + if (copy_to_user(&uattr->query.attach_flags, &flags, sizeof(flags))) {
> > + ret = -EFAULT;
> > + goto out;
> > + }
> > +
> > + if (attr->query.prog_cnt != 0 && prog_ids && cnt) {
> > + if (attr->query.prog_cnt < cnt)
> > + cnt = attr->query.prog_cnt;
> > +
> > + ids = kmalloc_array(cnt, sizeof(u32), GFP_KERNEL);
> > + if (!ids) {
> > + ret = -ENOMEM;
> > + goto out;
> > + }
> > +
> > + i = 0;
> > + list_for_each_entry(pl, &raw->progs, node) {
> > + ids[i++] = pl->prog->aux->id;
> > + if (i == cnt)
> > + break;
> > + }
> > +
> > + ret = copy_to_user(prog_ids, ids, cnt * sizeof(u32));
>
> Do you want to give user a chance to know that the "cnt" is not big enough
> by return -ENOSPC if cnt is smaller than the number of progs in the array?
True.
> > + }
> > +out:
> > + mutex_unlock(&ir_raw_handler_lock);
> > + put_device(&rcdev->dev);
> > +
> > + return ret;
> > +}
> > diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c
> > index 24e9fbb80e81..193540ded626 100644
> > --- a/drivers/media/rc/lirc_dev.c
> > +++ b/drivers/media/rc/lirc_dev.c
> > @@ -20,6 +20,7 @@
> > #include <linux/module.h>
> > #include <linux/mutex.h>
> > #include <linux/device.h>
> > +#include <linux/file.h>
> > #include <linux/idr.h>
> > #include <linux/poll.h>
> > #include <linux/sched.h>
> > @@ -816,4 +817,27 @@ void __exit lirc_dev_exit(void)
> > unregister_chrdev_region(lirc_base_dev, RC_DEV_MAX);
> > }
> >
> > +struct rc_dev *rc_dev_get_from_fd(int fd)
> > +{
> > + struct fd f = fdget(fd);
> > + struct lirc_fh *fh;
> > + struct rc_dev *dev;
> > +
> > + if (!f.file)
> > + return ERR_PTR(-EBADF);
> > +
> > + if (f.file->f_op != &lirc_fops) {
> > + fdput(f);
> > + return ERR_PTR(-EINVAL);
> > + }
> > +
> > + fh = f.file->private_data;
> > + dev = fh->rc;
> > +
> > + get_device(&dev->dev);
> > + fdput(f);
> > +
> > + return dev;
> > +}
> > +
> > MODULE_ALIAS("lirc_dev");
> > diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h
> > index e0e6a17460f6..148db73cfa0c 100644
> > --- a/drivers/media/rc/rc-core-priv.h
> > +++ b/drivers/media/rc/rc-core-priv.h
> > @@ -13,6 +13,7 @@
> > #define MAX_IR_EVENT_SIZE 512
> >
> > #include <linux/slab.h>
> > +#include <uapi/linux/bpf.h>
> > #include <media/rc-core.h>
> >
> > /**
> > @@ -57,6 +58,11 @@ struct ir_raw_event_ctrl {
> > /* raw decoder state follows */
> > struct ir_raw_event prev_ev;
> > struct ir_raw_event this_ev;
> > +
> > +#ifdef CONFIG_BPF_RAWIR_EVENT
> > + struct bpf_rawir_event bpf_rawir_event;
> > + struct list_head progs;
> > +#endif
> > struct nec_dec {
> > int state;
> > unsigned count;
> > @@ -126,6 +132,9 @@ struct ir_raw_event_ctrl {
> > } imon;
> > };
> >
> > +/* Mutex for locking raw IR processing and handler change */
> > +extern struct mutex ir_raw_handler_lock;
> > +
> > /* macros for IR decoders */
> > static inline bool geq_margin(unsigned d1, unsigned d2, unsigned margin)
> > {
> > @@ -288,6 +297,7 @@ void ir_lirc_raw_event(struct rc_dev *dev, struct ir_raw_event ev);
> > void ir_lirc_scancode_event(struct rc_dev *dev, struct lirc_scancode *lsc);
> > int ir_lirc_register(struct rc_dev *dev);
> > void ir_lirc_unregister(struct rc_dev *dev);
> > +struct rc_dev *rc_dev_get_from_fd(int fd);
> > #else
> > static inline int lirc_dev_init(void) { return 0; }
> > static inline void lirc_dev_exit(void) {}
> > @@ -299,4 +309,18 @@ static inline int ir_lirc_register(struct rc_dev *dev) { return 0; }
> > static inline void ir_lirc_unregister(struct rc_dev *dev) { }
> > #endif
> >
> > +/*
> > + * bpf interface
> > + */
> > +#ifdef CONFIG_BPF_RAWIR_EVENT
> > +void rc_dev_bpf_init(struct rc_dev *dev);
> > +void rc_dev_bpf_free(struct rc_dev *dev);
> > +void rc_dev_bpf_run(struct rc_dev *dev, struct ir_raw_event ev);
> > +#else
> > +static inline void rc_dev_bpf_init(struct rc_dev *dev) { }
> > +static inline void rc_dev_bpf_free(struct rc_dev *dev) { }
> > +static inline void rc_dev_bpf_run(struct rc_dev *dev, struct ir_raw_event ev)
> > +{ }
> > +#endif
> > +
> > #endif /* _RC_CORE_PRIV */
> > diff --git a/drivers/media/rc/rc-ir-raw.c b/drivers/media/rc/rc-ir-raw.c
> > index 374f83105a23..e68cdd4fbf5d 100644
> > --- a/drivers/media/rc/rc-ir-raw.c
> > +++ b/drivers/media/rc/rc-ir-raw.c
> > @@ -14,7 +14,7 @@
> > static LIST_HEAD(ir_raw_client_list);
> >
> > /* Used to handle IR raw handler extensions */
> > -static DEFINE_MUTEX(ir_raw_handler_lock);
> > +DEFINE_MUTEX(ir_raw_handler_lock);
> > static LIST_HEAD(ir_raw_handler_list);
> > static atomic64_t available_protocols = ATOMIC64_INIT(0);
> >
> > @@ -32,6 +32,7 @@ static int ir_raw_event_thread(void *data)
> > handler->protocols || !handler->protocols)
> > handler->decode(raw->dev, ev);
> > ir_lirc_raw_event(raw->dev, ev);
> > + rc_dev_bpf_run(raw->dev, ev);
> > raw->prev_ev = ev;
> > }
> > mutex_unlock(&ir_raw_handler_lock);
> > @@ -572,6 +573,7 @@ int ir_raw_event_prepare(struct rc_dev *dev)
> > spin_lock_init(&dev->raw->edge_spinlock);
> > timer_setup(&dev->raw->edge_handle, ir_raw_edge_handle, 0);
> > INIT_KFIFO(dev->raw->kfifo);
> > + rc_dev_bpf_init(dev);
> >
> > return 0;
> > }
> > @@ -621,9 +623,17 @@ void ir_raw_event_unregister(struct rc_dev *dev)
> > list_for_each_entry(handler, &ir_raw_handler_list, list)
> > if (handler->raw_unregister)
> > handler->raw_unregister(dev);
> > - mutex_unlock(&ir_raw_handler_lock);
> > +
> > + rc_dev_bpf_free(dev);
> >
> > ir_raw_event_free(dev);
> > +
> > + /*
> > + * A user can be calling bpf(BPF_PROG_{QUERY|ATTACH|DETACH}), so
> > + * ensure that the raw member is null on unlock; this is how
> > + * "device gone" is checked.
> > + */
> > + mutex_unlock(&ir_raw_handler_lock);
> > }
> >
> > /*
> > diff --git a/include/linux/bpf_rcdev.h b/include/linux/bpf_rcdev.h
> > new file mode 100644
> > index 000000000000..17a30f30436a
> > --- /dev/null
> > +++ b/include/linux/bpf_rcdev.h
> > @@ -0,0 +1,30 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +#ifndef _BPF_RCDEV_H
> > +#define _BPF_RCDEV_H
> > +
> > +#include <linux/bpf.h>
> > +#include <uapi/linux/bpf.h>
> > +
> > +#ifdef CONFIG_BPF_RAWIR_EVENT
> > +int rc_dev_prog_attach(const union bpf_attr *attr);
> > +int rc_dev_prog_detach(const union bpf_attr *attr);
> > +int rc_dev_prog_query(const union bpf_attr *attr, union bpf_attr __user *uattr);
> > +#else
> > +static inline int rc_dev_prog_attach(const union bpf_attr *attr)
> > +{
> > + return -EINVAL;
> > +}
> > +
> > +static inline int rc_dev_prog_detach(const union bpf_attr *attr)
> > +{
> > + return -EINVAL;
> > +}
> > +
> > +static inline int rc_dev_prog_query(const union bpf_attr *attr,
> > + union bpf_attr __user *uattr)
> > +{
> > + return -EINVAL;
> > +}
> > +#endif
> > +
> > +#endif /* _BPF_RCDEV_H */
> > diff --git a/include/linux/bpf_types.h b/include/linux/bpf_types.h
> > index b67f8793de0d..e2b1b12474d4 100644
> > --- a/include/linux/bpf_types.h
> > +++ b/include/linux/bpf_types.h
> > @@ -25,6 +25,9 @@ BPF_PROG_TYPE(BPF_PROG_TYPE_RAW_TRACEPOINT, raw_tracepoint)
> > #ifdef CONFIG_CGROUP_BPF
> > BPF_PROG_TYPE(BPF_PROG_TYPE_CGROUP_DEVICE, cg_dev)
> > #endif
> > +#ifdef CONFIG_BPF_RAWIR_EVENT
> > +BPF_PROG_TYPE(BPF_PROG_TYPE_RAWIR_EVENT, rawir_event)
> > +#endif
> >
> > BPF_MAP_TYPE(BPF_MAP_TYPE_ARRAY, array_map_ops)
> > BPF_MAP_TYPE(BPF_MAP_TYPE_PERCPU_ARRAY, percpu_array_map_ops)
> > diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> > index d94d333a8225..243e141e8a5b 100644
> > --- a/include/uapi/linux/bpf.h
> > +++ b/include/uapi/linux/bpf.h
> > @@ -141,6 +141,7 @@ enum bpf_prog_type {
> > BPF_PROG_TYPE_SK_MSG,
> > BPF_PROG_TYPE_RAW_TRACEPOINT,
> > BPF_PROG_TYPE_CGROUP_SOCK_ADDR,
> > + BPF_PROG_TYPE_RAWIR_EVENT,
> > };
> >
> > enum bpf_attach_type {
> > @@ -158,6 +159,7 @@ enum bpf_attach_type {
> > BPF_CGROUP_INET6_CONNECT,
> > BPF_CGROUP_INET4_POST_BIND,
> > BPF_CGROUP_INET6_POST_BIND,
> > + BPF_RAWIR_EVENT,
> > __MAX_BPF_ATTACH_TYPE
> > };
> >
> > @@ -1902,6 +1904,35 @@ union bpf_attr {
> > * egress otherwise). This is the only flag supported for now.
> > * Return
> > * **SK_PASS** on success, or **SK_DROP** on error.
> > + *
> > + * int bpf_rc_keydown(void *ctx, u32 protocol, u32 scancode, u32 toggle)
> > + * Description
> > + * Report decoded scancode with toggle value. For use in
> > + * BPF_PROG_TYPE_RAWIR_EVENT, to report a successfully
> > + * decoded scancode. This is will generate a keydown event,
> > + * and a keyup event once the scancode is no longer repeated.
> > + *
> > + * *ctx* pointer to bpf_rawir_event, *protocol* is decoded
> > + * protocol (see RC_PROTO_* enum).
> > + *
> > + * Some protocols include a toggle bit, in case the button
> > + * was released and pressed again between consecutive scancodes,
> > + * copy this bit into *toggle* if it exists, else set to 0.
> > + *
> > + * Return
> > + * Always return 0 (for now)
> > + *
> > + * int bpf_rc_repeat(void *ctx)
> > + * Description
> > + * Repeat the last decoded scancode; some IR protocols like
> > + * NEC have a special IR message for repeat last button,
> > + * in case user is holding a button down; the scancode is
> > + * not repeated.
> > + *
> > + * *ctx* pointer to bpf_rawir_event.
> > + *
> > + * Return
> > + * Always return 0 (for now)
> > */
> > #define __BPF_FUNC_MAPPER(FN) \
> > FN(unspec), \
> > @@ -1976,7 +2007,9 @@ union bpf_attr {
> > FN(fib_lookup), \
> > FN(sock_hash_update), \
> > FN(msg_redirect_hash), \
> > - FN(sk_redirect_hash),
> > + FN(sk_redirect_hash), \
> > + FN(rc_repeat), \
> > + FN(rc_keydown),
> >
> > /* integer value in 'imm' field of BPF_CALL instruction selects which helper
> > * function eBPF program intends to call
> > @@ -2043,6 +2076,26 @@ enum bpf_hdr_start_off {
> > BPF_HDR_START_NET,
> > };
> >
> > +/*
> > + * user accessible mirror of in-kernel ir_raw_event
> > + */
> > +#define BPF_RAWIR_EVENT_SPACE 0
> > +#define BPF_RAWIR_EVENT_PULSE 1
> > +#define BPF_RAWIR_EVENT_TIMEOUT 2
> > +#define BPF_RAWIR_EVENT_RESET 3
> > +#define BPF_RAWIR_EVENT_CARRIER 4
> > +#define BPF_RAWIR_EVENT_DUTY_CYCLE 5
> > +
> > +struct bpf_rawir_event {
> > + union {
> > + __u32 duration;
> > + __u32 carrier;
> > + __u32 duty_cycle;
> > + };
> > +
> > + __u32 type;
> > +};
> > +
> > /* user accessible mirror of in-kernel sk_buff.
> > * new fields can only be added to the end of this structure
> > */
> > diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
> > index e2aeb5e89f44..75c089f407c8 100644
> > --- a/kernel/bpf/syscall.c
> > +++ b/kernel/bpf/syscall.c
> > @@ -11,6 +11,7 @@
> > */
> > #include <linux/bpf.h>
> > #include <linux/bpf_trace.h>
> > +#include <linux/bpf_rcdev.h>
> > #include <linux/btf.h>
> > #include <linux/syscalls.h>
> > #include <linux/slab.h>
> > @@ -1567,6 +1568,8 @@ static int bpf_prog_attach(const union bpf_attr *attr)
> > case BPF_SK_SKB_STREAM_PARSER:
> > case BPF_SK_SKB_STREAM_VERDICT:
> > return sockmap_get_from_fd(attr, BPF_PROG_TYPE_SK_SKB, true);
> > + case BPF_RAWIR_EVENT:
> > + return rc_dev_prog_attach(attr);
> > default:
> > return -EINVAL;
> > }
> > @@ -1637,6 +1640,8 @@ static int bpf_prog_detach(const union bpf_attr *attr)
> > case BPF_SK_SKB_STREAM_PARSER:
> > case BPF_SK_SKB_STREAM_VERDICT:
> > return sockmap_get_from_fd(attr, BPF_PROG_TYPE_SK_SKB, false);
> > + case BPF_RAWIR_EVENT:
> > + return rc_dev_prog_detach(attr);
> > default:
> > return -EINVAL;
> > }
> > @@ -1684,6 +1689,8 @@ static int bpf_prog_query(const union bpf_attr *attr,
> > case BPF_CGROUP_SOCK_OPS:
> > case BPF_CGROUP_DEVICE:
> > break;
> > + case BPF_RAWIR_EVENT:
> > + return rc_dev_prog_query(attr, uattr);
> > default:
> > return -EINVAL;
> > }
> > --
> > 2.17.0
> >
^ permalink raw reply
* Re: [PATCH v3] mlx4_core: allocate ICM memory in page size chunks
From: Qing Huang @ 2018-05-17 21:45 UTC (permalink / raw)
To: Eric Dumazet, tariqt, davem, haakon.bugge, yanjun.zhu
Cc: netdev, linux-rdma, linux-kernel, gi-oh.kim
In-Reply-To: <e6c470f0-f2ae-5efd-09ed-0c9562a4a764@gmail.com>
On 5/17/2018 2:14 PM, Eric Dumazet wrote:
> On 05/17/2018 01:53 PM, Qing Huang wrote:
>> When a system is under memory presure (high usage with fragments),
>> the original 256KB ICM chunk allocations will likely trigger kernel
>> memory management to enter slow path doing memory compact/migration
>> ops in order to complete high order memory allocations.
>>
>> When that happens, user processes calling uverb APIs may get stuck
>> for more than 120s easily even though there are a lot of free pages
>> in smaller chunks available in the system.
>>
>> Syslog:
>> ...
>> Dec 10 09:04:51 slcc03db02 kernel: [397078.572732] INFO: task
>> oracle_205573_e:205573 blocked for more than 120 seconds.
>> ...
>>
> NACK on this patch.
>
> You have been asked repeatedly to use kvmalloc()
>
> This is not a minor suggestion.
>
> Take a look athttps://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=d8c13f2271ec5178c52fbde072ec7b562651ed9d
Would you please take a look at how table->icm is being used in the mlx4
driver? It's a meta data used for individual pointer variable referencing,
not as data frag or in/out buffer. It has no need for contiguous phy.
memory.
Thanks.
> And you'll understand some people care about this.
>
> Strongly.
>
> Thanks.
>
^ permalink raw reply
* Re: [RFC PATCH ghak32 V2 03/13] audit: log container info of syscalls
From: Richard Guy Briggs @ 2018-05-17 21:41 UTC (permalink / raw)
To: Steve Grubb
Cc: cgroups, containers, linux-api, Linux-Audit Mailing List,
linux-fsdevel, LKML, netdev, ebiederm, luto, jlayton, carlos,
dhowells, viro, simo, eparis, serge
In-Reply-To: <20180517170907.3d9f7c1a@ivy-bridge>
On 2018-05-17 17:09, Steve Grubb wrote:
> On Fri, 16 Mar 2018 05:00:30 -0400
> Richard Guy Briggs <rgb@redhat.com> wrote:
>
> > Create a new audit record AUDIT_CONTAINER_INFO to document the
> > container ID of a process if it is present.
>
> As mentioned in a previous email, I think AUDIT_CONTAINER is more
> suitable for the container record. One more comment below...
>
> > Called from audit_log_exit(), syscalls are covered.
> >
> > A sample raw event:
> > type=SYSCALL msg=audit(1519924845.499:257): arch=c000003e syscall=257
> > success=yes exit=3 a0=ffffff9c a1=56374e1cef30 a2=241 a3=1b6 items=2
> > ppid=606 pid=635 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0
> > sgid=0 fsgid=0 tty=pts0 ses=3 comm="bash" exe="/usr/bin/bash"
> > subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
> > key="tmpcontainerid" type=CWD msg=audit(1519924845.499:257):
> > cwd="/root" type=PATH msg=audit(1519924845.499:257): item=0
> > name="/tmp/" inode=13863 dev=00:27 mode=041777 ouid=0 ogid=0
> > rdev=00:00 obj=system_u:object_r:tmp_t:s0 nametype= PARENT
> > cap_fp=0000000000000000 cap_fi=0000000000000000 cap_fe=0 cap_fver=0
> > type=PATH msg=audit(1519924845.499:257): item=1
> > name="/tmp/tmpcontainerid" inode=17729 dev=00:27 mode=0100644 ouid=0
> > ogid=0 rdev=00:00 obj=unconfined_u:object_r:user_tmp_t:s0
> > nametype=CREATE cap_fp=0000000000000000 cap_fi=0000000000000000
> > cap_fe=0 cap_fver=0 type=PROCTITLE msg=audit(1519924845.499:257):
> > proctitle=62617368002D6300736C65657020313B206563686F2074657374203E202F746D702F746D70636F6E7461696E65726964
> > type=CONTAINER_INFO msg=audit(1519924845.499:257): op=task
> > contid=123458
> >
> > See: https://github.com/linux-audit/audit-kernel/issues/32
> > Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> > ---
> > include/linux/audit.h | 5 +++++
> > include/uapi/linux/audit.h | 1 +
> > kernel/audit.c | 20 ++++++++++++++++++++
> > kernel/auditsc.c | 2 ++
> > 4 files changed, 28 insertions(+)
> >
> > diff --git a/include/linux/audit.h b/include/linux/audit.h
> > index fe4ba3f..3acbe9d 100644
> > --- a/include/linux/audit.h
> > +++ b/include/linux/audit.h
> > @@ -154,6 +154,8 @@ extern void
> > audit_log_link_denied(const char *operation, extern int
> > audit_log_task_context(struct audit_buffer *ab); extern void
> > audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk);
> > +extern int audit_log_container_info(struct task_struct *tsk,
> > + struct audit_context *context);
> >
> > extern int audit_update_lsm_rules(void);
> >
> > @@ -205,6 +207,9 @@ static inline int audit_log_task_context(struct
> > audit_buffer *ab) static inline void audit_log_task_info(struct
> > audit_buffer *ab, struct task_struct *tsk)
> > { }
> > +static inline int audit_log_container_info(struct task_struct *tsk,
> > + struct audit_context
> > *context); +{ }
> > #define audit_enabled 0
> > #endif /* CONFIG_AUDIT */
> >
> > diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
> > index 921a71f..e83ccbd 100644
> > --- a/include/uapi/linux/audit.h
> > +++ b/include/uapi/linux/audit.h
> > @@ -115,6 +115,7 @@
> > #define AUDIT_REPLACE 1329 /* Replace auditd
> > if this packet unanswerd */ #define AUDIT_KERN_MODULE
> > 1330 /* Kernel Module events */ #define
> > AUDIT_FANOTIFY 1331 /* Fanotify access decision
> > */ +#define AUDIT_CONTAINER_INFO 1332 /* Container ID
> > information */ #define AUDIT_AVC 1400 /* SE
> > Linux avc denial or grant */ #define AUDIT_SELINUX_ERR
> > 1401 /* Internal SE Linux Errors */ diff --git
> > a/kernel/audit.c b/kernel/audit.c index 3f2f143..a12f21f 100644
> > --- a/kernel/audit.c
> > +++ b/kernel/audit.c
> > @@ -2049,6 +2049,26 @@ void audit_log_session_info(struct
> > audit_buffer *ab) audit_log_format(ab, " auid=%u ses=%u", auid,
> > sessionid); }
> >
> > +/*
> > + * audit_log_container_info - report container info
> > + * @tsk: task to be recorded
> > + * @context: task or local context for record
> > + */
> > +int audit_log_container_info(struct task_struct *tsk, struct
> > audit_context *context) +{
> > + struct audit_buffer *ab;
> > +
> > + if (!audit_containerid_set(tsk))
> > + return 0;
> > + /* Generate AUDIT_CONTAINER_INFO with container ID */
> > + ab = audit_log_start(context, GFP_KERNEL,
> > AUDIT_CONTAINER_INFO);
> > + if (!ab)
> > + return -ENOMEM;
> > + audit_log_format(ab, "contid=%llu",
> > audit_get_containerid(tsk));
> > + audit_log_end(ab);
> > + return 0;
> > +}
> > +
> > void audit_log_key(struct audit_buffer *ab, char *key)
> > {
> > audit_log_format(ab, " key=");
> > diff --git a/kernel/auditsc.c b/kernel/auditsc.c
> > index a6b0a52..65be110 100644
> > --- a/kernel/auditsc.c
> > +++ b/kernel/auditsc.c
> > @@ -1453,6 +1453,8 @@ static void audit_log_exit(struct audit_context
> > *context, struct task_struct *ts
> > audit_log_proctitle(tsk, context);
> >
> > + audit_log_container_info(tsk, context);
>
> Would there be any problem moving audit_log_container_info before
> audit_log_proctitle? There are some assumptions that proctitle is the
> last record in some situations.
I see no problem doing that.
> Thanks,
> -Steve
>
> > /* Send end of event record to help user space know we are
> > finished */ ab = audit_log_start(context, GFP_KERNEL, AUDIT_EOE);
> > if (ab)
- RGB
--
Richard Guy Briggs <rgb@redhat.com>
Sr. S/W Engineer, Kernel Security, Base Operating Systems
Remote, Ottawa, Red Hat Canada
IRC: rgb, SunRaycer
Voice: +1.647.777.2635, Internal: (81) 32635
^ permalink raw reply
* Re: [RFC PATCH bpf-next 12/12] i40e: implement Tx zero-copy
From: Jesper Dangaard Brouer @ 2018-05-17 21:31 UTC (permalink / raw)
To: Björn Töpel
Cc: magnus.karlsson, magnus.karlsson, alexander.h.duyck,
alexander.duyck, john.fastabend, ast, willemdebruijn.kernel,
daniel, mst, netdev, michael.lundkvist, jesse.brandeburg,
anjali.singhai, qi.z.zhang, intel-wired-lan, brouer
In-Reply-To: <20180515190615.23099-13-bjorn.topel@gmail.com>
On Tue, 15 May 2018 21:06:15 +0200 Björn Töpel <bjorn.topel@gmail.com> wrote:
> From: Magnus Karlsson <magnus.karlsson@intel.com>
>
> Here, the zero-copy ndo is implemented. As a shortcut, the existing
> XDP Tx rings are used for zero-copy. This means that and XDP program
> cannot redirect to an AF_XDP enabled XDP Tx ring.
This "shortcut" is not acceptable, and completely broken. The
XDP_REDIRECT queue_index is based on smp_processor_id(), and can easily
clash with the configured XSK queue_index. Provided a bit more code
context below...
On Tue, 15 May 2018 21:06:15 +0200
Björn Töpel <bjorn.topel@gmail.com> wrote:
int i40e_xdp_xmit(struct net_device *dev, struct xdp_frame *xdpf)
{
struct i40e_netdev_priv *np = netdev_priv(dev);
unsigned int queue_index = smp_processor_id();
struct i40e_vsi *vsi = np->vsi;
int err;
if (test_bit(__I40E_VSI_DOWN, vsi->state))
return -ENETDOWN;
> @@ -4025,6 +4158,9 @@ int i40e_xdp_xmit(struct net_device *dev, struct xdp_frame *xdpf)
> if (!i40e_enabled_xdp_vsi(vsi) || queue_index >= vsi->num_queue_pairs)
> return -ENXIO;
>
> + if (vsi->xdp_rings[queue_index]->xsk_umem)
> + return -ENXIO;
> +
Using the sane errno makes this impossible to debug (via the tracepoints).
> err = i40e_xmit_xdp_ring(xdpf, vsi->xdp_rings[queue_index]);
> if (err != I40E_XDP_TX)
> return -ENOSPC;
> @@ -4048,5 +4184,34 @@ void i40e_xdp_flush(struct net_device *dev)
> if (!i40e_enabled_xdp_vsi(vsi) || queue_index >= vsi->num_queue_pairs)
> return;
>
> + if (vsi->xdp_rings[queue_index]->xsk_umem)
> + return;
> +
> i40e_xdp_ring_update_tail(vsi->xdp_rings[queue_index]);
> }
--
Best regards,
Jesper Dangaard Brouer
MSc.CS, Principal Kernel Engineer at Red Hat
LinkedIn: http://www.linkedin.com/in/brouer
^ permalink raw reply
* Re: [PATCH bpf] bpf: fix truncated jump targets on heavy expansions
From: Martin KaFai Lau @ 2018-05-17 21:20 UTC (permalink / raw)
To: Daniel Borkmann; +Cc: alexei.starovoitov, netdev
In-Reply-To: <20180516234411.18122-1-daniel@iogearbox.net>
On Thu, May 17, 2018 at 01:44:11AM +0200, Daniel Borkmann wrote:
> Recently during testing, I ran into the following panic:
>
> [ 207.892422] Internal error: Accessing user space memory outside uaccess.h routines: 96000004 [#1] SMP
> [ 207.901637] Modules linked in: binfmt_misc [...]
> [ 207.966530] CPU: 45 PID: 2256 Comm: test_verifier Tainted: G W 4.17.0-rc3+ #7
> [ 207.974956] Hardware name: FOXCONN R2-1221R-A4/C2U4N_MB, BIOS G31FB18A 03/31/2017
> [ 207.982428] pstate: 60400005 (nZCv daif +PAN -UAO)
> [ 207.987214] pc : bpf_skb_load_helper_8_no_cache+0x34/0xc0
> [ 207.992603] lr : 0xffff000000bdb754
> [ 207.996080] sp : ffff000013703ca0
> [ 207.999384] x29: ffff000013703ca0 x28: 0000000000000001
> [ 208.004688] x27: 0000000000000001 x26: 0000000000000000
> [ 208.009992] x25: ffff000013703ce0 x24: ffff800fb4afcb00
> [ 208.015295] x23: ffff00007d2f5038 x22: ffff00007d2f5000
> [ 208.020599] x21: fffffffffeff2a6f x20: 000000000000000a
> [ 208.025903] x19: ffff000009578000 x18: 0000000000000a03
> [ 208.031206] x17: 0000000000000000 x16: 0000000000000000
> [ 208.036510] x15: 0000ffff9de83000 x14: 0000000000000000
> [ 208.041813] x13: 0000000000000000 x12: 0000000000000000
> [ 208.047116] x11: 0000000000000001 x10: ffff0000089e7f18
> [ 208.052419] x9 : fffffffffeff2a6f x8 : 0000000000000000
> [ 208.057723] x7 : 000000000000000a x6 : 00280c6160000000
> [ 208.063026] x5 : 0000000000000018 x4 : 0000000000007db6
> [ 208.068329] x3 : 000000000008647a x2 : 19868179b1484500
> [ 208.073632] x1 : 0000000000000000 x0 : ffff000009578c08
> [ 208.078938] Process test_verifier (pid: 2256, stack limit = 0x0000000049ca7974)
> [ 208.086235] Call trace:
> [ 208.088672] bpf_skb_load_helper_8_no_cache+0x34/0xc0
> [ 208.093713] 0xffff000000bdb754
> [ 208.096845] bpf_test_run+0x78/0xf8
> [ 208.100324] bpf_prog_test_run_skb+0x148/0x230
> [ 208.104758] sys_bpf+0x314/0x1198
> [ 208.108064] el0_svc_naked+0x30/0x34
> [ 208.111632] Code: 91302260 f9400001 f9001fa1 d2800001 (29500680)
> [ 208.117717] ---[ end trace 263cb8a59b5bf29f ]---
>
> The program itself which caused this had a long jump over the whole
> instruction sequence where all of the inner instructions required
> heavy expansions into multiple BPF instructions. Additionally, I also
> had BPF hardening enabled which requires once more rewrites of all
> constant values in order to blind them. Each time we rewrite insns,
> bpf_adj_branches() would need to potentially adjust branch targets
> which cross the patchlet boundary to accommodate for the additional
> delta. Eventually that lead to the case where the target offset could
> not fit into insn->off's upper 0x7fff limit anymore where then offset
> wraps around becoming negative (in s16 universe), or vice versa
> depending on the jump direction.
>
> Therefore it becomes necessary to detect and reject any such occasions
> in a generic way for native eBPF and cBPF to eBPF migrations. For
> the latter we can simply check bounds in the bpf_convert_filter()'s
> BPF_EMIT_JMP helper macro and bail out once we surpass limits. The
> bpf_patch_insn_single() for native eBPF (and cBPF to eBPF in case
> of subsequent hardening) is a bit more complex in that we need to
> detect such truncations before hitting the bpf_prog_realloc(). Thus
> the latter is split into an extra pass to probe problematic offsets
> on the original program in order to fail early. With that in place
> and carefully tested I no longer hit the panic and the rewrites are
> rejected properly. The above example panic I've seen on bpf-next,
> though the issue itself is generic in that a guard against this issue
> in bpf seems more appropriate in this case.
>
> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Martin KaFai Lau <kafai@fb.com>
^ permalink raw reply
* Re: [PATCH net 0/7] net: ip6_gre: Fixes in headroom handling
From: David Miller @ 2018-05-17 21:18 UTC (permalink / raw)
To: petrm; +Cc: netdev, kuznet, yoshfuji, u9012063, xeb
In-Reply-To: <wihfu2q2dvl.fsf@dev-r-vrt-156.mtr.labs.mlnx>
From: Petr Machata <petrm@mellanox.com>
Date: Fri, 18 May 2018 00:03:58 +0300
> David Miller <davem@davemloft.net> writes:
>
>> Series applied, thank you.
>
> Hi David, I forgot to add Fixes lines to the individual patches. I
> replied to the e-mails with those. Let me know if you want me to send a
> v2 with that and the Acked-by's.
When something is already in my tree, it can't be changed as it is committed
to the permanent record of my GIT tree and I cannot rebase since so many
people clone my tree.
Luckily for you, your Fixes: tags went out before I pushed, so I could
actually fix up the commit messages and add the tags.
>> Those reproducable test cases in the various commit messages are
>> pretty awesome. Could you please extract them and put them somewhere
>> appropriate under selftests?
>
> The ip6gretap one is covered by the mirror_gre test if you run it
> with veth devices instead of HW ports, but I can make it self-contained
> if you think that would be better.
>
> I'll add the erspan one.
Thank you.
^ permalink raw reply
* [bpf-next PATCH v2 2/2] bpf: add sk_msg prog sk access tests to test_verifier
From: John Fastabend @ 2018-05-17 21:17 UTC (permalink / raw)
To: ast, daniel; +Cc: netdev
In-Reply-To: <20180517211452.14426.98480.stgit@john-Precision-Tower-5810>
Add tests for BPF_PROG_TYPE_SK_MSG to test_verifier for read access
to new sk fields.
Signed-off-by: John Fastabend <john.fastabend@gmail.com>
Acked-by: Martin KaFai Lau <kafai@fb.com>
---
tools/include/uapi/linux/bpf.h | 8 ++
tools/testing/selftests/bpf/test_verifier.c | 115 +++++++++++++++++++++++++++
2 files changed, 123 insertions(+)
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index d94d333..97446bb 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -2176,6 +2176,14 @@ enum sk_action {
struct sk_msg_md {
void *data;
void *data_end;
+
+ __u32 family;
+ __u32 remote_ip4; /* Stored in network byte order */
+ __u32 local_ip4; /* Stored in network byte order */
+ __u32 remote_ip6[4]; /* Stored in network byte order */
+ __u32 local_ip6[4]; /* Stored in network byte order */
+ __u32 remote_port; /* Stored in network byte order */
+ __u32 local_port; /* stored in host byte order */
};
#define BPF_TAG_SIZE 8
diff --git a/tools/testing/selftests/bpf/test_verifier.c b/tools/testing/selftests/bpf/test_verifier.c
index a877af0..6ec4d9d 100644
--- a/tools/testing/selftests/bpf/test_verifier.c
+++ b/tools/testing/selftests/bpf/test_verifier.c
@@ -1686,6 +1686,121 @@ static void bpf_fill_rand_ld_dw(struct bpf_test *self)
.prog_type = BPF_PROG_TYPE_SK_SKB,
},
{
+ "valid access family in SK_MSG",
+ .insns = {
+ BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
+ offsetof(struct sk_msg_md, family)),
+ BPF_EXIT_INSN(),
+ },
+ .result = ACCEPT,
+ .prog_type = BPF_PROG_TYPE_SK_MSG,
+ },
+ {
+ "valid access remote_ip4 in SK_MSG",
+ .insns = {
+ BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
+ offsetof(struct sk_msg_md, remote_ip4)),
+ BPF_EXIT_INSN(),
+ },
+ .result = ACCEPT,
+ .prog_type = BPF_PROG_TYPE_SK_MSG,
+ },
+ {
+ "valid access local_ip4 in SK_MSG",
+ .insns = {
+ BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
+ offsetof(struct sk_msg_md, local_ip4)),
+ BPF_EXIT_INSN(),
+ },
+ .result = ACCEPT,
+ .prog_type = BPF_PROG_TYPE_SK_MSG,
+ },
+ {
+ "valid access remote_port in SK_MSG",
+ .insns = {
+ BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
+ offsetof(struct sk_msg_md, remote_port)),
+ BPF_EXIT_INSN(),
+ },
+ .result = ACCEPT,
+ .prog_type = BPF_PROG_TYPE_SK_MSG,
+ },
+ {
+ "valid access local_port in SK_MSG",
+ .insns = {
+ BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
+ offsetof(struct sk_msg_md, local_port)),
+ BPF_EXIT_INSN(),
+ },
+ .result = ACCEPT,
+ .prog_type = BPF_PROG_TYPE_SK_MSG,
+ },
+ {
+ "valid access remote_ip6 in SK_MSG",
+ .insns = {
+ BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
+ offsetof(struct sk_msg_md, remote_ip6[0])),
+ BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
+ offsetof(struct sk_msg_md, remote_ip6[1])),
+ BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
+ offsetof(struct sk_msg_md, remote_ip6[2])),
+ BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
+ offsetof(struct sk_msg_md, remote_ip6[3])),
+ BPF_EXIT_INSN(),
+ },
+ .result = ACCEPT,
+ .prog_type = BPF_PROG_TYPE_SK_SKB,
+ },
+ {
+ "valid access local_ip6 in SK_MSG",
+ .insns = {
+ BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
+ offsetof(struct sk_msg_md, local_ip6[0])),
+ BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
+ offsetof(struct sk_msg_md, local_ip6[1])),
+ BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
+ offsetof(struct sk_msg_md, local_ip6[2])),
+ BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
+ offsetof(struct sk_msg_md, local_ip6[3])),
+ BPF_EXIT_INSN(),
+ },
+ .result = ACCEPT,
+ .prog_type = BPF_PROG_TYPE_SK_SKB,
+ },
+ {
+ "invalid 64B read of family in SK_MSG",
+ .insns = {
+ BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1,
+ offsetof(struct sk_msg_md, family)),
+ BPF_EXIT_INSN(),
+ },
+ .errstr = "invalid bpf_context access",
+ .result = REJECT,
+ .prog_type = BPF_PROG_TYPE_SK_MSG,
+ },
+ {
+ "invalid read past end of SK_MSG",
+ .insns = {
+ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
+ offsetof(struct sk_msg_md, local_port) + 4),
+ BPF_EXIT_INSN(),
+ },
+ .errstr = "R0 !read_ok",
+ .result = REJECT,
+ .prog_type = BPF_PROG_TYPE_SK_MSG,
+ },
+ {
+ "invalid read offset in SK_MSG",
+ .insns = {
+ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
+ offsetof(struct sk_msg_md, family) + 1),
+ BPF_EXIT_INSN(),
+ },
+ .errstr = "invalid bpf_context access",
+ .result = REJECT,
+ .prog_type = BPF_PROG_TYPE_SK_MSG,
+ },
+ {
"direct packet read for SK_MSG",
.insns = {
BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1,
^ permalink raw reply related
* [bpf-next PATCH v2 1/2] bpf: allow sk_msg programs to read sock fields
From: John Fastabend @ 2018-05-17 21:16 UTC (permalink / raw)
To: ast, daniel; +Cc: netdev
In-Reply-To: <20180517211452.14426.98480.stgit@john-Precision-Tower-5810>
Currently sk_msg programs only have access to the raw data. However,
it is often useful when building policies to have the policies specific
to the socket endpoint. This allows using the socket tuple as input
into filters, etc.
This patch adds ctx access to the sock fields.
Signed-off-by: John Fastabend <john.fastabend@gmail.com>
Acked-by: Martin KaFai Lau <kafai@fb.com>
---
include/linux/filter.h | 1
include/uapi/linux/bpf.h | 8 +++
kernel/bpf/sockmap.c | 1
net/core/filter.c | 114 +++++++++++++++++++++++++++++++++++++++++++++-
4 files changed, 121 insertions(+), 3 deletions(-)
diff --git a/include/linux/filter.h b/include/linux/filter.h
index 9dbcb9d..d358d18 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -517,6 +517,7 @@ struct sk_msg_buff {
bool sg_copy[MAX_SKB_FRAGS];
__u32 flags;
struct sock *sk_redir;
+ struct sock *sk;
struct sk_buff *skb;
struct list_head list;
};
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index d94d333..97446bb 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -2176,6 +2176,14 @@ enum sk_action {
struct sk_msg_md {
void *data;
void *data_end;
+
+ __u32 family;
+ __u32 remote_ip4; /* Stored in network byte order */
+ __u32 local_ip4; /* Stored in network byte order */
+ __u32 remote_ip6[4]; /* Stored in network byte order */
+ __u32 local_ip6[4]; /* Stored in network byte order */
+ __u32 remote_port; /* Stored in network byte order */
+ __u32 local_port; /* stored in host byte order */
};
#define BPF_TAG_SIZE 8
diff --git a/kernel/bpf/sockmap.c b/kernel/bpf/sockmap.c
index c6de139..0ebf157 100644
--- a/kernel/bpf/sockmap.c
+++ b/kernel/bpf/sockmap.c
@@ -523,6 +523,7 @@ static unsigned int smap_do_tx_msg(struct sock *sk,
}
bpf_compute_data_pointers_sg(md);
+ md->sk = sk;
rc = (*prog->bpf_func)(md, prog->insnsi);
psock->apply_bytes = md->apply_bytes;
diff --git a/net/core/filter.c b/net/core/filter.c
index 6d0d156..aec5eba 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -5148,18 +5148,23 @@ static bool sk_msg_is_valid_access(int off, int size,
switch (off) {
case offsetof(struct sk_msg_md, data):
info->reg_type = PTR_TO_PACKET;
+ if (size != sizeof(__u64))
+ return false;
break;
case offsetof(struct sk_msg_md, data_end):
info->reg_type = PTR_TO_PACKET_END;
+ if (size != sizeof(__u64))
+ return false;
break;
+ default:
+ if (size != sizeof(__u32))
+ return false;
}
if (off < 0 || off >= sizeof(struct sk_msg_md))
return false;
if (off % size != 0)
return false;
- if (size != sizeof(__u64))
- return false;
return true;
}
@@ -5835,7 +5840,8 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type,
break;
case offsetof(struct bpf_sock_ops, local_ip4):
- BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_rcv_saddr) != 4);
+ BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common,
+ skc_rcv_saddr) != 4);
*insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
struct bpf_sock_ops_kern, sk),
@@ -6152,6 +6158,7 @@ static u32 sk_msg_convert_ctx_access(enum bpf_access_type type,
struct bpf_prog *prog, u32 *target_size)
{
struct bpf_insn *insn = insn_buf;
+ int off;
switch (si->off) {
case offsetof(struct sk_msg_md, data):
@@ -6164,6 +6171,107 @@ static u32 sk_msg_convert_ctx_access(enum bpf_access_type type,
si->dst_reg, si->src_reg,
offsetof(struct sk_msg_buff, data_end));
break;
+ case offsetof(struct sk_msg_md, family):
+ BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_family) != 2);
+
+ *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
+ struct sk_msg_buff, sk),
+ si->dst_reg, si->src_reg,
+ offsetof(struct sk_msg_buff, sk));
+ *insn++ = BPF_LDX_MEM(BPF_H, si->dst_reg, si->dst_reg,
+ offsetof(struct sock_common, skc_family));
+ break;
+
+ case offsetof(struct sk_msg_md, remote_ip4):
+ BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_daddr) != 4);
+
+ *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
+ struct sk_msg_buff, sk),
+ si->dst_reg, si->src_reg,
+ offsetof(struct sk_msg_buff, sk));
+ *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->dst_reg,
+ offsetof(struct sock_common, skc_daddr));
+ break;
+
+ case offsetof(struct sk_msg_md, local_ip4):
+ BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common,
+ skc_rcv_saddr) != 4);
+
+ *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
+ struct sk_msg_buff, sk),
+ si->dst_reg, si->src_reg,
+ offsetof(struct sk_msg_buff, sk));
+ *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->dst_reg,
+ offsetof(struct sock_common,
+ skc_rcv_saddr));
+ break;
+
+ case offsetof(struct sk_msg_md, remote_ip6[0]) ...
+ offsetof(struct sk_msg_md, remote_ip6[3]):
+#if IS_ENABLED(CONFIG_IPV6)
+ BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common,
+ skc_v6_daddr.s6_addr32[0]) != 4);
+
+ off = si->off;
+ off -= offsetof(struct sk_msg_md, remote_ip6[0]);
+ *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
+ struct sk_msg_buff, sk),
+ si->dst_reg, si->src_reg,
+ offsetof(struct sk_msg_buff, sk));
+ *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->dst_reg,
+ offsetof(struct sock_common,
+ skc_v6_daddr.s6_addr32[0]) +
+ off);
+#else
+ *insn++ = BPF_MOV32_IMM(si->dst_reg, 0);
+#endif
+ break;
+
+ case offsetof(struct sk_msg_md, local_ip6[0]) ...
+ offsetof(struct sk_msg_md, local_ip6[3]):
+#if IS_ENABLED(CONFIG_IPV6)
+ BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common,
+ skc_v6_rcv_saddr.s6_addr32[0]) != 4);
+
+ off = si->off;
+ off -= offsetof(struct sk_msg_md, local_ip6[0]);
+ *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
+ struct sk_msg_buff, sk),
+ si->dst_reg, si->src_reg,
+ offsetof(struct sk_msg_buff, sk));
+ *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->dst_reg,
+ offsetof(struct sock_common,
+ skc_v6_rcv_saddr.s6_addr32[0]) +
+ off);
+#else
+ *insn++ = BPF_MOV32_IMM(si->dst_reg, 0);
+#endif
+ break;
+
+ case offsetof(struct sk_msg_md, remote_port):
+ BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_dport) != 2);
+
+ *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
+ struct sk_msg_buff, sk),
+ si->dst_reg, si->src_reg,
+ offsetof(struct sk_msg_buff, sk));
+ *insn++ = BPF_LDX_MEM(BPF_H, si->dst_reg, si->dst_reg,
+ offsetof(struct sock_common, skc_dport));
+#ifndef __BIG_ENDIAN_BITFIELD
+ *insn++ = BPF_ALU32_IMM(BPF_LSH, si->dst_reg, 16);
+#endif
+ break;
+
+ case offsetof(struct sk_msg_md, local_port):
+ BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_num) != 2);
+
+ *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
+ struct sk_msg_buff, sk),
+ si->dst_reg, si->src_reg,
+ offsetof(struct sk_msg_buff, sk));
+ *insn++ = BPF_LDX_MEM(BPF_H, si->dst_reg, si->dst_reg,
+ offsetof(struct sock_common, skc_num));
+ break;
}
return insn - insn_buf;
^ permalink raw reply related
* [bpf-next PATCH v2 0/2] SK_MSG programs: read sock fields
From: John Fastabend @ 2018-05-17 21:16 UTC (permalink / raw)
To: ast, daniel; +Cc: netdev
In this series we add the ability for sk msg programs to read basic
sock information about the sock they are attached to. The second
patch adds the tests to the selftest test_verifier.
One obseration that I had from writing this seriess is lots of the
./net/core/filter.c code is almost duplicated across program types.
I thought about building a template/macro that we could use as a
single block of code to read sock data out for multiple programs,
but I wasn't convinced it was worth it yet. The result was using a
macro saved a couple lines of code per block but made the code
a bit harder to read IMO. We can probably revisit the idea later
if we get more duplication.
v2: add errstr field to negative test_verifier test cases to ensure
we get the expected err string back from the verifier.
---
John Fastabend (2):
bpf: allow sk_msg programs to read sock fields
bpf: add sk_msg prog sk access tests to test_verifier
include/linux/filter.h | 1
include/uapi/linux/bpf.h | 8 ++
kernel/bpf/sockmap.c | 1
net/core/filter.c | 114 ++++++++++++++++++++++++++-
tools/include/uapi/linux/bpf.h | 8 ++
tools/testing/selftests/bpf/test_verifier.c | 115 +++++++++++++++++++++++++++
6 files changed, 244 insertions(+), 3 deletions(-)
^ permalink raw reply
* Re: [PATCH v3] mlx4_core: allocate ICM memory in page size chunks
From: Eric Dumazet @ 2018-05-17 21:14 UTC (permalink / raw)
To: Qing Huang, tariqt, davem, haakon.bugge, yanjun.zhu
Cc: netdev, linux-rdma, linux-kernel, gi-oh.kim
In-Reply-To: <20180517205343.8401-1-qing.huang@oracle.com>
On 05/17/2018 01:53 PM, Qing Huang wrote:
> When a system is under memory presure (high usage with fragments),
> the original 256KB ICM chunk allocations will likely trigger kernel
> memory management to enter slow path doing memory compact/migration
> ops in order to complete high order memory allocations.
>
> When that happens, user processes calling uverb APIs may get stuck
> for more than 120s easily even though there are a lot of free pages
> in smaller chunks available in the system.
>
> Syslog:
> ...
> Dec 10 09:04:51 slcc03db02 kernel: [397078.572732] INFO: task
> oracle_205573_e:205573 blocked for more than 120 seconds.
> ...
>
NACK on this patch.
You have been asked repeatedly to use kvmalloc()
This is not a minor suggestion.
Take a look at https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=d8c13f2271ec5178c52fbde072ec7b562651ed9d
And you'll understand some people care about this.
Strongly.
Thanks.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox