* Re: [PATCH net] net: Fix the rollback test in dev_change_name()
From: Eric Dumazet @ 2009-11-16 11:08 UTC (permalink / raw)
To: David Miller; +Cc: jarkao2, netdev
In-Reply-To: <20091116.024936.14048478.davem@davemloft.net>
David Miller a écrit :
> From: Jarek Poplawski <jarkao2@gmail.com>
> Date: Mon, 16 Nov 2009 09:30:24 +0000
>
>> From: Eric Dumazet <eric.dumazet@gmail.com>
>>
>> net: Fix the rollback test in dev_change_name()
>>
>> In dev_change_name() an err variable is used for storing the original
>> call_netdevice_notifiers() errno (negative) and testing for a rollback
>> error later, but the test for non-zero is wrong, because the err might
>> have positive value as well - from dev_alloc_name(). It means the
>> rollback for a netdevice with a number > 0 will never happen. (The err
>> test is reordered btw. to make it more readable.)
>>
>> Signed-off-by: Jarek Poplawski <jarkao2@gmail.com>
>> Cc: Eric Dumazet <eric.dumazet@gmail.com>
>
> Ok.
>
> Eric please give your signoff and I'll put this where it needs
> to go.
>
I finaly understood why I got stuck on this one : I thought dev_alloc_name()
was returning 0 in case of success. The test was thus realy obscure for me.
So Jarek patch is pretty clear now I saw the light !
Thanks
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
^ permalink raw reply
* RE: [net-next] bnx2x: Handle Rx and Tx together in NAPI
From: Vladislav Zolotarov @ 2009-11-16 11:11 UTC (permalink / raw)
To: David Miller; +Cc: netdev@vger.kernel.org, Eilon Greenstein
In-Reply-To: <20091116.022012.81633492.davem@davemloft.net>
Ok. I'll fix it shortly and send u a new patch.
To say the truth, limiting the amount of Tx work done in one NAPI round is
about to harm single NAPI performance, however I thought it would be a nice thing to
do in global (all network devices/queues in the system) perspective. In Tx only
case: when all NAPIs do only Tx DPC work (UDP Tx only case) I need to ensure fairness
somehow, so I chose NAPI's budget. Could u advice on this?
There is another decision to make: what to do when Rx hasn't consumed the whole budget
and there is still Tx work to do. I think that in this case we need to return "budget", so that
we pushed to the end on the local NAPI's list, "consuming" some global Rx budget of the
local NAPI. Another option is to return the number of Rx
packets handled and make this NAPI be called at once. My decision is based on the fact
that there were scenarios when net_tx_action and net_rx_action were running on different
CPUs in UDP Tx test and were feeding each other. In this case if I implemented the later option
I would prevent other local NAPIs to run.
What is your opinion on this?
Thanks,
vlad
> -----Original Message-----
> From: David Miller [mailto:davem@davemloft.net]
> Sent: Monday, November 16, 2009 12:20 PM
> To: Vladislav Zolotarov
> Cc: netdev@vger.kernel.org; Eilon Greenstein
> Subject: Re: [net-next] bnx2x: Handle Rx and Tx together in NAPI
>
> From: "Vladislav Zolotarov" <vladz@broadcom.com>
> Date: Mon, 16 Nov 2009 12:01:09 +0200
>
> > - Limit Tx work done in one iteration by the same number
> of packets as
> > Rx in order to ensure both fair work load balancing
> relatively to other
> > devices scheduled for NAPI on the local CPU and sane Tx/Rx
> skb resource
> > management from single QP perspective.
>
> You should not do this.
>
> RX is several orders of magnitude more work than TX is. TX therefore
> should not be charged against the NAPI polling quota.
>
> Don't try to be different from other drivers unless you have detailed
> performance numbers from various situations (local TCP flows _and_
> routing) to justify it. :-)
>
> All NAPI drivers ignore TX work when considering NAPI polling quotas
> and you should too :-)
>
>
^ permalink raw reply
* Re: [PATCH 1/2] rps: core implementation
From: David Miller @ 2009-11-16 11:15 UTC (permalink / raw)
To: eric.dumazet; +Cc: therbert, netdev
In-Reply-To: <4AFA73DA.30308@gmail.com>
From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Wed, 11 Nov 2009 09:20:42 +0100
> I think I'll try to extend your patches with TX completion recycling too.
>
> Ie record in skb the cpu number of original sender, and queue skb to
> remote queue for destruction (sock_wfree() call and expensive
> scheduler calls...)
>
> (This probably needs driver cooperation, instead of calling consume_skb(),
> use a different function)
You can add a new argument to consume_skb() which indicates to remote
schedule a local free.
I would also suggest to record the TX cpu at dev_hard_start_xmit()
time, rather than somewhere higher up such as the socket layer.
Otherwise you'll mess up routing/netfilter cases, and also mishandle
task migration.
But a very excellent idea.
^ permalink raw reply
* Re: [PATCH 1/2] rps: core implementation
From: David Miller @ 2009-11-16 11:19 UTC (permalink / raw)
To: therbert; +Cc: netdev
In-Reply-To: <65634d660911102253o2b4f7a19kfed5849e5c88bfe1@mail.gmail.com>
From: Tom Herbert <therbert@google.com>
Date: Tue, 10 Nov 2009 22:53:17 -0800
> + /* Schedule NAPI for backlog device */
> + if (napi_schedule_prep(&queue->backlog)) {
> + if (cpu != smp_processor_id()) {
> + cpu_set(cpu,
> + get_cpu_var(rps_remote_softirq_cpus));
> + __raise_softirq_irqoff(NET_RPS_SOFTIRQ);
> + } else
> + __napi_schedule(&queue->backlog);
> + }
> + goto enqueue;
{,__}send_remote_softirq() doesn't work? :-)
^ permalink raw reply
* Re: [net-next] bnx2x: Handle Rx and Tx together in NAPI
From: David Miller @ 2009-11-16 11:24 UTC (permalink / raw)
To: vladz; +Cc: netdev, eilong
In-Reply-To: <8628FE4E7912BF47A96AE7DD7BAC0AADCB2D07B367@SJEXCHCCR02.corp.ad.broadcom.com>
From: "Vladislav Zolotarov" <vladz@broadcom.com>
Date: Mon, 16 Nov 2009 03:11:27 -0800
> To say the truth, limiting the amount of Tx work done in one NAPI
> round is about to harm single NAPI performance, however I thought it
> would be a nice thing to do in global (all network devices/queues in
> the system) perspective. In Tx only case: when all NAPIs do only Tx
> DPC work (UDP Tx only case) I need to ensure fairness somehow, so I
> chose NAPI's budget. Could u advice on this?
The extra loop you'll trigger in the code above ->poll() that loops
over NAPI context is more expensive than the TX freeing work.
The size of your TX ring will be enough all by itself to ensure
enough fairness.
If you try to use the NAPI quota, you're just adding overhead.
> There is another decision to make: what to do when Rx hasn't
> consumed the whole budget and there is still Tx work to do. I think
> that in this case we need to return "budget", so that we pushed to
> the end on the local NAPI's list, "consuming" some global Rx budget
> of the local NAPI. Another option is to return the number of Rx
> packets handled and make this NAPI be called at once. My decision is
> based on the fact that there were scenarios when net_tx_action and
> net_rx_action were running on different CPUs in UDP Tx test and were
> feeding each other. In this case if I implemented the later option I
> would prevent other local NAPIs to run.
I think you should always process all of the pending TX work first,
then do RX work and base your budget and rescheduling decisions
purely on RX work.
If you want to see it codified look at the tg3 driver or any other
driver that has been NAPI for a long ti me.
^ permalink raw reply
* Re: [PATCH net] net: Fix the rollback test in dev_change_name()
From: David Miller @ 2009-11-16 11:31 UTC (permalink / raw)
To: eric.dumazet; +Cc: jarkao2, netdev
In-Reply-To: <4B0132A6.7090305@gmail.com>
From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Mon, 16 Nov 2009 12:08:22 +0100
> David Miller a écrit :
>> From: Jarek Poplawski <jarkao2@gmail.com>
>> Date: Mon, 16 Nov 2009 09:30:24 +0000
>>
>>> From: Eric Dumazet <eric.dumazet@gmail.com>
>>>
>>> net: Fix the rollback test in dev_change_name()
>>>
>>> In dev_change_name() an err variable is used for storing the original
>>> call_netdevice_notifiers() errno (negative) and testing for a rollback
>>> error later, but the test for non-zero is wrong, because the err might
>>> have positive value as well - from dev_alloc_name(). It means the
>>> rollback for a netdevice with a number > 0 will never happen. (The err
>>> test is reordered btw. to make it more readable.)
>>>
>>> Signed-off-by: Jarek Poplawski <jarkao2@gmail.com>
>>> Cc: Eric Dumazet <eric.dumazet@gmail.com>
...
>> Eric please give your signoff and I'll put this where it needs
>> to go.
...
> Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Applied to net-2.6 and queued for -stable, thanks everyone!
^ permalink raw reply
* RE: [net-next] bnx2x: Handle Rx and Tx together in NAPI
From: Kumar Gopalpet-B05799 @ 2009-11-16 11:56 UTC (permalink / raw)
To: David Miller; +Cc: vladz, netdev, eilong
In-Reply-To: <20091116.030504.268003197.davem@davemloft.net>
>> I was talking about an independent napi routine for cleaning
>tx ring,
>> I do not want to mix the rx and tx clean ring processes.
>
>But you absolutely should do this, it will give optimal performance.
>
In the current implemnetation, the ->poll() function does the cleanup of
the tx and rx rings of the same device.
In case of forwarding scenarios (for eg, eth0 --> eth1) we should clean
the tx ring of eth1 so that the buffers can be reclaimed and they be
reused for eth0 RX and same is the case for opposite flow. With the
current implementation there will be a problem for the bidirectional
flow as a ->poll() function will try to cleanup the rx and tx ring of
the same device.
Hence I feel, if we separate out the tx and rx clean ring processes, it
would be more advantageous as the reclaim process can be more effective.
--
Thanks
Sandeep
^ permalink raw reply
* Re: [net-next] bnx2x: Handle Rx and Tx together in NAPI
From: David Miller @ 2009-11-16 12:24 UTC (permalink / raw)
To: B05799; +Cc: vladz, netdev, eilong
In-Reply-To: <9F4C7D19E8361D4C94921B95BE08B81B950C11@zin33exm22.fsl.freescale.net>
From: "Kumar Gopalpet-B05799" <B05799@freescale.com>
Date: Mon, 16 Nov 2009 17:26:33 +0530
> In the current implemnetation, the ->poll() function does the cleanup of
> the tx and rx rings of the same device.
> In case of forwarding scenarios (for eg, eth0 --> eth1) we should clean
> the tx ring of eth1 so that the buffers can be reclaimed and they be
> reused for eth0 RX and same is the case for opposite flow. With the
> current implementation there will be a problem for the bidirectional
> flow as a ->poll() function will try to cleanup the rx and tx ring of
> the same device.
>
> Hence I feel, if we separate out the tx and rx clean ring processes, it
> would be more advantageous as the reclaim process can be more effective.
Eric Dumazet is working on patches to make sure the TX frees
get scheduled on the same CPU as they were transmitted on.
Therefore, you shouldn't try to approximate this in your driver.
^ permalink raw reply
* Re: [PATCH 2/2] act_mirred: optimization
From: Changli Gao @ 2009-11-16 13:05 UTC (permalink / raw)
To: David Miller; +Cc: hadi, shemminger, netdev
In-Reply-To: <20091116.025859.78494103.davem@davemloft.net>
On Mon, Nov 16, 2009 at 6:58 PM, David Miller <davem@davemloft.net> wrote:
> From: David Miller <davem@davemloft.net>
> Date: Mon, 16 Nov 2009 02:48:39 -0800 (PST)
>
>> From: Changli Gao <xiaosuo@gmail.com>
>> Date: Mon, 16 Nov 2009 17:53:29 +0800
>>
>>> act_mirred: optimization.
>>>
>>> move checking if eaction is valid in tcf_mirred_init()
>>>
>>> Signed-off-by: Changli Gao <xiaosuo@gmail.com>
>>> Signed-off-by: Jamal Hadi Salim <hadi@cyberus.ca>
>>
>> Also applied, thank you.
>
> Nevermind, you're NOT TESTING the patches you are posting:
>
> net/sched/act_mirred.c: In function ‘tcf_mirred’:
> net/sched/act_mirred.c:168: error: label ‘out’ used but not defined
> net/sched/act_mirred.c:158: warning: unused variable ‘err’
> net/sched/act_mirred.c:158: warning: unused variable ‘retval’
> make[2]: *** [net/sched/act_mirred.o] Error 1
> make[1]: *** [net/sched] Error 2
> make[1]: *** Waiting for unfinished jobs....
>
> I'm thus reverting both changes.
>
> Don't submit changes which are untested, it wastes my time.
>
I am sorry about that. But I did test it before submitting these two,
and I am just wondering if they are applied without any error. Would
you post the file after being patched? I think it will be helpful to
finger out the real problem.
BTW: since my email client thunderbird was broken, I used google
webmail(with ViewSourceWith addon) to submit these two patches.
--
Regards,
Changli Gao(xiaosuo@gmail.com)
^ permalink raw reply
* Re: [PATCH] net/can: add driver for mscan family & mpc52xx_mscan
From: Wolfgang Grandegger @ 2009-11-16 13:08 UTC (permalink / raw)
To: Wolfram Sang
Cc: netdev, Grant Likely, socketcan-core, linuxppc-dev, David Miller
In-Reply-To: <20091116102414.GB30609@pengutronix.de>
Hi Wolfram,
Wolfram Sang wrote:
> Hi Wolfgang,
>
> On Mon, Nov 16, 2009 at 09:44:05AM +0100, Wolfgang Grandegger wrote:
>> Hi Wolfram,
>>
>> thanks for pushing this driver to mainline. I think you should also add
>> a CC to the Devicetree-discuss ML.
>
> thank you very much for your review! I agree with nearly all of your points and will
> send an update today. The only thing I have doubts about is removing those lines:
Thanks, quite a bit of work.
>> +MODULE_AUTHOR("Andrey Volkov <avolkov@varma-el.com>");
>> +MODULE_LICENSE("GPL v2");
>> +MODULE_DESCRIPTION("CAN port driver for a MSCAN based chips");
>
> I looked around in the kernel sources and found that they are often present in
> generic modules, even if they can't be used without a wrapper (examples are all
> files in drivers/i2c/algos or drivers/net/wireless/iwlwifi/iwl-core.c). As I'm
> also a bit anxious to fiddle with other people's authorship, I'd prefer to keep
> them.
They do not harm, fine for me.
> Finally, I'll also try to test suspend/resume, but I have to find out if it is
> supported on that board in general.
Maybe somebody else already uses suspend/resume on a MPC5200 board with
Socket-CAN and could provide some feedback.
Wolfgang.
^ permalink raw reply
* [RFC-PATCH] libiscsi dhcp handler
From: Rakesh Ranjan @ 2009-11-16 13:11 UTC (permalink / raw)
To: Mike Christie
Cc: open-iscsi-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org,
netdev-u79uwXL29TY76Z2rM5mHXA, LKML, David Miller,
James Bottomley, Karen Xie, Rakesh Ranjan
[-- Attachment #1: Type: text/plain, Size: 748 bytes --]
Hi mike,
Herein attached patches to support dhcp based provisioning for iSCSI
offload capable cards. I have made dhcp code as generic as possible,
please go through the code. Based on the feedback I will submit final
version of these patches.
Regards
Rakesh Ranjan
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "open-iscsi" group.
To post to this group, send email to open-iscsi-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
To unsubscribe from this group, send email to open-iscsi+unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
For more options, visit this group at http://groups.google.com/group/open-iscsi
-~----------~----~----~----~------~----~------~--~---
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Required-changes-for-libiscsi-to-support-dhcp-based.patch --]
[-- Type: text/x-patch, Size: 4284 bytes --]
>From 472d53f2ca0122b7fbfeabbcbde2c9a15499042b Mon Sep 17 00:00:00 2001
From: Rakesh Ranjan <rakesh-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org>
Date: Mon, 16 Nov 2009 18:11:56 +0530
Subject: [PATCH 1/2] Required changes for libiscsi to support dhcp based provisioning for offload capable cards.
These changes adds ISCSI_UEVENT_REQ_IPCONF message to invoke dhcp handler.
Signed-off-by: Rakesh Ranjan <rakesh-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org>
---
Makefile | 3 ++-
include/scsi/iscsi_if.h | 4 ++++
include/scsi/libiscsi.h | 20 ++++++++++++++++++++
include/scsi/scsi_transport_iscsi.h | 1 +
scsi_transport_iscsi.c | 25 +++++++++++++++++++++++++
5 files changed, 52 insertions(+), 1 deletions(-)
diff --git a/Makefile b/Makefile
index 26d33e5..3e5d461 100644
--- a/Makefile
+++ b/Makefile
@@ -2,10 +2,11 @@
# libiscsi modules
#
ifneq ($(KERNELRELEASE),)
- obj-m += libiscsi.o
obj-m += libiscsi_tcp.o
obj-m += scsi_transport_iscsi.o
obj-m += iscsi_tcp.o
+ obj-m += libiscsi.o
+ obj-m += libiscsi_ipconfig.o
EXTRA_CFLAGS += -I$(src)/include
else
diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
index d67dda2..135f229 100644
--- a/include/scsi/iscsi_if.h
+++ b/include/scsi/iscsi_if.h
@@ -59,6 +59,7 @@ enum iscsi_uevent_e {
ISCSI_UEVENT_TRANSPORT_EP_CONNECT_THROUGH_HOST = UEVENT_BASE + 19,
ISCSI_UEVENT_PATH_UPDATE = UEVENT_BASE + 20,
+ ISCSI_UEVENT_REQ_IPCONF = UEVENT_BASE + 21,
/* up events */
ISCSI_KEVENT_RECV_PDU = KEVENT_BASE + 1,
@@ -172,6 +173,9 @@ struct iscsi_uevent {
struct msg_set_path {
uint32_t host_no;
} set_path;
+ struct mag_req_ipconf {
+ uint32_t host_no;
+ } req_ipconf;
} u;
union {
/* messages k -> u */
diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
index a72edd4..a9af95e 100644
--- a/include/scsi/libiscsi.h
+++ b/include/scsi/libiscsi.h
@@ -330,6 +330,18 @@ struct iscsi_host {
char workq_name[20];
};
+/* libiscsi ipconfig */
+struct dhcp_info {
+ __be32 ltime;
+ __be32 serverid;
+ __be32 ipaddr;
+ __be32 netmask;
+ __be32 dnsaddr;
+ __be32 gipaddr;
+ __u8 *mac_addr;
+};
+
+
/*
* scsi host template
*/
@@ -427,6 +439,14 @@ extern void iscsi_pool_free(struct iscsi_pool *);
extern int iscsi_pool_init(struct iscsi_pool *, int, void ***, int);
/*
+ * libiscsi ipconfig helpers
+ */
+extern int libiscsi_do_ipconf(struct net_device *ndev,
+ struct dhcp_info *dinfo);
+extern int libiscsi_ipconfig_recv(struct net_device *ndev,
+ struct sk_buff *skb);
+
+/*
* inline functions to deal with padding.
*/
static inline unsigned int
diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
index 349c7f3..3e5fd96 100644
--- a/include/scsi/scsi_transport_iscsi.h
+++ b/include/scsi/scsi_transport_iscsi.h
@@ -134,6 +134,7 @@ struct iscsi_transport {
int (*tgt_dscvr) (struct Scsi_Host *shost, enum iscsi_tgt_dscvr type,
uint32_t enable, struct sockaddr *dst_addr);
int (*set_path) (struct Scsi_Host *shost, struct iscsi_path *params);
+ int (*req_ipconf) (struct Scsi_Host *shost);
};
/*
diff --git a/scsi_transport_iscsi.c b/scsi_transport_iscsi.c
index ad897df..4897a3f 100644
--- a/scsi_transport_iscsi.c
+++ b/scsi_transport_iscsi.c
@@ -1508,6 +1508,28 @@ iscsi_set_path(struct iscsi_transport *transport, struct iscsi_uevent *ev)
}
static int
+iscsi_req_ipconf(struct iscsi_transport *transport, struct iscsi_uevent *ev)
+{
+ struct Scsi_Host *shost;
+ int err;
+
+ if (!transport->req_ipconf)
+ return -ENOSYS;
+
+ shost = scsi_host_lookup(ev->u.req_ipconf.host_no);
+ if (!shost) {
+ printk(KERN_ERR "ipconf req could not find host no %u\n",
+ ev->u.req_ipconf.host_no);
+ return -ENODEV;
+ }
+
+ err = transport->req_ipconf(shost);
+
+ scsi_host_put(shost);
+ return err;
+}
+
+static int
iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
{
int err = 0;
@@ -1627,6 +1649,9 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
case ISCSI_UEVENT_PATH_UPDATE:
err = iscsi_set_path(transport, ev);
break;
+ case ISCSI_UEVENT_REQ_IPCONF:
+ err = iscsi_req_ipconf(transport, ev);
+ break;
default:
err = -ENOSYS;
break;
--
1.6.0.6
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: 0002-dhcp-handler-for-libiscsi-to-support-dhcp-provisioni.patch --]
[-- Type: text/x-patch, Size: 11364 bytes --]
>From 8df0fd4d0a972bd76bb71d7fdac274b273cec50d Mon Sep 17 00:00:00 2001
From: Rakesh Ranjan <rakesh-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org>
Date: Mon, 16 Nov 2009 18:32:57 +0530
Subject: [PATCH 2/2] dhcp handler for libiscsi to support dhcp provisioning for offload capable cards.
This module contains a compact dhcp handler to support dhcp based provisioning for
offload capable cards.
Signed-off-by: Rakesh Ranjan <rakesh-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org>
---
libiscsi_ipconfig.c | 466 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 466 insertions(+), 0 deletions(-)
create mode 100644 libiscsi_ipconfig.c
diff --git a/libiscsi_ipconfig.c b/libiscsi_ipconfig.c
new file mode 100644
index 0000000..4057aae
--- /dev/null
+++ b/libiscsi_ipconfig.c
@@ -0,0 +1,466 @@
+/* libiscsi_ipconfig.c: libiscsi dhcp client.
+ *
+ * Copyright (c) 2009 Chelsio Communications, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ *
+ * Written by: Rakesh Ranjan (rakesh-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org)
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/in.h>
+#include <linux/delay.h>
+#include <linux/if_arp.h>
+#include <net/ip.h>
+#include <scsi/iscsi_if.h>
+#include <scsi/libiscsi.h>
+
+#define DHCP_REQUEST 1
+#define DHCP_REPLY 2
+#define DHCP_HTYPE_ETHERNET 1
+#define DHCP_HLEN_ETHERNET 6
+#define DHCP_MSG_LEN 236
+
+#define DHCPC_SERVER_PORT 67
+#define DHCPC_CLIENT_PORT 68
+
+/* DHCP message types */
+#define DHCPDISCOVER 1
+#define DHCPOFFER 2
+#define DHCPREQUEST 3
+#define DHCPDECLINE 4
+#define DHCPACK 5
+#define DHCPNAK 6
+#define DHCPRELEASE 7
+#define DHCPINFORM 8
+
+/* DHCP options */
+#define DHCP_OPTION_SUBNET_MASK 1
+#define DHCP_OPTION_ROUTER 3
+#define DHCP_OPTION_DNS_SERVER 6
+#define DHCP_OPTION_MTU 26
+#define DHCP_OPTION_REQ_IPADDR 50
+#define DHCP_OPTION_LEASE_TIME 51
+#define DHCP_OPTION_MSG_TYPE 53
+#define DHCP_OPTION_SERVER_ID 54
+#define DHCP_OPTION_REQ_LIST 55
+#define DHCP_OPTION_VCID 60
+#define DHCP_OPTION_END 255
+
+enum {
+ STATE_INIT = 0,
+ STATE_SENDING,
+ STATE_OFFER_REC,
+ STATE_CONFIG_REC,
+};
+
+struct dhcp_pkt {
+ struct iphdr iph;
+ struct udphdr udph;
+ u8 op;
+ u8 htype;
+ u8 hlen;
+ u8 hops;
+ __be32 xid;
+ __be16 secs;
+ __be16 flags;
+ __be32 cipaddr;
+ __be32 yipaddr;
+ __be32 sipaddr;
+ __be32 ripaddr;
+ u8 chwaddr[16];
+ u8 sname[64];
+ u8 bfile[128];
+ u8 options[312];
+};
+
+
+static struct dhcp_client_state {
+ struct sk_buff *skb;
+ struct dhcp_pkt *pkt;
+ struct net_device *ndev;
+ struct list_head list;
+ struct dhcp_info dinfo;
+
+ volatile __u8 state;
+ __be32 xid;
+
+} client_state;
+
+static DEFINE_SPINLOCK(rcv_lock);
+
+static const char *RFC2132_VENDOR_CLASS_ID = "libiscsi client";
+
+static const u8 magic_cookie[4] = { 99, 130, 83, 99 };
+
+static inline u8 *add_msg_type(u8 *optptr, u8 type)
+{
+ *optptr++ = DHCP_OPTION_MSG_TYPE;
+ *optptr++ = 1;
+ *optptr++ = type;
+ return optptr;
+}
+
+static inline u8 *add_req_options(u8 *optptr)
+{
+ *optptr++ = DHCP_OPTION_REQ_LIST;
+ *optptr++ = 4;
+ *optptr++ = DHCP_OPTION_SUBNET_MASK;
+ *optptr++ = DHCP_OPTION_ROUTER;
+ *optptr++ = DHCP_OPTION_DNS_SERVER;
+ *optptr++ = DHCP_OPTION_MTU;
+ return optptr;
+}
+
+static inline u8 *add_vendor_cid(u8 *optptr)
+{
+ u8 len = strlen(RFC2132_VENDOR_CLASS_ID);
+ *optptr++ = DHCP_OPTION_VCID;
+ *optptr++ = len;
+ memcpy(optptr, RFC2132_VENDOR_CLASS_ID, len);
+ optptr += len;
+ return optptr;
+}
+
+static inline u8 *add_server_id(__be32 *sid, u8 *optptr)
+{
+ *optptr++ = DHCP_OPTION_SERVER_ID;
+ *optptr++ = 4;
+ memcpy(optptr, sid, 4);
+ return optptr + 4;
+}
+
+static inline u8 *add_req_ipaddr(__be32 *ip, u8 *optptr)
+{
+ *optptr++ = DHCP_OPTION_REQ_IPADDR;
+ *optptr++ = 4;
+ memcpy(optptr, ip, 4);
+ return optptr + 4;
+}
+
+static inline u8 *add_end(u8 *optptr)
+{
+ *optptr++ = DHCP_OPTION_END;
+ return optptr;
+}
+
+static void
+libiscsi_process_dhcp_opts(struct dhcp_client_state *client, u8 *optptr,
+ int len)
+{
+ u8 *end = optptr + len;
+ u8 type = 0;
+
+ while (optptr < end) {
+ switch (*optptr) {
+ case DHCP_OPTION_SUBNET_MASK:
+ memcpy(&client->dinfo.netmask, optptr + 2, 4);
+ break;
+ case DHCP_OPTION_ROUTER:
+ memcpy(&client->dinfo.gipaddr, optptr + 2, 4);
+ break;
+ case DHCP_OPTION_DNS_SERVER:
+ memcpy(&client->dinfo.dnsaddr, optptr + 2, 4);
+ break;
+ case DHCP_OPTION_MSG_TYPE:
+ type = *(optptr + 2);
+ if (type == DHCPOFFER)
+ client->state = STATE_OFFER_REC;
+ else if (type == DHCPACK)
+ client->state = STATE_CONFIG_REC;
+ break;
+ case DHCP_OPTION_SERVER_ID:
+ memcpy(&client->dinfo.serverid, optptr + 2, 4);
+ break;
+ case DHCP_OPTION_LEASE_TIME:
+ memcpy(&client->dinfo.ltime, optptr + 2, 4);
+ break;
+ case DHCP_OPTION_END:
+ break;
+ }
+
+ optptr += optptr[1] + 2;
+ }
+}
+
+static void
+libiscsi_process_dhcp_pack(struct dhcp_client_state *client,
+ struct dhcp_pkt *pkt)
+{
+ u8 *start, *end;
+ int opt_len;
+
+ start = &pkt->options[4];
+ end = (u8 *) pkt + ntohs(pkt->iph.tot_len);
+ opt_len = end - start;
+
+ if (pkt->op == DHCP_REPLY &&
+ !memcmp(&pkt->xid, &client->xid, sizeof(client->xid)) &&
+ !memcmp(pkt->chwaddr, client->dinfo.mac_addr, pkt->hlen)) {
+ memcpy(&client->dinfo.ipaddr, &pkt->yipaddr, 4);
+ libiscsi_process_dhcp_opts(client, start, opt_len);
+ }
+}
+
+static int
+libiscsi_ipconfig_send(struct dhcp_client_state *client)
+{
+ int rc = 0;
+ struct sk_buff *lskb = client->skb;
+
+ lskb->dev = client->ndev;
+ lskb->protocol = htons(ETH_P_IP);
+
+ dev_hard_header(lskb, client->ndev, ntohs(lskb->protocol),
+ client->ndev->broadcast,
+ client->dinfo.mac_addr, lskb->len);
+ rc = dev_queue_xmit(lskb);
+
+ return rc;
+}
+
+int
+libiscsi_ipconfig_recv(struct net_device *ndev, struct sk_buff *skb)
+{
+ struct iphdr *iph;
+ struct udphdr *udph;
+ struct ethhdr *eh;
+ struct dhcp_pkt *pkt;
+ struct sk_buff *pskb;
+ int len, opts_len;
+ struct dhcp_client_state *client;
+ int rc = 0;
+
+
+ client = &client_state;
+
+ if (unlikely(client->state == STATE_INIT))
+ goto out;
+
+ if (skb->pkt_type != PACKET_OTHERHOST)
+ goto out;
+
+ pskb = skb_copy(skb, GFP_ATOMIC);
+ if (!pskb) {
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ eh = eth_hdr(pskb);
+ if (!is_valid_ether_addr(eh->h_dest))
+ goto drop;
+
+ if (compare_ether_addr(eh->h_dest, client->dinfo.mac_addr))
+ goto drop;
+
+ if (!pskb_may_pull(pskb, sizeof(struct iphdr) + sizeof(struct udphdr)))
+ goto drop;
+
+
+ skb_reset_network_header(pskb);
+ pkt = (struct dhcp_pkt *) skb_network_header(pskb);
+ iph = &pkt->iph;
+
+ if (iph->ihl != 5 || iph->version != 4 || iph->protocol != IPPROTO_UDP)
+ goto drop;
+
+ if (iph->frag_off & htons(IP_OFFSET | IP_MF))
+ goto drop;
+
+ if (skb->len < ntohs(iph->tot_len))
+ goto drop;
+
+ if (ip_fast_csum((u8 *)iph, iph->ihl))
+ goto drop;
+
+ udph = &pkt->udph;
+ if (udph->source != htons(67) || udph->dest != htons(68))
+ goto drop;
+
+ if (ntohs(iph->tot_len) < ntohs(udph->len) + sizeof(struct iphdr))
+ goto drop;
+
+ len = ntohs(udph->len) - sizeof(struct udphdr);
+ opts_len = len - (sizeof(*pkt) -
+ sizeof(struct iphdr) -
+ sizeof(struct udphdr) -
+ sizeof(pkt->options));
+ if (opts_len < 0)
+ goto drop;
+
+ if (memcmp(pkt->options, magic_cookie, 4))
+ goto drop;
+
+ spin_lock(&rcv_lock);
+
+ libiscsi_process_dhcp_pack(client, pkt);
+
+ spin_unlock(&rcv_lock);
+
+drop:
+ kfree(pskb);
+out:
+ return rc;
+}
+EXPORT_SYMBOL(libiscsi_ipconfig_recv);
+
+static int
+libiscsi_create_dhcp_msg(struct dhcp_client_state *client)
+{
+ struct iphdr *iph;
+ struct udphdr *udph;
+ struct sk_buff *skb;
+ struct dhcp_pkt *pkt;
+ int rc = 0;
+
+ skb = alloc_skb(sizeof(*pkt) +
+ LL_ALLOCATED_SPACE(client->ndev) + 15,
+ GFP_KERNEL);
+ if (!skb) {
+ rc = -ENOMEM;
+ return rc;
+ }
+
+ client->skb = skb;
+ skb_reserve(skb, LL_RESERVED_SPACE(client->ndev));
+
+ pkt = (struct dhcp_pkt *) skb_put(skb, sizeof(*pkt));
+ BUG_ON(!pkt);
+ client->pkt = pkt;
+ memset(pkt, 0, sizeof(*pkt));
+
+ skb_reset_network_header(skb);
+
+ /* construct IP header */
+ iph = &pkt->iph;
+ iph->version = 4;
+ iph->ihl = 5;
+ iph->tot_len = htons(sizeof(struct dhcp_pkt));
+ iph->frag_off = htons(IP_DF);
+ iph->ttl = 64;
+ iph->protocol = IPPROTO_UDP;
+ iph->daddr = htonl(INADDR_BROADCAST);
+ iph->check = ip_fast_csum((u8 *) iph, iph->ihl);
+
+ /* Construct UDP header */
+ udph = &pkt->udph;
+ udph->source = htons(DHCPC_CLIENT_PORT);
+ udph->dest = htons(DHCPC_SERVER_PORT);
+ udph->len = htons(sizeof(struct dhcp_pkt) - sizeof(struct iphdr));
+
+ pkt->op = DHCP_REQUEST;
+ pkt->htype = DHCP_HTYPE_ETHERNET;
+ pkt->hlen = ETH_ALEN;
+
+ memcpy(pkt->chwaddr, client->dinfo.mac_addr, ETH_ALEN);
+ pkt->secs = htons(jiffies / HZ);
+ pkt->xid = client->xid;
+
+ memcpy(pkt->options, magic_cookie, sizeof(magic_cookie));
+
+ return rc;
+}
+
+static int libiscsi_send_dhcp_request(struct dhcp_client_state *client)
+{
+ int rc = 0;
+ u8 *end;
+
+ rc = libiscsi_create_dhcp_msg(client);
+ if (rc)
+ return rc;
+
+ end = add_msg_type(&client->pkt->options[4], DHCPREQUEST);
+ end = add_server_id(&client->dinfo.serverid, end);
+ end = add_req_ipaddr(&client->dinfo.ipaddr, end);
+ end = add_vendor_cid(end);
+ end = add_end(end);
+
+ rc = libiscsi_ipconfig_send(client);
+
+ return rc;
+}
+
+static int libiscsi_send_dhcp_discover(struct dhcp_client_state *client)
+{
+ int rc = 0;
+ u8 *end;
+
+ rc = libiscsi_create_dhcp_msg(client);
+ if (rc)
+ return rc;
+
+ end = add_msg_type(&client->pkt->options[4], DHCPDISCOVER);
+ end = add_req_options(end);
+ end = add_vendor_cid(end);
+ end = add_end(end);
+
+ client->state = STATE_SENDING;
+ rc = libiscsi_ipconfig_send(client);
+
+ return rc;
+}
+
+static void
+libiscsi_wait_for_pack(struct dhcp_client_state *client, u8 state)
+{
+ unsigned long tout, ntout;
+
+ get_random_bytes(&tout, sizeof(tout));
+ tout = (tout % (unsigned)HZ) + (HZ * 2);
+
+ ntout = jiffies + tout;
+ while (time_before(jiffies, ntout) && (client->state != state))
+ schedule_timeout_uninterruptible(1);
+}
+
+int libiscsi_do_ipconf(struct net_device *ndev, struct dhcp_info *dinfo)
+{
+ int rc = 0;
+ int retry;
+ struct dhcp_client_state *client;
+ retry = 2;
+
+ client = &client_state;
+ client->dinfo.mac_addr = dinfo->mac_addr;
+ client->ndev = ndev;
+ client->state = STATE_INIT;
+
+ /* show time */
+ for (;;) {
+ get_random_bytes(&client->xid, sizeof(__be32));
+ libiscsi_send_dhcp_discover(client);
+ libiscsi_wait_for_pack(client, STATE_OFFER_REC);
+
+ if (client->state == STATE_OFFER_REC) {
+ libiscsi_send_dhcp_request(client);
+ libiscsi_wait_for_pack(client, STATE_CONFIG_REC);
+ if (client->state == STATE_CONFIG_REC) {
+ dinfo->ipaddr = client->dinfo.ipaddr;
+ dinfo->netmask = client->dinfo.netmask;
+ dinfo->ltime = client->dinfo.ltime;
+ client->state = STATE_INIT;
+ break;
+ }
+ }
+
+ if (!--retry) {
+ rc = -ENETUNREACH;
+ break;
+ }
+ }
+
+ return rc;
+}
+EXPORT_SYMBOL(libiscsi_do_ipconf);
+
+MODULE_AUTHOR("Rakesh Ranjan");
+MODULE_DESCRIPTION("iSCSI ipconfig functions");
+MODULE_LICENSE("GPL");
--
1.6.0.6
^ permalink raw reply related
* Re: [PATCH 2/2] act_mirred: optimization
From: David Miller @ 2009-11-16 13:17 UTC (permalink / raw)
To: xiaosuo; +Cc: hadi, shemminger, netdev
In-Reply-To: <412e6f7f0911160505x10da9a92j694669db9d030da1@mail.gmail.com>
From: Changli Gao <xiaosuo@gmail.com>
Date: Mon, 16 Nov 2009 21:05:28 +0800
> I am sorry about that. But I did test it before submitting these two,
> and I am just wondering if they are applied without any error. Would
> you post the file after being patched? I think it will be helpful to
> finger out the real problem.
I don't have time for that sorry.
I think the problem might be that you are developing against
either net-2.6 or Linus's tree, whereas you should be working
against net-next-2.6
^ permalink raw reply
* Re: [RFC-PATCH] libiscsi dhcp handler
From: David Miller @ 2009-11-16 13:18 UTC (permalink / raw)
To: rakesh; +Cc: michaelc, open-iscsi, netdev, linux-kernel, James.Bottomley, kxie
In-Reply-To: <4B014F95.8000906@chelsio.com>
From: Rakesh Ranjan <rakesh@chelsio.com>
Date: Mon, 16 Nov 2009 18:41:49 +0530
> Herein attached patches to support dhcp based provisioning for iSCSI
> offload capable cards. I have made dhcp code as generic as possible,
> please go through the code. Based on the feedback I will submit final
> version of these patches.
You can't really add objects to the build before the patch that
adds the source for that object.
^ permalink raw reply
* Re: [PATCH 2/2] act_mirred: optimization
From: Changli Gao @ 2009-11-16 13:22 UTC (permalink / raw)
To: David Miller; +Cc: hadi, shemminger, netdev
In-Reply-To: <20091116.051722.255835290.davem@davemloft.net>
On Mon, Nov 16, 2009 at 9:17 PM, David Miller <davem@davemloft.net> wrote:
> From: Changli Gao <xiaosuo@gmail.com>
> Date: Mon, 16 Nov 2009 21:05:28 +0800
>
>> I am sorry about that. But I did test it before submitting these two,
>> and I am just wondering if they are applied without any error. Would
>> you post the file after being patched? I think it will be helpful to
>> finger out the real problem.
>
> I don't have time for that sorry.
Thanks all the same!
>
> I think the problem might be that you are developing against
> either net-2.6 or Linus's tree, whereas you should be working
> against net-next-2.6
>
I am working against linux-next. I'll check if there is any
difference. BTW: were these patches applied in order, 1 - 2?
--
Regards,
Changli Gao(xiaosuo@gmail.com)
^ permalink raw reply
* Re: [RFC-PATCH] libiscsi dhcp handler
From: Rakesh Ranjan @ 2009-11-16 13:24 UTC (permalink / raw)
To: David Miller
Cc: michaelc, open-iscsi, netdev, linux-kernel, James.Bottomley, kxie
In-Reply-To: <20091116.051835.125328285.davem@davemloft.net>
David Miller wrote:
> From: Rakesh Ranjan <rakesh@chelsio.com>
> Date: Mon, 16 Nov 2009 18:41:49 +0530
>
>> Herein attached patches to support dhcp based provisioning for iSCSI
>> offload capable cards. I have made dhcp code as generic as possible,
>> please go through the code. Based on the feedback I will submit final
>> version of these patches.
>
> You can't really add objects to the build before the patch that
> adds the source for that object.
>
my mistake, the makefile part of patch is irrelevant. Will send new
patch in few mins.
Regards
Rakesh Ranjan
^ permalink raw reply
* Re: [PATCH 2/2] act_mirred: optimization
From: Jarek Poplawski @ 2009-11-16 13:27 UTC (permalink / raw)
To: Changli Gao; +Cc: David Miller, hadi, shemminger, netdev
In-Reply-To: <412e6f7f0911160505x10da9a92j694669db9d030da1@mail.gmail.com>
On 16-11-2009 14:05, Changli Gao wrote:
> On Mon, Nov 16, 2009 at 6:58 PM, David Miller <davem@davemloft.net> wrote:
>> From: David Miller <davem@davemloft.net>
>> Date: Mon, 16 Nov 2009 02:48:39 -0800 (PST)
>>
>>> From: Changli Gao <xiaosuo@gmail.com>
>>> Date: Mon, 16 Nov 2009 17:53:29 +0800
>>>
>>>> act_mirred: optimization.
>>>>
>>>> move checking if eaction is valid in tcf_mirred_init()
>>>>
>>>> Signed-off-by: Changli Gao <xiaosuo@gmail.com>
>>>> Signed-off-by: Jamal Hadi Salim <hadi@cyberus.ca>
>>> Also applied, thank you.
>> Nevermind, you're NOT TESTING the patches you are posting:
>>
>> net/sched/act_mirred.c: In function â??tcf_mirredâ??:
>> net/sched/act_mirred.c:168: error: label â??outâ?? used but not defined
>> net/sched/act_mirred.c:158: warning: unused variable â??errâ??
>> net/sched/act_mirred.c:158: warning: unused variable â??retvalâ??
>> make[2]: *** [net/sched/act_mirred.o] Error 1
>> make[1]: *** [net/sched] Error 2
>> make[1]: *** Waiting for unfinished jobs....
>>
>> I'm thus reverting both changes.
>>
>> Don't submit changes which are untested, it wastes my time.
>>
>
> I am sorry about that. But I did test it before submitting these two,
> and I am just wondering if they are applied without any error. Would
> you post the file after being patched? I think it will be helpful to
> finger out the real problem.
>
> BTW: since my email client thunderbird was broken, I used google
> webmail(with ViewSourceWith addon) to submit these two patches.
>
It seems PATCH 1/2 might be broken by email (but I got it second hand
from gmail). checkpatch output:
ERROR: patch seems to be corrupt (line wrapped?)
#17: FILE: net/sched/act_mirred.c:147:
struct tc_action *a,
WARNING: printk() should include KERN_ facility level
#34: FILE: net/sched/act_mirred.c:160:
+ printk("tcf_mirred unknown action %d\n",
total: 1 errors, 1 warnings, 89 lines checked
mirred1.diff has style problems, please review. If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
Jarek P.
^ permalink raw reply
* Re: KS8695: problem with ethernet driver
From: Figo.zhang @ 2009-11-12 14:44 UTC (permalink / raw)
To: zeal; +Cc: netdev, Vincent Sanders, Ben Dooks
In-Reply-To: <efc9214f0911160123t31d7df31tc1afcbd5129b7d86@mail.gmail.com>
On Mon, 2009-11-16 at 17:23 +0800, zeal wrote:
> Hi,
>
> I've two questions on the ks8695.
>
> 1. We knew recently Figo.zhang has added NAPI support for ks8695 net driver.
> Thanks him. But on our ks8695 board it couldn't work well as i thought.
> We used net-next-git kernel.
>
> IP layer cannot receive any frame from lan or wan port(s).
>
> After dig into the driver, I found the rx interrupt occurs,
> but the corresponding status bit is not set. So it won't go into napi
> schedule block.
would like to add debug information at ks8695_rx_irq() to see if the
interrupt function can work and the status value? in line 443, add :
printk(KERN_EMERG "rx status = 0x%x\n", status);
>
> if (status & mask_bit) {
> if (napi_schedule_prep(&ksp->napi)) {
> /*disable rx interrupt*/
> status &= ~mask_bit;
> writel(status , KS8695_IRQ_VA + KS8695_INTEN);
> __napi_schedule(&ksp->napi);
> }
> }
>
> Does anybody tested this NAPI driver succeeded before? If so it maybe
> hardware issue.
>
> 2. It's a extend topic about ks8695. Does the cpu port can tell the
> source port (i.e. lan port ID)
> when it receive a frame from LAN ports? I think a smart switch need
> know where the frame come from
> and then decide where it to go. And many switch-chip in this way.
> The manual can't help me at all as i've done according to it.
>
> Any hint is appreciated.
>
^ permalink raw reply
* Re: [PATCH 2/2] act_mirred: optimization
From: David Miller @ 2009-11-16 13:33 UTC (permalink / raw)
To: xiaosuo; +Cc: hadi, shemminger, netdev
In-Reply-To: <412e6f7f0911160522w34895b0eked14f69ccc62c96b@mail.gmail.com>
From: Changli Gao <xiaosuo@gmail.com>
Date: Mon, 16 Nov 2009 21:22:46 +0800
> I am working against linux-next. I'll check if there is any
> difference. BTW: were these patches applied in order, 1 - 2?
Yes, they were.
^ permalink raw reply
* [PATCH 1/2 net-next-2.6] net: add dev_txq_stats_fold() helper
From: Eric Dumazet @ 2009-11-16 13:36 UTC (permalink / raw)
To: David S. Miller; +Cc: Linux Netdev List
Some drivers ndo_get_stats() method need to perform txqueue stats folding.
Move folding from dev_get_stats() to a new dev_txq_stats_fold() function
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---
include/linux/netdevice.h | 1
net/core/dev.c | 48 +++++++++++++++++++++---------------
2 files changed, 30 insertions(+), 19 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 7043f85..c8fa462 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1941,6 +1941,7 @@ extern void netdev_features_change(struct net_device *dev);
extern void dev_load(struct net *net, const char *name);
extern void dev_mcast_init(void);
extern const struct net_device_stats *dev_get_stats(struct net_device *dev);
+extern void dev_txq_stats_fold(const struct net_device *dev, struct net_device_stats *stats);
extern int netdev_max_backlog;
extern int weight_p;
diff --git a/net/core/dev.c b/net/core/dev.c
index 4b24d79..49417ba 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -5168,6 +5168,32 @@ void netdev_run_todo(void)
}
/**
+ * dev_txq_stats_fold - fold tx_queues stats
+ * @dev: device to get statistics from
+ * @stats: struct net_device_stats to hold results
+ */
+void dev_txq_stats_fold(const struct net_device *dev,
+ struct net_device_stats *stats)
+{
+ unsigned long tx_bytes = 0, tx_packets = 0, tx_dropped = 0;
+ unsigned int i;
+ struct netdev_queue *txq;
+
+ for (i = 0; i < dev->num_tx_queues; i++) {
+ txq = netdev_get_tx_queue(dev, i);
+ tx_bytes += txq->tx_bytes;
+ tx_packets += txq->tx_packets;
+ tx_dropped += txq->tx_dropped;
+ }
+ if (tx_bytes || tx_packets || tx_dropped) {
+ stats->tx_bytes = tx_bytes;
+ stats->tx_packets = tx_packets;
+ stats->tx_dropped = tx_dropped;
+ }
+}
+EXPORT_SYMBOL(dev_txq_stats_fold);
+
+/**
* dev_get_stats - get network device statistics
* @dev: device to get statistics from
*
@@ -5181,25 +5207,9 @@ const struct net_device_stats *dev_get_stats(struct net_device *dev)
if (ops->ndo_get_stats)
return ops->ndo_get_stats(dev);
- else {
- unsigned long tx_bytes = 0, tx_packets = 0, tx_dropped = 0;
- struct net_device_stats *stats = &dev->stats;
- unsigned int i;
- struct netdev_queue *txq;
-
- for (i = 0; i < dev->num_tx_queues; i++) {
- txq = netdev_get_tx_queue(dev, i);
- tx_bytes += txq->tx_bytes;
- tx_packets += txq->tx_packets;
- tx_dropped += txq->tx_dropped;
- }
- if (tx_bytes || tx_packets || tx_dropped) {
- stats->tx_bytes = tx_bytes;
- stats->tx_packets = tx_packets;
- stats->tx_dropped = tx_dropped;
- }
- return stats;
- }
+
+ dev_txq_stats_fold(dev, &dev->stats);
+ return &dev->stats;
}
EXPORT_SYMBOL(dev_get_stats);
^ permalink raw reply related
* [PATCH 2/2 net-next-2.6] vlan: Precise RX stats accounting
From: Eric Dumazet @ 2009-11-16 13:37 UTC (permalink / raw)
To: David S. Miller; +Cc: Linux Netdev List
With multi queue devices, its possible that several cpu call
vlan RX routines simultaneously for the same vlan device.
We update RX stats counter without any locking, so we can
get slightly wrong counters.
One possible fix is to use percpu counters, to get precise
accounting and also get guarantee of no cache line ping pongs
between cpus.
In case dynamic percpu allocation fails, we fallback to previous
mode (sharing dev->stats counter)
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---
net/8021q/vlan.c | 1
net/8021q/vlan.h | 10 +++++++
net/8021q/vlan_core.c | 19 ++++++++++----
net/8021q/vlan_dev.c | 53 +++++++++++++++++++++++++++++++++++-----
4 files changed, 72 insertions(+), 11 deletions(-)
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index 39f8d01..db6a9bc 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -179,6 +179,7 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head)
/* Free the group, after all cpu's are done. */
call_rcu(&grp->rcu, vlan_rcu_free);
}
+ free_percpu(vlan->vlan_rx_stats);
/* Get rid of the vlan's reference to real_dev */
dev_put(real_dev);
diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h
index 68f9290..a211a55 100644
--- a/net/8021q/vlan.h
+++ b/net/8021q/vlan.h
@@ -16,6 +16,15 @@ struct vlan_priority_tci_mapping {
struct vlan_priority_tci_mapping *next;
};
+
+/* percpu rx stats */
+struct vlan_rx_stats {
+ unsigned long rx_packets;
+ unsigned long rx_bytes;
+ unsigned long multicast;
+ unsigned long rx_errors;
+};
+
/**
* struct vlan_dev_info - VLAN private device data
* @nr_ingress_mappings: number of ingress priority mappings
@@ -45,6 +54,7 @@ struct vlan_dev_info {
struct proc_dir_entry *dent;
unsigned long cnt_inc_headroom_on_tx;
unsigned long cnt_encap_on_xmit;
+ struct vlan_rx_stats *vlan_rx_stats;
};
static inline struct vlan_dev_info *vlan_dev_info(const struct net_device *dev)
diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c
index 971d375..9b97ffb 100644
--- a/net/8021q/vlan_core.c
+++ b/net/8021q/vlan_core.c
@@ -31,7 +31,7 @@ EXPORT_SYMBOL(__vlan_hwaccel_rx);
int vlan_hwaccel_do_receive(struct sk_buff *skb)
{
struct net_device *dev = skb->dev;
- struct net_device_stats *stats;
+ struct vlan_rx_stats *rx_stats = NULL;
skb->dev = vlan_dev_info(dev)->real_dev;
netif_nit_deliver(skb);
@@ -40,15 +40,24 @@ int vlan_hwaccel_do_receive(struct sk_buff *skb)
skb->priority = vlan_get_ingress_priority(dev, skb->vlan_tci);
skb->vlan_tci = 0;
- stats = &dev->stats;
- stats->rx_packets++;
- stats->rx_bytes += skb->len;
+ if (likely(vlan_dev_info(dev)->vlan_rx_stats)) {
+ rx_stats = per_cpu_ptr(vlan_dev_info(dev)->vlan_rx_stats,
+ smp_processor_id());
+ rx_stats->rx_packets++;
+ rx_stats->rx_bytes += skb->len;
+ } else {
+ dev->stats.rx_packets++;
+ dev->stats.rx_bytes += skb->len;
+ }
switch (skb->pkt_type) {
case PACKET_BROADCAST:
break;
case PACKET_MULTICAST:
- stats->multicast++;
+ if (likely(rx_stats))
+ rx_stats->multicast++;
+ else
+ dev->stats.multicast++;
break;
case PACKET_OTHERHOST:
/* Our lower layer thinks this is not local, let's make sure.
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 9159659..9ef1e0e 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -140,7 +140,7 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *ptype, struct net_device *orig_dev)
{
struct vlan_hdr *vhdr;
- struct net_device_stats *stats;
+ struct vlan_rx_stats *rx_stats = NULL;
u16 vlan_id;
u16 vlan_tci;
@@ -163,9 +163,15 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
goto err_unlock;
}
- stats = &skb->dev->stats;
- stats->rx_packets++;
- stats->rx_bytes += skb->len;
+ if (likely(vlan_dev_info(dev)->vlan_rx_stats)) {
+ rx_stats = per_cpu_ptr(vlan_dev_info(dev)->vlan_rx_stats,
+ smp_processor_id());
+ rx_stats->rx_packets++;
+ rx_stats->rx_bytes += skb->len;
+ } else {
+ dev->stats.rx_packets++;
+ dev->stats.rx_bytes += skb->len;
+ }
skb_pull_rcsum(skb, VLAN_HLEN);
@@ -180,7 +186,10 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
break;
case PACKET_MULTICAST:
- stats->multicast++;
+ if (likely(rx_stats))
+ rx_stats->multicast++;
+ else
+ dev->stats.multicast++;
break;
case PACKET_OTHERHOST:
@@ -200,7 +209,10 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
skb = vlan_check_reorder_header(skb);
if (!skb) {
- stats->rx_errors++;
+ if (likely(rx_stats))
+ rx_stats->rx_errors++;
+ else
+ dev->stats.rx_errors++;
goto err_unlock;
}
@@ -775,6 +787,31 @@ static u32 vlan_ethtool_get_flags(struct net_device *dev)
return dev_ethtool_get_flags(vlan->real_dev);
}
+static struct net_device_stats *vlan_dev_get_stats(struct net_device *dev)
+{
+ struct net_device_stats *stats = &dev->stats;
+
+ dev_txq_stats_fold(dev, stats);
+
+ if (vlan_dev_info(dev)->vlan_rx_stats) {
+ struct vlan_rx_stats *p, rx = {0};
+ int i;
+
+ for_each_possible_cpu(i) {
+ p = per_cpu_ptr(vlan_dev_info(dev)->vlan_rx_stats, i);
+ rx.rx_packets += p->rx_packets;
+ rx.rx_bytes += p->rx_bytes;
+ rx.rx_errors += p->rx_errors;
+ rx.multicast += p->multicast;
+ }
+ stats->rx_packets = rx.rx_packets;
+ stats->rx_bytes = rx.rx_bytes;
+ stats->rx_errors = rx.rx_errors;
+ stats->multicast = rx.multicast;
+ }
+ return stats;
+}
+
static const struct ethtool_ops vlan_ethtool_ops = {
.get_settings = vlan_ethtool_get_settings,
.get_drvinfo = vlan_ethtool_get_drvinfo,
@@ -797,6 +834,7 @@ static const struct net_device_ops vlan_netdev_ops = {
.ndo_change_rx_flags = vlan_dev_change_rx_flags,
.ndo_do_ioctl = vlan_dev_ioctl,
.ndo_neigh_setup = vlan_dev_neigh_setup,
+ .ndo_get_stats = vlan_dev_get_stats,
#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)
.ndo_fcoe_ddp_setup = vlan_dev_fcoe_ddp_setup,
.ndo_fcoe_ddp_done = vlan_dev_fcoe_ddp_done,
@@ -820,6 +858,7 @@ static const struct net_device_ops vlan_netdev_accel_ops = {
.ndo_change_rx_flags = vlan_dev_change_rx_flags,
.ndo_do_ioctl = vlan_dev_ioctl,
.ndo_neigh_setup = vlan_dev_neigh_setup,
+ .ndo_get_stats = vlan_dev_get_stats,
#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)
.ndo_fcoe_ddp_setup = vlan_dev_fcoe_ddp_setup,
.ndo_fcoe_ddp_done = vlan_dev_fcoe_ddp_done,
@@ -841,5 +880,7 @@ void vlan_setup(struct net_device *dev)
dev->destructor = free_netdev;
dev->ethtool_ops = &vlan_ethtool_ops;
+ vlan_dev_info(dev)->vlan_rx_stats = alloc_percpu(struct vlan_rx_stats);
+
memset(dev->broadcast, 0, ETH_ALEN);
}
^ permalink raw reply related
* Re: [PATCH] ppp: fix BUG on non-linear SKB (multilink receive)
From: Ben McKeegan @ 2009-11-16 13:44 UTC (permalink / raw)
To: David Miller; +Cc: paulus, netdev, linux-ppp
In-Reply-To: <20091113.194650.214404898.davem@davemloft.net>
PPP does not correctly call pskb_may_pull() on all necessary receive paths
before reading the PPP protocol, thus causing PPP to report seemingly
random 'unsupported protocols' and eventually trigger BUG_ON(skb->len <
skb->data_len) in skb_pull_rcsum() when receiving multilink protocol in
non-linear skbs.
ppp_receive_nonmp_frame() does not call pskb_may_pull() before reading the
protocol number. For the non-mp receive path this is not a problem, as
this check is done in ppp_receive_frame(). For the mp receive path,
ppp_mp_reconstruct() usually copies the data into a new linear skb.
However, in the case where the frame is made up of a single mp fragment,
the mp header is pulled and the existing skb used. This skb was then
passed to ppp_receive_nonmp_frame() without checking if the encapsulated
protocol header could safely be read.
Signed-off-by: Ben McKeegan <ben@netservers.co.uk>
---
diff -uprN linux-2.6.31.6/drivers/net/ppp_generic.c linux-2.6.31.6-ppp-non-linear-skb/drivers/net/ppp_generic.c
--- linux-2.6.31.6/drivers/net/ppp_generic.c 2009-11-10 00:32:31.000000000 +0000
+++ linux-2.6.31.6-ppp-non-linear-skb/drivers/net/ppp_generic.c 2009-11-16 13:14:22.000000000 +0000
@@ -1943,8 +1943,15 @@ ppp_receive_mp_frame(struct ppp *ppp, st
}
/* Pull completed packets off the queue and receive them. */
- while ((skb = ppp_mp_reconstruct(ppp)))
- ppp_receive_nonmp_frame(ppp, skb);
+ while ((skb = ppp_mp_reconstruct(ppp))) {
+ if (pskb_may_pull(skb, 2))
+ ppp_receive_nonmp_frame(ppp, skb);
+ else {
+ ++ppp->dev->stats.rx_length_errors;
+ kfree_skb(skb);
+ ppp_receive_error(ppp);
+ }
+ }
return;
^ permalink raw reply
* Re: [RFC-PATCH] libiscsi dhcp handler
From: Rakesh Ranjan @ 2009-11-16 13:45 UTC (permalink / raw)
To: David Miller
Cc: michaelc, open-iscsi, netdev, linux-kernel, James.Bottomley, kxie,
Rakesh Ranjan
In-Reply-To: <20091116.051835.125328285.davem@davemloft.net>
[-- Attachment #1: Type: text/plain, Size: 516 bytes --]
David Miller wrote:
> From: Rakesh Ranjan <rakesh@chelsio.com>
> Date: Mon, 16 Nov 2009 18:41:49 +0530
>
>> Herein attached patches to support dhcp based provisioning for iSCSI
>> offload capable cards. I have made dhcp code as generic as possible,
>> please go through the code. Based on the feedback I will submit final
>> version of these patches.
>
> You can't really add objects to the build before the patch that
> adds the source for that object.
>
Hi david,
Fixed patch attached.
Regards
Rakesh Ranjan
[-- Attachment #2: 0001-Required-changes-for-libiscsi-to-support-dhcp-based.patch --]
[-- Type: text/x-patch, Size: 3869 bytes --]
>From a643bfb01c4edbb2e686dd2500a564c93d402bba Mon Sep 17 00:00:00 2001
From: Rakesh Ranjan <rakesh@chelsio.com>
Date: Mon, 16 Nov 2009 19:07:40 +0530
Subject: [PATCH 1/2] Required changes for libiscsi to support dhcp based provisioning for offload capable cards.
These changes adds ISCSI_UEVENT_REQ_IPCONF message to invoke dhcp handler.
Signed-off-by: Rakesh Ranjan <rakesh@chelsio.com>
---
drivers/scsi/scsi_transport_iscsi.c | 25 +++++++++++++++++++++++++
include/scsi/iscsi_if.h | 4 ++++
include/scsi/libiscsi.h | 20 ++++++++++++++++++++
include/scsi/scsi_transport_iscsi.h | 1 +
4 files changed, 50 insertions(+), 0 deletions(-)
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index ad897df..4897a3f 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -1508,6 +1508,28 @@ iscsi_set_path(struct iscsi_transport *transport, struct iscsi_uevent *ev)
}
static int
+iscsi_req_ipconf(struct iscsi_transport *transport, struct iscsi_uevent *ev)
+{
+ struct Scsi_Host *shost;
+ int err;
+
+ if (!transport->req_ipconf)
+ return -ENOSYS;
+
+ shost = scsi_host_lookup(ev->u.req_ipconf.host_no);
+ if (!shost) {
+ printk(KERN_ERR "ipconf req could not find host no %u\n",
+ ev->u.req_ipconf.host_no);
+ return -ENODEV;
+ }
+
+ err = transport->req_ipconf(shost);
+
+ scsi_host_put(shost);
+ return err;
+}
+
+static int
iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
{
int err = 0;
@@ -1627,6 +1649,9 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
case ISCSI_UEVENT_PATH_UPDATE:
err = iscsi_set_path(transport, ev);
break;
+ case ISCSI_UEVENT_REQ_IPCONF:
+ err = iscsi_req_ipconf(transport, ev);
+ break;
default:
err = -ENOSYS;
break;
diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
index d67dda2..135f229 100644
--- a/include/scsi/iscsi_if.h
+++ b/include/scsi/iscsi_if.h
@@ -59,6 +59,7 @@ enum iscsi_uevent_e {
ISCSI_UEVENT_TRANSPORT_EP_CONNECT_THROUGH_HOST = UEVENT_BASE + 19,
ISCSI_UEVENT_PATH_UPDATE = UEVENT_BASE + 20,
+ ISCSI_UEVENT_REQ_IPCONF = UEVENT_BASE + 21,
/* up events */
ISCSI_KEVENT_RECV_PDU = KEVENT_BASE + 1,
@@ -172,6 +173,9 @@ struct iscsi_uevent {
struct msg_set_path {
uint32_t host_no;
} set_path;
+ struct mag_req_ipconf {
+ uint32_t host_no;
+ } req_ipconf;
} u;
union {
/* messages k -> u */
diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
index a72edd4..a9af95e 100644
--- a/include/scsi/libiscsi.h
+++ b/include/scsi/libiscsi.h
@@ -330,6 +330,18 @@ struct iscsi_host {
char workq_name[20];
};
+/* libiscsi ipconfig */
+struct dhcp_info {
+ __be32 ltime;
+ __be32 serverid;
+ __be32 ipaddr;
+ __be32 netmask;
+ __be32 dnsaddr;
+ __be32 gipaddr;
+ __u8 *mac_addr;
+};
+
+
/*
* scsi host template
*/
@@ -427,6 +439,14 @@ extern void iscsi_pool_free(struct iscsi_pool *);
extern int iscsi_pool_init(struct iscsi_pool *, int, void ***, int);
/*
+ * libiscsi ipconfig helpers
+ */
+extern int libiscsi_do_ipconf(struct net_device *ndev,
+ struct dhcp_info *dinfo);
+extern int libiscsi_ipconfig_recv(struct net_device *ndev,
+ struct sk_buff *skb);
+
+/*
* inline functions to deal with padding.
*/
static inline unsigned int
diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
index 349c7f3..3e5fd96 100644
--- a/include/scsi/scsi_transport_iscsi.h
+++ b/include/scsi/scsi_transport_iscsi.h
@@ -134,6 +134,7 @@ struct iscsi_transport {
int (*tgt_dscvr) (struct Scsi_Host *shost, enum iscsi_tgt_dscvr type,
uint32_t enable, struct sockaddr *dst_addr);
int (*set_path) (struct Scsi_Host *shost, struct iscsi_path *params);
+ int (*req_ipconf) (struct Scsi_Host *shost);
};
/*
--
1.6.0.6
[-- Attachment #3: 0002-dhcp-handler-for-libiscsi-to-support-dhcp-provisioni.patch --]
[-- Type: text/x-patch, Size: 11987 bytes --]
>From 604f882083472b515342c43790eb252dd0e9a18b Mon Sep 17 00:00:00 2001
From: Rakesh Ranjan <rakesh@chelsio.com>
Date: Mon, 16 Nov 2009 19:10:00 +0530
Subject: [PATCH 2/2] dhcp handler for libiscsi to support dhcp provisioning for offload capable cards.
This module contains a compact dhcp handler to support dhcp based provisioning for
offload capable cards.
Signed-off-by: Rakesh Ranjan <rakesh@chelsio.com>
---
drivers/scsi/Makefile | 2 +-
drivers/scsi/libiscsi_ipconfig.c | 466 ++++++++++++++++++++++++++++++++++++++
2 files changed, 467 insertions(+), 1 deletions(-)
create mode 100644 drivers/scsi/libiscsi_ipconfig.c
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 3ad61db..c53355f 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -129,7 +129,7 @@ obj-$(CONFIG_SCSI_HPTIOP) += hptiop.o
obj-$(CONFIG_SCSI_STEX) += stex.o
obj-$(CONFIG_SCSI_MVSAS) += mvsas/
obj-$(CONFIG_PS3_ROM) += ps3rom.o
-obj-$(CONFIG_SCSI_CXGB3_ISCSI) += libiscsi.o libiscsi_tcp.o cxgb3i/
+obj-$(CONFIG_SCSI_CXGB3_ISCSI) += libiscsi.o libiscsi_ipconfig.o libiscsi_tcp.o cxgb3i/
obj-$(CONFIG_SCSI_BNX2_ISCSI) += libiscsi.o bnx2i/
obj-$(CONFIG_BE2ISCSI) += libiscsi.o be2iscsi/
obj-$(CONFIG_SCSI_PMCRAID) += pmcraid.o
diff --git a/drivers/scsi/libiscsi_ipconfig.c b/drivers/scsi/libiscsi_ipconfig.c
new file mode 100644
index 0000000..4057aae
--- /dev/null
+++ b/drivers/scsi/libiscsi_ipconfig.c
@@ -0,0 +1,466 @@
+/* libiscsi_ipconfig.c: libiscsi dhcp client.
+ *
+ * Copyright (c) 2009 Chelsio Communications, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ *
+ * Written by: Rakesh Ranjan (rakesh@chelsio.com)
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/in.h>
+#include <linux/delay.h>
+#include <linux/if_arp.h>
+#include <net/ip.h>
+#include <scsi/iscsi_if.h>
+#include <scsi/libiscsi.h>
+
+#define DHCP_REQUEST 1
+#define DHCP_REPLY 2
+#define DHCP_HTYPE_ETHERNET 1
+#define DHCP_HLEN_ETHERNET 6
+#define DHCP_MSG_LEN 236
+
+#define DHCPC_SERVER_PORT 67
+#define DHCPC_CLIENT_PORT 68
+
+/* DHCP message types */
+#define DHCPDISCOVER 1
+#define DHCPOFFER 2
+#define DHCPREQUEST 3
+#define DHCPDECLINE 4
+#define DHCPACK 5
+#define DHCPNAK 6
+#define DHCPRELEASE 7
+#define DHCPINFORM 8
+
+/* DHCP options */
+#define DHCP_OPTION_SUBNET_MASK 1
+#define DHCP_OPTION_ROUTER 3
+#define DHCP_OPTION_DNS_SERVER 6
+#define DHCP_OPTION_MTU 26
+#define DHCP_OPTION_REQ_IPADDR 50
+#define DHCP_OPTION_LEASE_TIME 51
+#define DHCP_OPTION_MSG_TYPE 53
+#define DHCP_OPTION_SERVER_ID 54
+#define DHCP_OPTION_REQ_LIST 55
+#define DHCP_OPTION_VCID 60
+#define DHCP_OPTION_END 255
+
+enum {
+ STATE_INIT = 0,
+ STATE_SENDING,
+ STATE_OFFER_REC,
+ STATE_CONFIG_REC,
+};
+
+struct dhcp_pkt {
+ struct iphdr iph;
+ struct udphdr udph;
+ u8 op;
+ u8 htype;
+ u8 hlen;
+ u8 hops;
+ __be32 xid;
+ __be16 secs;
+ __be16 flags;
+ __be32 cipaddr;
+ __be32 yipaddr;
+ __be32 sipaddr;
+ __be32 ripaddr;
+ u8 chwaddr[16];
+ u8 sname[64];
+ u8 bfile[128];
+ u8 options[312];
+};
+
+
+static struct dhcp_client_state {
+ struct sk_buff *skb;
+ struct dhcp_pkt *pkt;
+ struct net_device *ndev;
+ struct list_head list;
+ struct dhcp_info dinfo;
+
+ volatile __u8 state;
+ __be32 xid;
+
+} client_state;
+
+static DEFINE_SPINLOCK(rcv_lock);
+
+static const char *RFC2132_VENDOR_CLASS_ID = "libiscsi client";
+
+static const u8 magic_cookie[4] = { 99, 130, 83, 99 };
+
+static inline u8 *add_msg_type(u8 *optptr, u8 type)
+{
+ *optptr++ = DHCP_OPTION_MSG_TYPE;
+ *optptr++ = 1;
+ *optptr++ = type;
+ return optptr;
+}
+
+static inline u8 *add_req_options(u8 *optptr)
+{
+ *optptr++ = DHCP_OPTION_REQ_LIST;
+ *optptr++ = 4;
+ *optptr++ = DHCP_OPTION_SUBNET_MASK;
+ *optptr++ = DHCP_OPTION_ROUTER;
+ *optptr++ = DHCP_OPTION_DNS_SERVER;
+ *optptr++ = DHCP_OPTION_MTU;
+ return optptr;
+}
+
+static inline u8 *add_vendor_cid(u8 *optptr)
+{
+ u8 len = strlen(RFC2132_VENDOR_CLASS_ID);
+ *optptr++ = DHCP_OPTION_VCID;
+ *optptr++ = len;
+ memcpy(optptr, RFC2132_VENDOR_CLASS_ID, len);
+ optptr += len;
+ return optptr;
+}
+
+static inline u8 *add_server_id(__be32 *sid, u8 *optptr)
+{
+ *optptr++ = DHCP_OPTION_SERVER_ID;
+ *optptr++ = 4;
+ memcpy(optptr, sid, 4);
+ return optptr + 4;
+}
+
+static inline u8 *add_req_ipaddr(__be32 *ip, u8 *optptr)
+{
+ *optptr++ = DHCP_OPTION_REQ_IPADDR;
+ *optptr++ = 4;
+ memcpy(optptr, ip, 4);
+ return optptr + 4;
+}
+
+static inline u8 *add_end(u8 *optptr)
+{
+ *optptr++ = DHCP_OPTION_END;
+ return optptr;
+}
+
+static void
+libiscsi_process_dhcp_opts(struct dhcp_client_state *client, u8 *optptr,
+ int len)
+{
+ u8 *end = optptr + len;
+ u8 type = 0;
+
+ while (optptr < end) {
+ switch (*optptr) {
+ case DHCP_OPTION_SUBNET_MASK:
+ memcpy(&client->dinfo.netmask, optptr + 2, 4);
+ break;
+ case DHCP_OPTION_ROUTER:
+ memcpy(&client->dinfo.gipaddr, optptr + 2, 4);
+ break;
+ case DHCP_OPTION_DNS_SERVER:
+ memcpy(&client->dinfo.dnsaddr, optptr + 2, 4);
+ break;
+ case DHCP_OPTION_MSG_TYPE:
+ type = *(optptr + 2);
+ if (type == DHCPOFFER)
+ client->state = STATE_OFFER_REC;
+ else if (type == DHCPACK)
+ client->state = STATE_CONFIG_REC;
+ break;
+ case DHCP_OPTION_SERVER_ID:
+ memcpy(&client->dinfo.serverid, optptr + 2, 4);
+ break;
+ case DHCP_OPTION_LEASE_TIME:
+ memcpy(&client->dinfo.ltime, optptr + 2, 4);
+ break;
+ case DHCP_OPTION_END:
+ break;
+ }
+
+ optptr += optptr[1] + 2;
+ }
+}
+
+static void
+libiscsi_process_dhcp_pack(struct dhcp_client_state *client,
+ struct dhcp_pkt *pkt)
+{
+ u8 *start, *end;
+ int opt_len;
+
+ start = &pkt->options[4];
+ end = (u8 *) pkt + ntohs(pkt->iph.tot_len);
+ opt_len = end - start;
+
+ if (pkt->op == DHCP_REPLY &&
+ !memcmp(&pkt->xid, &client->xid, sizeof(client->xid)) &&
+ !memcmp(pkt->chwaddr, client->dinfo.mac_addr, pkt->hlen)) {
+ memcpy(&client->dinfo.ipaddr, &pkt->yipaddr, 4);
+ libiscsi_process_dhcp_opts(client, start, opt_len);
+ }
+}
+
+static int
+libiscsi_ipconfig_send(struct dhcp_client_state *client)
+{
+ int rc = 0;
+ struct sk_buff *lskb = client->skb;
+
+ lskb->dev = client->ndev;
+ lskb->protocol = htons(ETH_P_IP);
+
+ dev_hard_header(lskb, client->ndev, ntohs(lskb->protocol),
+ client->ndev->broadcast,
+ client->dinfo.mac_addr, lskb->len);
+ rc = dev_queue_xmit(lskb);
+
+ return rc;
+}
+
+int
+libiscsi_ipconfig_recv(struct net_device *ndev, struct sk_buff *skb)
+{
+ struct iphdr *iph;
+ struct udphdr *udph;
+ struct ethhdr *eh;
+ struct dhcp_pkt *pkt;
+ struct sk_buff *pskb;
+ int len, opts_len;
+ struct dhcp_client_state *client;
+ int rc = 0;
+
+
+ client = &client_state;
+
+ if (unlikely(client->state == STATE_INIT))
+ goto out;
+
+ if (skb->pkt_type != PACKET_OTHERHOST)
+ goto out;
+
+ pskb = skb_copy(skb, GFP_ATOMIC);
+ if (!pskb) {
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ eh = eth_hdr(pskb);
+ if (!is_valid_ether_addr(eh->h_dest))
+ goto drop;
+
+ if (compare_ether_addr(eh->h_dest, client->dinfo.mac_addr))
+ goto drop;
+
+ if (!pskb_may_pull(pskb, sizeof(struct iphdr) + sizeof(struct udphdr)))
+ goto drop;
+
+
+ skb_reset_network_header(pskb);
+ pkt = (struct dhcp_pkt *) skb_network_header(pskb);
+ iph = &pkt->iph;
+
+ if (iph->ihl != 5 || iph->version != 4 || iph->protocol != IPPROTO_UDP)
+ goto drop;
+
+ if (iph->frag_off & htons(IP_OFFSET | IP_MF))
+ goto drop;
+
+ if (skb->len < ntohs(iph->tot_len))
+ goto drop;
+
+ if (ip_fast_csum((u8 *)iph, iph->ihl))
+ goto drop;
+
+ udph = &pkt->udph;
+ if (udph->source != htons(67) || udph->dest != htons(68))
+ goto drop;
+
+ if (ntohs(iph->tot_len) < ntohs(udph->len) + sizeof(struct iphdr))
+ goto drop;
+
+ len = ntohs(udph->len) - sizeof(struct udphdr);
+ opts_len = len - (sizeof(*pkt) -
+ sizeof(struct iphdr) -
+ sizeof(struct udphdr) -
+ sizeof(pkt->options));
+ if (opts_len < 0)
+ goto drop;
+
+ if (memcmp(pkt->options, magic_cookie, 4))
+ goto drop;
+
+ spin_lock(&rcv_lock);
+
+ libiscsi_process_dhcp_pack(client, pkt);
+
+ spin_unlock(&rcv_lock);
+
+drop:
+ kfree(pskb);
+out:
+ return rc;
+}
+EXPORT_SYMBOL(libiscsi_ipconfig_recv);
+
+static int
+libiscsi_create_dhcp_msg(struct dhcp_client_state *client)
+{
+ struct iphdr *iph;
+ struct udphdr *udph;
+ struct sk_buff *skb;
+ struct dhcp_pkt *pkt;
+ int rc = 0;
+
+ skb = alloc_skb(sizeof(*pkt) +
+ LL_ALLOCATED_SPACE(client->ndev) + 15,
+ GFP_KERNEL);
+ if (!skb) {
+ rc = -ENOMEM;
+ return rc;
+ }
+
+ client->skb = skb;
+ skb_reserve(skb, LL_RESERVED_SPACE(client->ndev));
+
+ pkt = (struct dhcp_pkt *) skb_put(skb, sizeof(*pkt));
+ BUG_ON(!pkt);
+ client->pkt = pkt;
+ memset(pkt, 0, sizeof(*pkt));
+
+ skb_reset_network_header(skb);
+
+ /* construct IP header */
+ iph = &pkt->iph;
+ iph->version = 4;
+ iph->ihl = 5;
+ iph->tot_len = htons(sizeof(struct dhcp_pkt));
+ iph->frag_off = htons(IP_DF);
+ iph->ttl = 64;
+ iph->protocol = IPPROTO_UDP;
+ iph->daddr = htonl(INADDR_BROADCAST);
+ iph->check = ip_fast_csum((u8 *) iph, iph->ihl);
+
+ /* Construct UDP header */
+ udph = &pkt->udph;
+ udph->source = htons(DHCPC_CLIENT_PORT);
+ udph->dest = htons(DHCPC_SERVER_PORT);
+ udph->len = htons(sizeof(struct dhcp_pkt) - sizeof(struct iphdr));
+
+ pkt->op = DHCP_REQUEST;
+ pkt->htype = DHCP_HTYPE_ETHERNET;
+ pkt->hlen = ETH_ALEN;
+
+ memcpy(pkt->chwaddr, client->dinfo.mac_addr, ETH_ALEN);
+ pkt->secs = htons(jiffies / HZ);
+ pkt->xid = client->xid;
+
+ memcpy(pkt->options, magic_cookie, sizeof(magic_cookie));
+
+ return rc;
+}
+
+static int libiscsi_send_dhcp_request(struct dhcp_client_state *client)
+{
+ int rc = 0;
+ u8 *end;
+
+ rc = libiscsi_create_dhcp_msg(client);
+ if (rc)
+ return rc;
+
+ end = add_msg_type(&client->pkt->options[4], DHCPREQUEST);
+ end = add_server_id(&client->dinfo.serverid, end);
+ end = add_req_ipaddr(&client->dinfo.ipaddr, end);
+ end = add_vendor_cid(end);
+ end = add_end(end);
+
+ rc = libiscsi_ipconfig_send(client);
+
+ return rc;
+}
+
+static int libiscsi_send_dhcp_discover(struct dhcp_client_state *client)
+{
+ int rc = 0;
+ u8 *end;
+
+ rc = libiscsi_create_dhcp_msg(client);
+ if (rc)
+ return rc;
+
+ end = add_msg_type(&client->pkt->options[4], DHCPDISCOVER);
+ end = add_req_options(end);
+ end = add_vendor_cid(end);
+ end = add_end(end);
+
+ client->state = STATE_SENDING;
+ rc = libiscsi_ipconfig_send(client);
+
+ return rc;
+}
+
+static void
+libiscsi_wait_for_pack(struct dhcp_client_state *client, u8 state)
+{
+ unsigned long tout, ntout;
+
+ get_random_bytes(&tout, sizeof(tout));
+ tout = (tout % (unsigned)HZ) + (HZ * 2);
+
+ ntout = jiffies + tout;
+ while (time_before(jiffies, ntout) && (client->state != state))
+ schedule_timeout_uninterruptible(1);
+}
+
+int libiscsi_do_ipconf(struct net_device *ndev, struct dhcp_info *dinfo)
+{
+ int rc = 0;
+ int retry;
+ struct dhcp_client_state *client;
+ retry = 2;
+
+ client = &client_state;
+ client->dinfo.mac_addr = dinfo->mac_addr;
+ client->ndev = ndev;
+ client->state = STATE_INIT;
+
+ /* show time */
+ for (;;) {
+ get_random_bytes(&client->xid, sizeof(__be32));
+ libiscsi_send_dhcp_discover(client);
+ libiscsi_wait_for_pack(client, STATE_OFFER_REC);
+
+ if (client->state == STATE_OFFER_REC) {
+ libiscsi_send_dhcp_request(client);
+ libiscsi_wait_for_pack(client, STATE_CONFIG_REC);
+ if (client->state == STATE_CONFIG_REC) {
+ dinfo->ipaddr = client->dinfo.ipaddr;
+ dinfo->netmask = client->dinfo.netmask;
+ dinfo->ltime = client->dinfo.ltime;
+ client->state = STATE_INIT;
+ break;
+ }
+ }
+
+ if (!--retry) {
+ rc = -ENETUNREACH;
+ break;
+ }
+ }
+
+ return rc;
+}
+EXPORT_SYMBOL(libiscsi_do_ipconf);
+
+MODULE_AUTHOR("Rakesh Ranjan");
+MODULE_DESCRIPTION("iSCSI ipconfig functions");
+MODULE_LICENSE("GPL");
--
1.6.0.6
^ permalink raw reply related
* Re: [PATCH v1 resent] net: TCP_MSS_DEFAULT, TCP_MSS_DESIRED
From: William Allen Simpson @ 2009-11-16 14:01 UTC (permalink / raw)
To: David Miller; +Cc: netdev, linux-kernel
In-Reply-To: <20091115.205442.77893528.davem@davemloft.net>
David Miller wrote:
> I already applied this patch to net-next-2.6, there is no need
> to resend it.
>
Cool, there wasn't your usual "applied" response to the list, so the
instructions say send again after waiting (5 days in this case), as it
might have been overlooked.
'git fetch' followed by 'git rebase origin/master' re-applies my patches
locally, but doesn't inform me that this patch has already been applied,
it just handles it silently....
I've found the log, it's commit bee7ca9ec03a26676ea2b1c28dc4039348eff3e1
Thanks!
^ permalink raw reply
* Re: [RFC PATCH] net: add dataref destructor to sk_buff
From: Gregory Haskins @ 2009-11-16 14:22 UTC (permalink / raw)
To: David Miller
Cc: herbert, ghaskins, mst, alacrityvm-devel, linux-kernel, netdev
In-Reply-To: <20091113.190438.78469912.davem@davemloft.net>
[-- Attachment #1: Type: text/plain, Size: 2245 bytes --]
David Miller wrote:
> From: Gregory Haskins <gregory.haskins@gmail.com>
> Date: Fri, 13 Nov 2009 20:33:35 -0500
>
>> Well, not with respect to the overall protocol, of course not. But with
>> respect to the buffer in question, it _has_ to be. Or am I missing
>> something?
>
> sendfile() absolutely, and positively, is not.
>
> Any entity can write to the pages being send via sendfile(), at will,
> and those writes will show up in the packet stream if they occur
> before the NIC DMA's the memory backed by those pages into it's
> buffer.
Right, understood.
>
> There is zero data synchronization whatsoever, we don't lock the
> pages, we don't block their usage while they are queued up in the
> socket send queue, nothing like that.
Understood.
>
> The user returns long before it every hits the wire and there is zero
> "notification" to the user that the pages in question for the
> sendfile() request are no longer in use.
Ok, this was the part I didn't know.
>
> It seems that your understanding of how buffering and synchronization
> works in the TCP stack has come out of a fairy tale :-)
I understand that we do not protect the buffers from modification from
other entities in process. This was purely a question of
synchronization from the producers standpoint.
IOW:
for (;;) {
char buf[512];
memcpy(buf, next, sizeof(buf));
write(fd, buf);
}
would work without worrying that the producer will stomp on buf itself.
It is now my understanding that for things other than sendfile, this
works because the buffer is copied before it returns control to the app.
For sendfile(), the producer is more or less on its own and therefore
has to be careful if they are reusing previous mmapped buffers. Ok.
But really, this is somewhat orthogonal to the original problem, so let
me see if we can bring it back on topic. Michael stated that this patch
in question may be problematic because there are places in the stack
that can get_page() without also maintaining a reference to the shinfo
object. Evgeniy seems to say the opposite. I am not sure who is right,
or if I misunderstood one or both of them. Any thoughts?
Kind Regards,
-Greg
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 267 bytes --]
^ permalink raw reply
* [PATCH 1/2] KS8695: fix ks8695_rx_irq() bug.
From: zealcook @ 2009-11-16 14:30 UTC (permalink / raw)
To: netdev; +Cc: ben, davem, jie.zeng
From: jie.zeng <jie.zeng@soliton.com.cn>
ks8695 rx irq is edge-level. Before arriving at irq handler, the
corresponding status bit has been clear(irq's ack).
So we should not check it after that.
Signed-off-by: jie.zeng <jie.zeng@soliton.com.cn>
---
drivers/net/arm/ks8695net.c | 20 +++++++-------------
1 files changed, 7 insertions(+), 13 deletions(-)
diff --git a/drivers/net/arm/ks8695net.c b/drivers/net/arm/ks8695net.c
index 0073d19..64c683d 100644
--- a/drivers/net/arm/ks8695net.c
+++ b/drivers/net/arm/ks8695net.c
@@ -433,24 +433,18 @@ ks8695_rx_irq(int irq, void *dev_id)
{
struct net_device *ndev = (struct net_device *)dev_id;
struct ks8695_priv *ksp = netdev_priv(ndev);
- unsigned long status;
-
- unsigned long mask_bit = 1 << ks8695_get_rx_enable_bit(ksp);
spin_lock(&ksp->rx_lock);
status = readl(KS8695_IRQ_VA + KS8695_INTST);
- /*clean rx status bit*/
- writel(status | mask_bit , KS8695_IRQ_VA + KS8695_INTST);
-
- if (status & mask_bit) {
- if (napi_schedule_prep(&ksp->napi)) {
- /*disable rx interrupt*/
- status &= ~mask_bit;
- writel(status , KS8695_IRQ_VA + KS8695_INTEN);
- __napi_schedule(&ksp->napi);
- }
+ if (napi_schedule_prep(&ksp->napi)) {
+ unsigned long status;
+ unsigned long mask_bit = 1 << ks8695_get_rx_enable_bit(ksp);
+ /*disable rx interrupt*/
+ status &= ~mask_bit;
+ writel(status , KS8695_IRQ_VA + KS8695_INTEN);
+ __napi_schedule(&ksp->napi);
}
spin_unlock(&ksp->rx_lock);
--
1.4.4.4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox