* Re: [patch v4 00/12] IPVS: SIP Persistence Engine
From: Simon Horman @ 2010-10-04 11:30 UTC (permalink / raw)
To: lvs-devel, netdev, netfilter, netfilter-devel
Cc: Jan Engelhardt, Stephen Hemminger, Wensong Zhang,
Julian Anastasov, Patrick McHardy
In-Reply-To: <20101004090352.966809749@akiko.akashicho.tokyo.vergenet.net>
On Mon, Oct 04, 2010 at 06:03:52PM +0900, Simon Horman wrote:
> This patch series adds load-balancing of UDP SIP based on Call-ID to
> IPVS as well as a frame-work for extending IPVS to handle alternate
> persistence requirements.
[snip]
> CODE AVAILABILITY
>
> The kernel patches (12) are available in git as the pe-3 branch of
> git://git.kernel.org/pub/scm/linux/kernel/git/horms/lvs-test-2.6.git
>
> The ipvsadm patches (2) are available in git as the pe-3 branch of
> git://github.com/horms/ipvsadm-test.git
pe-3 should read pe-4 above (x2).
> There is no change to the ipvsadm patches since the v2 series
> so I will not repost them.
^ permalink raw reply
* Re: [PATCH net-next V3] net: dynamic ingress_queue allocation
From: Jarek Poplawski @ 2010-10-04 12:06 UTC (permalink / raw)
To: Eric Dumazet; +Cc: hadi, David Miller, netdev
In-Reply-To: <1286181729.18293.8.camel@edumazet-laptop>
On Mon, Oct 04, 2010 at 10:42:09AM +0200, Eric Dumazet wrote:
> Le dimanche 03 octobre 2010 ?? 11:42 +0200, Jarek Poplawski a écrit :
>
> > I'd consider rcu_dereference_rtnl(). Btw, technically qdisc_lookup()
> > doesn't require rtnl, and there was time it was used without it
> > (on xmit path).
>
>
> Hmm, for me, rcu_dereference_rtnl() is a bit lazy.
>
> Either we are a reader and should use rcu_dereference(), or a writer and
> RTNL should be held.
>
> Mixing two conditions in a "super macro" is a workaround that we used to
> promptly shutup some lockdep splats. Real fix would be to use strict
> lockdep conditions, because this better documents the code and the
> locking invariants.
>
> BTW, rtnl_dereference() should be changed to use
> rcu_dereference_protected() instead of rcu_dereference_check() :
> If RTBL is held, there is no need to force a barrier.
Actually, I'm one of those (convinced by Patrick btw), who consider
rcu_dereference() on the clear update side as misleading, so I'm not
rtnl_dereference() fan with or without changes.
>
>
> > I think you should also add a comment here why this rcu is used, and
> > that it changes only once in dev's liftime.
> >
>
> This comment was needed in the previous version of the patch, with the
> smb_wmb() barrier. Now I switched to regular rcu use, nothing prevents
> us to change dev->ingress_queue in flight. Of course there is no current
> interest doing so.
Right, but then at least in qdisc_lookup():
if (dev_ingress_queue(dev))
q = qdisc_match_from_root(dev_ingress_queue(dev), handle);
you should use a variable instead of the second dereference (rtnl isn't
mandatory here).
Jarek P.
^ permalink raw reply
* [patch] cls_u32: signedness bug
From: Dan Carpenter @ 2010-10-04 12:28 UTC (permalink / raw)
To: Jamal Hadi Salim
Cc: David S. Miller, Stephen Hemminger, Frans Pop, Changli Gao,
netdev, kernel-janitors
skb_headroom() is unsigned so "skb_headroom(skb) + toff" is also
unsigned and can't be less than zero. This test was added in 66d50d25:
"u32: negative offset fix" It was supposed to fix a regression.
Signed-off-by: Dan Carpenter <error27@gmail.com>
---
Compile tested only. Please check.
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index 7416a5c..b0c2a82 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -137,7 +137,7 @@ next_knode:
int toff = off + key->off + (off2 & key->offmask);
__be32 *data, _data;
- if (skb_headroom(skb) + toff < 0)
+ if (skb_headroom(skb) + toff > INT_MAX)
goto out;
data = skb_header_pointer(skb, toff, 4, &_data);
^ permalink raw reply related
* Re: [PATCH net-next V3] net: dynamic ingress_queue allocation
From: Eric Dumazet @ 2010-10-04 12:52 UTC (permalink / raw)
To: Jarek Poplawski; +Cc: hadi, David Miller, netdev
In-Reply-To: <20101004120626.GA2022@del.dom.local>
Le lundi 04 octobre 2010 à 14:06 +0200, Jarek Poplawski a écrit :
> Right, but then at least in qdisc_lookup():
>
> if (dev_ingress_queue(dev))
> q = qdisc_match_from_root(dev_ingress_queue(dev), handle);
>
> you should use a variable instead of the second dereference (rtnl isn't
> mandatory here).
I am lost.
If rntl is not mandatory, what is the lock that protects us ?
qdisc_lookup() _is_ called under the protection of a lock.
Or as soon as we return from it, result could change under us.
Please name it, and I'll use it :
rcu_dereference_protected(dev->ingress_queue, lockdep_is_held(THISLOCK))
^ permalink raw reply
* Re: [PATCH v2] bonding: rejoin multicast groups on VLANs
From: Andy Gospodarek @ 2010-10-04 13:24 UTC (permalink / raw)
To: Flavio Leitner; +Cc: netdev, Andy Gospodarek, bonding-devel, Jay Vosburgh
In-Reply-To: <1285879524-7046-1-git-send-email-fleitner@redhat.com>
On Thu, Sep 30, 2010 at 05:45:24PM -0300, Flavio Leitner wrote:
> It fixes bonding to rejoin multicast groups added
> to VLAN devices on top of bonding when a failover
> happens.
>
> Signed-off-by: Flavio Leitner <fleitner@redhat.com>
> ---
> drivers/net/bonding/bond_main.c | 61 +++++++++++++++++++++++++++++++++-----
> drivers/net/bonding/bonding.h | 1 +
> 2 files changed, 54 insertions(+), 8 deletions(-)
>
[...]
> @@ -944,7 +979,9 @@ static void bond_mc_swap(struct bonding *bond, struct slave *new_active,
>
> netdev_for_each_mc_addr(ha, bond->dev)
> dev_mc_add(new_active->dev, ha->addr);
> - bond_resend_igmp_join_requests(bond);
> +
> + /* rejoin multicast groups */
> + queue_delayed_work(bond->wq, &bond->mcast_work, 0);
> }
> }
>
I was hoping that one patch would just make the changes so
retransmission was supported on VLANs and the second patch would queue
the work and add the tunable for multiple retransmissions, but I guess
it wasn't clear enough.
I felt like that would divide the patches up into the bug-fix (VLANs +
multicast not working) and the new feature (multiple retransmissions
from the workqueue).
I will test these out this morning and make sure things look good.
^ permalink raw reply
* Re: [patch v4 10/12] IPVS: Allow configuration of persistence engines
From: Simon Horman @ 2010-10-04 13:41 UTC (permalink / raw)
To: lvs-devel, netdev, netfilter, netfilter-devel
Cc: Jan Engelhardt, Stephen Hemminger, Wensong Zhang,
Julian Anastasov, Patrick McHardy
In-Reply-To: <20101004090818.882956490@akiko.akashicho.tokyo.vergenet.net>
On Mon, Oct 04, 2010 at 06:04:02PM +0900, Simon Horman wrote:
> Allow the persistence engine of a virtual service to be set, edited
> and unset.
>
> This feature only works with the netlink user-space interface.
>
> Signed-off-by: Simon Horman <horms@verge.net.au>
> Acked-by: Julian Anastasov <ja@ssi.bg>
>
> ---
>
> v2
> * Dereference persistence engine when a service is deleted.
> This allows persistence modules to be removed from the kernel
> once they are no longer used.
> * Update for the recent "ipvs: changes related to service usecnt" change
> * Trivial rediff
>
> v4
> * As suggested by Julian Anastasov <ja@ssi.bg>
> - Initialise ip_vs_service_user_kern to zero in ip_vs_copy_usvc_compat()
> to avoid a crash caused by the pe_name element being uninitialised.
*Red Face*
I forgot to test this change and I had made a typo.
I will repost.
^ permalink raw reply
* [PATCH NEXT 2/9] qlcnic: fix eswitch stats
From: Amit Kumar Salecha @ 2010-10-04 13:45 UTC (permalink / raw)
To: davem; +Cc: netdev, ameen.rahman, anirban.chakraborty
In-Reply-To: <1286199938-17367-1-git-send-email-amit.salecha@qlogic.com>
Some of the counters are not implemented in fw.
Fw return NOT AVAILABLE VALUE as (0xffffffffffffffff).
Adding these counters, result in invalid value.
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
drivers/net/qlcnic/qlcnic.h | 12 ++++++++++++
drivers/net/qlcnic/qlcnic_ctx.c | 31 ++++++++++++++++++++++---------
2 files changed, 34 insertions(+), 9 deletions(-)
diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h
index 714ddf4..4667463 100644
--- a/drivers/net/qlcnic/qlcnic.h
+++ b/drivers/net/qlcnic/qlcnic.h
@@ -1169,6 +1169,18 @@ struct qlcnic_esw_func_cfg {
#define QLCNIC_STATS_ESWITCH 2
#define QLCNIC_QUERY_RX_COUNTER 0
#define QLCNIC_QUERY_TX_COUNTER 1
+#define QLCNIC_ESW_STATS_NOT_AVAIL 0xffffffffffffffffULL
+
+#define QLCNIC_ADD_ESW_STATS(VAL1, VAL2)\
+do { \
+ if (((VAL1) == QLCNIC_ESW_STATS_NOT_AVAIL) && \
+ ((VAL2) != QLCNIC_ESW_STATS_NOT_AVAIL)) \
+ (VAL1) = (VAL2); \
+ else if (((VAL1) != QLCNIC_ESW_STATS_NOT_AVAIL) && \
+ ((VAL2) != QLCNIC_ESW_STATS_NOT_AVAIL)) \
+ (VAL1) += (VAL2); \
+} while (0)
+
struct __qlcnic_esw_statistics {
__le16 context_id;
__le16 version;
diff --git a/drivers/net/qlcnic/qlcnic_ctx.c b/drivers/net/qlcnic/qlcnic_ctx.c
index 95a821e..a4c4d09 100644
--- a/drivers/net/qlcnic/qlcnic_ctx.c
+++ b/drivers/net/qlcnic/qlcnic_ctx.c
@@ -1016,7 +1016,14 @@ int qlcnic_get_eswitch_stats(struct qlcnic_adapter *adapter, const u8 eswitch,
if (adapter->npars == NULL)
return -EIO;
- memset(esw_stats, 0, sizeof(struct __qlcnic_esw_statistics));
+ memset(esw_stats, 0, sizeof(u64));
+ esw_stats->unicast_frames = QLCNIC_ESW_STATS_NOT_AVAIL;
+ esw_stats->multicast_frames = QLCNIC_ESW_STATS_NOT_AVAIL;
+ esw_stats->broadcast_frames = QLCNIC_ESW_STATS_NOT_AVAIL;
+ esw_stats->dropped_frames = QLCNIC_ESW_STATS_NOT_AVAIL;
+ esw_stats->errors = QLCNIC_ESW_STATS_NOT_AVAIL;
+ esw_stats->local_frames = QLCNIC_ESW_STATS_NOT_AVAIL;
+ esw_stats->numbytes = QLCNIC_ESW_STATS_NOT_AVAIL;
esw_stats->context_id = eswitch;
for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
@@ -1029,14 +1036,20 @@ int qlcnic_get_eswitch_stats(struct qlcnic_adapter *adapter, const u8 eswitch,
esw_stats->size = port_stats.size;
esw_stats->version = port_stats.version;
- esw_stats->unicast_frames += port_stats.unicast_frames;
- esw_stats->multicast_frames += port_stats.multicast_frames;
- esw_stats->broadcast_frames += port_stats.broadcast_frames;
- esw_stats->dropped_frames += port_stats.dropped_frames;
- esw_stats->errors += port_stats.errors;
- esw_stats->local_frames += port_stats.local_frames;
- esw_stats->numbytes += port_stats.numbytes;
-
+ QLCNIC_ADD_ESW_STATS(esw_stats->unicast_frames,
+ port_stats.unicast_frames);
+ QLCNIC_ADD_ESW_STATS(esw_stats->multicast_frames,
+ port_stats.multicast_frames);
+ QLCNIC_ADD_ESW_STATS(esw_stats->broadcast_frames,
+ port_stats.broadcast_frames);
+ QLCNIC_ADD_ESW_STATS(esw_stats->dropped_frames,
+ port_stats.dropped_frames);
+ QLCNIC_ADD_ESW_STATS(esw_stats->errors,
+ port_stats.errors);
+ QLCNIC_ADD_ESW_STATS(esw_stats->local_frames,
+ port_stats.local_frames);
+ QLCNIC_ADD_ESW_STATS(esw_stats->numbytes,
+ port_stats.numbytes);
ret = 0;
}
return ret;
--
1.6.0.2
^ permalink raw reply related
* [PATCH NEXT 4/9] qlcnic: support quiescent mode
From: Amit Kumar Salecha @ 2010-10-04 13:45 UTC (permalink / raw)
To: davem; +Cc: netdev, ameen.rahman, anirban.chakraborty
In-Reply-To: <1286199938-17367-1-git-send-email-amit.salecha@qlogic.com>
Put device in quiescent mode during internal loopback test.
Before running test, set state to NEED_QUISCENT. After getting
ack from all function, change state to QUISCENT and perform test.
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
drivers/net/qlcnic/qlcnic.h | 2 +
drivers/net/qlcnic/qlcnic_ethtool.c | 6 +++
drivers/net/qlcnic/qlcnic_main.c | 83 +++++++++++++++++++++++++++-------
3 files changed, 74 insertions(+), 17 deletions(-)
diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h
index 4667463..6e4150d 100644
--- a/drivers/net/qlcnic/qlcnic.h
+++ b/drivers/net/qlcnic/qlcnic.h
@@ -1302,6 +1302,8 @@ int qlcnic_set_ilb_mode(struct qlcnic_adapter *adapter);
void qlcnic_fetch_mac(struct qlcnic_adapter *, u32, u32, u8, u8 *);
/* Functions from qlcnic_main.c */
+int qlcnic_request_quiscent_mode(struct qlcnic_adapter *adapter);
+void qlcnic_clear_quiscent_mode(struct qlcnic_adapter *adapter);
int qlcnic_reset_context(struct qlcnic_adapter *);
u32 qlcnic_issue_cmd(struct qlcnic_adapter *adapter,
u32 pci_fn, u32 version, u32 arg1, u32 arg2, u32 arg3, u32 cmd);
diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c
index 6a76014..0181301 100644
--- a/drivers/net/qlcnic/qlcnic_ethtool.c
+++ b/drivers/net/qlcnic/qlcnic_ethtool.c
@@ -706,6 +706,11 @@ static int qlcnic_loopback_test(struct net_device *netdev)
if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
return -EIO;
+ if (qlcnic_request_quiscent_mode(adapter)) {
+ clear_bit(__QLCNIC_RESETTING, &adapter->state);
+ return -EIO;
+ }
+
ret = qlcnic_diag_alloc_res(netdev, QLCNIC_LOOPBACK_TEST);
if (ret)
goto clear_it;
@@ -722,6 +727,7 @@ done:
qlcnic_diag_free_res(netdev, max_sds_rings);
clear_it:
+ qlcnic_clear_quiscent_mode(adapter);
adapter->max_sds_rings = max_sds_rings;
clear_bit(__QLCNIC_RESETTING, &adapter->state);
return ret;
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index a3d7705..33fe4d4 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -2746,7 +2746,8 @@ qlcnic_fwinit_work(struct work_struct *work)
goto err_ret;
dev_state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
- if (dev_state == QLCNIC_DEV_QUISCENT) {
+ if (dev_state == QLCNIC_DEV_QUISCENT ||
+ dev_state == QLCNIC_DEV_NEED_QUISCENT) {
qlcnic_api_unlock(adapter);
qlcnic_schedule_work(adapter, qlcnic_fwinit_work,
FW_POLL_DELAY * 2);
@@ -2768,18 +2769,6 @@ qlcnic_fwinit_work(struct work_struct *work)
skip_ack_check:
dev_state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
- if (dev_state == QLCNIC_DEV_NEED_QUISCENT) {
- QLCWR32(adapter, QLCNIC_CRB_DEV_STATE,
- QLCNIC_DEV_QUISCENT);
- qlcnic_schedule_work(adapter, qlcnic_fwinit_work,
- FW_POLL_DELAY * 2);
- QLCDB(adapter, DRV, "Quiscing the driver\n");
- qlcnic_idc_debug_info(adapter, 0);
-
- qlcnic_api_unlock(adapter);
- return;
- }
-
if (dev_state == QLCNIC_DEV_NEED_RESET) {
QLCWR32(adapter, QLCNIC_CRB_DEV_STATE,
QLCNIC_DEV_INITIALIZING);
@@ -2836,7 +2825,12 @@ qlcnic_detach_work(struct work_struct *work)
netif_device_detach(netdev);
- qlcnic_down(adapter, netdev);
+ /* Dont grab rtnl lock during Quiscent mode */
+ if (adapter->dev_state == QLCNIC_DEV_NEED_QUISCENT) {
+ if (netif_running(netdev))
+ __qlcnic_down(adapter, netdev);
+ } else
+ qlcnic_down(adapter, netdev);
status = QLCRD32(adapter, QLCNIC_PEG_HALT_STATUS1);
@@ -2878,6 +2872,61 @@ qlcnic_set_npar_non_operational(struct qlcnic_adapter *adapter)
qlcnic_api_unlock(adapter);
}
+/* Caller should held RESETTING bit.
+ * This should be call in sync with qlcnic_request_quiscent_mode.
+ */
+void qlcnic_clear_quiscent_mode(struct qlcnic_adapter *adapter)
+{
+ qlcnic_clr_drv_state(adapter);
+ qlcnic_api_lock(adapter);
+ QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_READY);
+ qlcnic_api_unlock(adapter);
+}
+
+/* Caller should held RESETTING bit.
+ */
+int qlcnic_request_quiscent_mode(struct qlcnic_adapter *adapter)
+{
+ u8 timeo = adapter->dev_init_timeo / 2;
+ u32 state;
+
+ if (qlcnic_api_lock(adapter))
+ return -EIO;
+
+ state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
+ if (state != QLCNIC_DEV_READY)
+ return -EIO;
+
+ QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_NEED_QUISCENT);
+ qlcnic_api_unlock(adapter);
+ QLCDB(adapter, DRV, "NEED QUISCENT state set\n");
+ qlcnic_idc_debug_info(adapter, 0);
+
+ qlcnic_set_drv_state(adapter, QLCNIC_DEV_NEED_QUISCENT);
+
+ do {
+ msleep(2000);
+ state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
+ if (state == QLCNIC_DEV_QUISCENT)
+ return 0;
+ if (!qlcnic_check_drv_state(adapter)) {
+ if (qlcnic_api_lock(adapter))
+ return -EIO;
+ QLCWR32(adapter, QLCNIC_CRB_DEV_STATE,
+ QLCNIC_DEV_QUISCENT);
+ qlcnic_api_unlock(adapter);
+ QLCDB(adapter, DRV, "QUISCENT mode set\n");
+ return 0;
+ }
+ } while (--timeo);
+
+ dev_err(&adapter->pdev->dev, "Failed to quiesce device, DRV_STATE=%08x"
+ " DRV_ACTIVE=%08x\n", QLCRD32(adapter, QLCNIC_CRB_DRV_STATE),
+ QLCRD32(adapter, QLCNIC_CRB_DRV_ACTIVE));
+ qlcnic_clear_quiscent_mode(adapter);
+ return -EIO;
+}
+
/*Transit to RESET state from READY state only */
static void
qlcnic_dev_request_reset(struct qlcnic_adapter *adapter)
@@ -2984,11 +3033,11 @@ qlcnic_check_health(struct qlcnic_adapter *adapter)
qlcnic_dev_request_reset(adapter);
state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
- if (state == QLCNIC_DEV_NEED_RESET ||
- state == QLCNIC_DEV_NEED_QUISCENT) {
+ if (state == QLCNIC_DEV_NEED_RESET) {
qlcnic_set_npar_non_operational(adapter);
adapter->need_fw_reset = 1;
- }
+ } else if (state == QLCNIC_DEV_NEED_QUISCENT)
+ goto detach;
heartbeat = QLCRD32(adapter, QLCNIC_PEG_ALIVE_COUNTER);
if (heartbeat != adapter->heartbeat) {
--
1.6.0.2
^ permalink raw reply related
* [PATCH 0/9]qlcnic: miscellaneous fixes
From: Amit Kumar Salecha @ 2010-10-04 13:45 UTC (permalink / raw)
To: davem; +Cc: netdev, ameen.rahman, anirban.chakraborty
Hi
Series of 9 patches to fix endianesses for PPC, internal loopback test
and etc.
Please apply them on net-next.
-Amit
^ permalink raw reply
* [PATCH NEXT 1/9] qlcnic: fix internal loopback test
From: Amit Kumar Salecha @ 2010-10-04 13:45 UTC (permalink / raw)
To: davem; +Cc: netdev, ameen.rahman, anirban.chakraborty
In-Reply-To: <1286199938-17367-1-git-send-email-amit.salecha@qlogic.com>
o Loop 10 times with delay of 1 ms to rcv packet.
o Print garbage packet.
o Try send/receive MAX(16) packet, instead of exit from test,
if a packet is not received.
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
drivers/net/qlcnic/qlcnic_ethtool.c | 26 +++++++++++++++++++-------
drivers/net/qlcnic/qlcnic_init.c | 19 ++++++++++++++++++-
2 files changed, 37 insertions(+), 8 deletions(-)
diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c
index cb9463b..550cfe9 100644
--- a/drivers/net/qlcnic/qlcnic_ethtool.c
+++ b/drivers/net/qlcnic/qlcnic_ethtool.c
@@ -636,6 +636,8 @@ static int qlcnic_get_sset_count(struct net_device *dev, int sset)
}
#define QLC_ILB_PKT_SIZE 64
+#define QLC_NUM_ILB_PKT 16
+#define QLC_ILB_MAX_RCV_LOOP 10
static void qlcnic_create_loopback_buff(unsigned char *data)
{
@@ -657,24 +659,34 @@ static int qlcnic_do_ilb_test(struct qlcnic_adapter *adapter)
struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx;
struct qlcnic_host_sds_ring *sds_ring = &recv_ctx->sds_rings[0];
struct sk_buff *skb;
- int i;
+ int i, loop, cnt = 0;
- for (i = 0; i < 16; i++) {
+ for (i = 0; i < QLC_NUM_ILB_PKT; i++) {
skb = dev_alloc_skb(QLC_ILB_PKT_SIZE);
qlcnic_create_loopback_buff(skb->data);
skb_put(skb, QLC_ILB_PKT_SIZE);
adapter->diag_cnt = 0;
-
qlcnic_xmit_frame(skb, adapter->netdev);
- msleep(5);
-
- qlcnic_process_rcv_ring_diag(sds_ring);
+ loop = 0;
+ do {
+ msleep(1);
+ qlcnic_process_rcv_ring_diag(sds_ring);
+ } while (loop++ < QLC_ILB_MAX_RCV_LOOP &&
+ !adapter->diag_cnt);
dev_kfree_skb_any(skb);
+
if (!adapter->diag_cnt)
- return -1;
+ dev_warn(&adapter->pdev->dev, "ILB Test: %dth packet"
+ " not recevied\n", i + 1);
+ else
+ cnt++;
+ }
+ if (cnt != i) {
+ dev_warn(&adapter->pdev->dev, "ILB Test failed\n");
+ return -1;
}
return 0;
}
diff --git a/drivers/net/qlcnic/qlcnic_init.c b/drivers/net/qlcnic/qlcnic_init.c
index 5c33d15..908a25b 100644
--- a/drivers/net/qlcnic/qlcnic_init.c
+++ b/drivers/net/qlcnic/qlcnic_init.c
@@ -1693,6 +1693,18 @@ qlcnic_post_rx_buffers_nodb(struct qlcnic_adapter *adapter,
spin_unlock(&rds_ring->lock);
}
+static void dump_skb(struct sk_buff *skb)
+{
+ int i;
+ unsigned char *data = skb->data;
+
+ for (i = 0; i < skb->len; i++) {
+ printk("%02x ", data[i]);
+ if ((i & 0x0f) == 8)
+ printk("\n");
+ }
+}
+
static struct qlcnic_rx_buffer *
qlcnic_process_rcv_diag(struct qlcnic_adapter *adapter,
struct qlcnic_host_sds_ring *sds_ring,
@@ -1723,13 +1735,18 @@ qlcnic_process_rcv_diag(struct qlcnic_adapter *adapter,
if (!skb)
return buffer;
- skb_put(skb, rds_ring->skb_size);
+ if (length > rds_ring->skb_size)
+ skb_put(skb, rds_ring->skb_size);
+ else
+ skb_put(skb, length);
if (pkt_offset)
skb_pull(skb, pkt_offset);
if (!qlcnic_check_loopback_buff(skb->data))
adapter->diag_cnt++;
+ else
+ dump_skb(skb);
dev_kfree_skb_any(skb);
adapter->stats.rx_pkts++;
--
1.6.0.2
^ permalink raw reply related
* [PATCH NEXT 3/9] qlcnic: fix diag register
From: Amit Kumar Salecha @ 2010-10-04 13:45 UTC (permalink / raw)
To: davem; +Cc: netdev, ameen.rahman, anirban.chakraborty
In-Reply-To: <1286199938-17367-1-git-send-email-amit.salecha@qlogic.com>
regs_buff[i] and diag_registers[j] array should use different index
variable.
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
drivers/net/qlcnic/qlcnic_ethtool.c | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c
index 550cfe9..6a76014 100644
--- a/drivers/net/qlcnic/qlcnic_ethtool.c
+++ b/drivers/net/qlcnic/qlcnic_ethtool.c
@@ -343,7 +343,7 @@ qlcnic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx;
struct qlcnic_host_sds_ring *sds_ring;
u32 *regs_buff = p;
- int ring, i = 0;
+ int ring, i = 0, j = 0;
memset(p, 0, qlcnic_get_regs_len(dev));
regs->version = (QLCNIC_ETHTOOL_REGS_VER << 24) |
@@ -352,8 +352,8 @@ qlcnic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
regs_buff[0] = (0xcafe0000 | (QLCNIC_DEV_INFO_SIZE & 0xffff));
regs_buff[1] = QLCNIC_MGMT_API_VERSION;
- for (i = QLCNIC_DEV_INFO_SIZE + 1; diag_registers[i] != -1; i++)
- regs_buff[i] = QLCRD32(adapter, diag_registers[i]);
+ for (i = QLCNIC_DEV_INFO_SIZE + 1; diag_registers[j] != -1; j++, i++)
+ regs_buff[i] = QLCRD32(adapter, diag_registers[j]);
if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
return;
--
1.6.0.2
^ permalink raw reply related
* [PATCH NEXT 6/9] qlcnic: fix vlan TSO on big endian machine
From: Amit Kumar Salecha @ 2010-10-04 13:45 UTC (permalink / raw)
To: davem; +Cc: netdev, ameen.rahman, anirban.chakraborty, Sucheta Chakraborty
In-Reply-To: <1286199938-17367-1-git-send-email-amit.salecha@qlogic.com>
From: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com>
o desc->vlan_tci is in __le16 format. Doing htons and
cpu_to_le64 again on vlan_tci, result in invalid value on ppc.
Signed-off-by: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com>
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
drivers/net/qlcnic/qlcnic.h | 7 ++++++-
drivers/net/qlcnic/qlcnic_hw.c | 6 ++++--
drivers/net/qlcnic/qlcnic_main.c | 15 ++++++++++-----
3 files changed, 20 insertions(+), 8 deletions(-)
diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h
index 610c17a..a1bb1d8 100644
--- a/drivers/net/qlcnic/qlcnic.h
+++ b/drivers/net/qlcnic/qlcnic.h
@@ -898,6 +898,11 @@ struct qlcnic_mac_req {
u8 mac_addr[6];
};
+struct qlcnic_vlan_req {
+ __le16 vlan_id;
+ __le16 rsvd[3];
+};
+
struct qlcnic_ipaddr {
__be32 ipv4;
__be32 ipv6[4];
@@ -940,7 +945,7 @@ struct qlcnic_ipaddr {
struct qlcnic_filter {
struct hlist_node fnode;
u8 faddr[ETH_ALEN];
- u16 vlan_id;
+ __le16 vlan_id;
unsigned long ftime;
};
diff --git a/drivers/net/qlcnic/qlcnic_hw.c b/drivers/net/qlcnic/qlcnic_hw.c
index 68d5693..712cfab 100644
--- a/drivers/net/qlcnic/qlcnic_hw.c
+++ b/drivers/net/qlcnic/qlcnic_hw.c
@@ -375,10 +375,11 @@ qlcnic_send_cmd_descs(struct qlcnic_adapter *adapter,
static int
qlcnic_sre_macaddr_change(struct qlcnic_adapter *adapter, u8 *addr,
- u16 vlan_id, unsigned op)
+ __le16 vlan_id, unsigned op)
{
struct qlcnic_nic_req req;
struct qlcnic_mac_req *mac_req;
+ struct qlcnic_vlan_req *vlan_req;
u64 word;
memset(&req, 0, sizeof(struct qlcnic_nic_req));
@@ -391,7 +392,8 @@ qlcnic_sre_macaddr_change(struct qlcnic_adapter *adapter, u8 *addr,
mac_req->op = op;
memcpy(mac_req->mac_addr, addr, 6);
- req.words[1] = cpu_to_le64(vlan_id);
+ vlan_req = (struct qlcnic_vlan_req *)&req.words[1];
+ vlan_req->vlan_id = vlan_id;
return qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
}
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index 33fe4d4..6146f6a 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -28,6 +28,7 @@
#include "qlcnic.h"
+#include <linux/swab.h>
#include <linux/dma-mapping.h>
#include <linux/if_vlan.h>
#include <net/ip.h>
@@ -1834,11 +1835,12 @@ static void qlcnic_free_lb_filters_mem(struct qlcnic_adapter *adapter)
}
static void qlcnic_change_filter(struct qlcnic_adapter *adapter,
- u64 uaddr, u16 vlan_id, struct qlcnic_host_tx_ring *tx_ring)
+ u64 uaddr, __le16 vlan_id, struct qlcnic_host_tx_ring *tx_ring)
{
struct cmd_desc_type0 *hwdesc;
struct qlcnic_nic_req *req;
struct qlcnic_mac_req *mac_req;
+ struct qlcnic_vlan_req *vlan_req;
u32 producer;
u64 word;
@@ -1856,7 +1858,8 @@ static void qlcnic_change_filter(struct qlcnic_adapter *adapter,
mac_req->op = vlan_id ? QLCNIC_MAC_VLAN_ADD : QLCNIC_MAC_ADD;
memcpy(mac_req->mac_addr, &uaddr, ETH_ALEN);
- req->words[1] = cpu_to_le64(vlan_id);
+ vlan_req = (struct qlcnic_vlan_req *)&req->words[1];
+ vlan_req->vlan_id = vlan_id;
tx_ring->producer = get_next_index(producer, tx_ring->num_desc);
}
@@ -1875,7 +1878,7 @@ qlcnic_send_filter(struct qlcnic_adapter *adapter,
struct hlist_node *tmp_hnode, *n;
struct hlist_head *head;
u64 src_addr = 0;
- u16 vlan_id = 0;
+ __le16 vlan_id = 0;
u8 hindex;
if (!compare_ether_addr(phdr->h_source, adapter->mac_addr))
@@ -1928,7 +1931,8 @@ qlcnic_tso_check(struct net_device *netdev,
struct vlan_ethhdr *vh;
struct qlcnic_adapter *adapter = netdev_priv(netdev);
u32 producer = tx_ring->producer;
- int vlan_oob = first_desc->flags_opcode & cpu_to_le16(FLAGS_VLAN_OOB);
+ __le16 vlan_oob = first_desc->flags_opcode &
+ cpu_to_le16(FLAGS_VLAN_OOB);
if (*(skb->data) & BIT_0) {
flags |= BIT_0;
@@ -1999,7 +2003,8 @@ qlcnic_tso_check(struct net_device *netdev,
vh = (struct vlan_ethhdr *)((char *)hwdesc + 2);
skb_copy_from_linear_data(skb, vh, 12);
vh->h_vlan_proto = htons(ETH_P_8021Q);
- vh->h_vlan_TCI = htons(first_desc->vlan_TCI);
+ vh->h_vlan_TCI = (__be16)swab16((u16)first_desc->vlan_TCI);
+
skb_copy_from_linear_data_offset(skb, 12,
(char *)vh + 16, copy_len - 16);
--
1.6.0.2
^ permalink raw reply related
* [PATCH NEXT 5/9] qlcnic: fix endianess for lro
From: Amit Kumar Salecha @ 2010-10-04 13:45 UTC (permalink / raw)
To: davem; +Cc: netdev, ameen.rahman, anirban.chakraborty, Sucheta Chakraborty
In-Reply-To: <1286199938-17367-1-git-send-email-amit.salecha@qlogic.com>
From: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com>
ipaddress in ifa->ifa_address field are in big endian format.
Also device requires ip address in big endian only.
Signed-off-by: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com>
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
drivers/net/qlcnic/qlcnic.h | 7 ++++++-
drivers/net/qlcnic/qlcnic_hw.c | 6 ++++--
2 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h
index 6e4150d..610c17a 100644
--- a/drivers/net/qlcnic/qlcnic.h
+++ b/drivers/net/qlcnic/qlcnic.h
@@ -898,6 +898,11 @@ struct qlcnic_mac_req {
u8 mac_addr[6];
};
+struct qlcnic_ipaddr {
+ __be32 ipv4;
+ __be32 ipv6[4];
+};
+
#define QLCNIC_MSI_ENABLED 0x02
#define QLCNIC_MSIX_ENABLED 0x04
#define QLCNIC_LRO_ENABLED 0x08
@@ -1286,7 +1291,7 @@ void qlcnic_free_mac_list(struct qlcnic_adapter *adapter);
int qlcnic_nic_set_promisc(struct qlcnic_adapter *adapter, u32);
int qlcnic_config_intr_coalesce(struct qlcnic_adapter *adapter);
int qlcnic_config_rss(struct qlcnic_adapter *adapter, int enable);
-int qlcnic_config_ipaddr(struct qlcnic_adapter *adapter, u32 ip, int cmd);
+int qlcnic_config_ipaddr(struct qlcnic_adapter *adapter, __be32 ip, int cmd);
int qlcnic_linkevent_request(struct qlcnic_adapter *adapter, int enable);
void qlcnic_advert_link_change(struct qlcnic_adapter *adapter, int linkup);
diff --git a/drivers/net/qlcnic/qlcnic_hw.c b/drivers/net/qlcnic/qlcnic_hw.c
index c198df9..68d5693 100644
--- a/drivers/net/qlcnic/qlcnic_hw.c
+++ b/drivers/net/qlcnic/qlcnic_hw.c
@@ -676,9 +676,10 @@ int qlcnic_config_rss(struct qlcnic_adapter *adapter, int enable)
return rv;
}
-int qlcnic_config_ipaddr(struct qlcnic_adapter *adapter, u32 ip, int cmd)
+int qlcnic_config_ipaddr(struct qlcnic_adapter *adapter, __be32 ip, int cmd)
{
struct qlcnic_nic_req req;
+ struct qlcnic_ipaddr *ipa;
u64 word;
int rv;
@@ -689,7 +690,8 @@ int qlcnic_config_ipaddr(struct qlcnic_adapter *adapter, u32 ip, int cmd)
req.req_hdr = cpu_to_le64(word);
req.words[0] = cpu_to_le64(cmd);
- req.words[1] = cpu_to_le64(ip);
+ ipa = (struct qlcnic_ipaddr *)&req.words[1];
+ ipa->ipv4 = ip;
rv = qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
if (rv != 0)
--
1.6.0.2
^ permalink raw reply related
* [PATCH NEXT 8/9] qlcnic: cleanup port mode setting
From: Amit Kumar Salecha @ 2010-10-04 13:45 UTC (permalink / raw)
To: davem; +Cc: netdev, ameen.rahman, anirban.chakraborty, Sritej Velaga
In-Reply-To: <1286199938-17367-1-git-send-email-amit.salecha@qlogic.com>
From: Sritej Velaga <sritej.velaga@qlogic.com>
Port mode setting is not required for Qlogic CNA adapters.
Signed-off-by: Sritej Velaga <sritej.velaga@qlogic.com>
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
drivers/net/qlcnic/qlcnic_main.c | 40 --------------------------------------
1 files changed, 0 insertions(+), 40 deletions(-)
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index b689d1b..ce830c9 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -46,11 +46,6 @@ char qlcnic_driver_name[] = "qlcnic";
static const char qlcnic_driver_string[] = "QLogic 1/10 GbE "
"Converged/Intelligent Ethernet Driver v" QLCNIC_LINUX_VERSIONID;
-static int port_mode = QLCNIC_PORT_MODE_AUTO_NEG;
-
-/* Default to restricted 1G auto-neg mode */
-static int wol_port_mode = 5;
-
static int qlcnic_mac_learn;
module_param(qlcnic_mac_learn, int, 0644);
MODULE_PARM_DESC(qlcnic_mac_learn, "Mac Filter (0=disabled, 1=enabled)");
@@ -264,40 +259,6 @@ static void qlcnic_clear_stats(struct qlcnic_adapter *adapter)
memset(&adapter->stats, 0, sizeof(adapter->stats));
}
-static void qlcnic_set_port_mode(struct qlcnic_adapter *adapter)
-{
- u32 val, data;
-
- val = adapter->ahw.board_type;
- if ((val == QLCNIC_BRDTYPE_P3_HMEZ) ||
- (val == QLCNIC_BRDTYPE_P3_XG_LOM)) {
- if (port_mode == QLCNIC_PORT_MODE_802_3_AP) {
- data = QLCNIC_PORT_MODE_802_3_AP;
- QLCWR32(adapter, QLCNIC_PORT_MODE_ADDR, data);
- } else if (port_mode == QLCNIC_PORT_MODE_XG) {
- data = QLCNIC_PORT_MODE_XG;
- QLCWR32(adapter, QLCNIC_PORT_MODE_ADDR, data);
- } else if (port_mode == QLCNIC_PORT_MODE_AUTO_NEG_1G) {
- data = QLCNIC_PORT_MODE_AUTO_NEG_1G;
- QLCWR32(adapter, QLCNIC_PORT_MODE_ADDR, data);
- } else if (port_mode == QLCNIC_PORT_MODE_AUTO_NEG_XG) {
- data = QLCNIC_PORT_MODE_AUTO_NEG_XG;
- QLCWR32(adapter, QLCNIC_PORT_MODE_ADDR, data);
- } else {
- data = QLCNIC_PORT_MODE_AUTO_NEG;
- QLCWR32(adapter, QLCNIC_PORT_MODE_ADDR, data);
- }
-
- if ((wol_port_mode != QLCNIC_PORT_MODE_802_3_AP) &&
- (wol_port_mode != QLCNIC_PORT_MODE_XG) &&
- (wol_port_mode != QLCNIC_PORT_MODE_AUTO_NEG_1G) &&
- (wol_port_mode != QLCNIC_PORT_MODE_AUTO_NEG_XG)) {
- wol_port_mode = QLCNIC_PORT_MODE_AUTO_NEG;
- }
- QLCWR32(adapter, QLCNIC_WOL_PORT_MODE, wol_port_mode);
- }
-}
-
static void qlcnic_set_msix_bit(struct pci_dev *pdev, int enable)
{
u32 control;
@@ -1032,7 +993,6 @@ qlcnic_start_firmware(struct qlcnic_adapter *adapter)
err = qlcnic_pinit_from_rom(adapter);
if (err)
goto err_out;
- qlcnic_set_port_mode(adapter);
err = qlcnic_load_firmware(adapter);
if (err)
--
1.6.0.2
^ permalink raw reply related
* [PATCH NEXT 9/9] qlcnic: set mtu lower limit
From: Amit Kumar Salecha @ 2010-10-04 13:45 UTC (permalink / raw)
To: davem; +Cc: netdev, ameen.rahman, anirban.chakraborty, Sritej Velaga
In-Reply-To: <1286199938-17367-1-git-send-email-amit.salecha@qlogic.com>
From: Sritej Velaga <sritej.velaga@qlogic.com>
Setting mtu < 68 is not supported.
Signed-off-by: Sritej Velaga <sritej.velaga@qlogic.com>
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
drivers/net/qlcnic/qlcnic.h | 1 +
drivers/net/qlcnic/qlcnic_hw.c | 6 +++---
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h
index a1bb1d8..6636a33 100644
--- a/drivers/net/qlcnic/qlcnic.h
+++ b/drivers/net/qlcnic/qlcnic.h
@@ -95,6 +95,7 @@
#define FIRST_PAGE_GROUP_END 0x100000
#define P3_MAX_MTU (9600)
+#define P3_MIN_MTU (68)
#define QLCNIC_MAX_ETHERHDR 32 /* This contains some padding */
#define QLCNIC_P3_RX_BUF_MAX_LEN (QLCNIC_MAX_ETHERHDR + ETH_DATA_LEN)
diff --git a/drivers/net/qlcnic/qlcnic_hw.c b/drivers/net/qlcnic/qlcnic_hw.c
index 712cfab..9d3e16d 100644
--- a/drivers/net/qlcnic/qlcnic_hw.c
+++ b/drivers/net/qlcnic/qlcnic_hw.c
@@ -758,9 +758,9 @@ int qlcnic_change_mtu(struct net_device *netdev, int mtu)
struct qlcnic_adapter *adapter = netdev_priv(netdev);
int rc = 0;
- if (mtu > P3_MAX_MTU) {
- dev_err(&adapter->netdev->dev, "mtu > %d bytes unsupported\n",
- P3_MAX_MTU);
+ if (mtu < P3_MIN_MTU || mtu > P3_MAX_MTU) {
+ dev_err(&adapter->netdev->dev, "%d bytes < mtu < %d bytes"
+ " not supported\n", P3_MAX_MTU, P3_MIN_MTU);
return -EINVAL;
}
--
1.6.0.2
^ permalink raw reply related
* [PATCH NEXT 7/9] qlcnic: sparse warning fixes
From: Amit Kumar Salecha @ 2010-10-04 13:45 UTC (permalink / raw)
To: davem; +Cc: netdev, ameen.rahman, anirban.chakraborty, Sucheta Chakraborty
In-Reply-To: <1286199938-17367-1-git-send-email-amit.salecha@qlogic.com>
From: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com>
Signed-off-by: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com>
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
drivers/net/qlcnic/qlcnic_ctx.c | 12 ++++++------
drivers/net/qlcnic/qlcnic_main.c | 10 +++++-----
2 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/drivers/net/qlcnic/qlcnic_ctx.c b/drivers/net/qlcnic/qlcnic_ctx.c
index a4c4d09..75e3b19 100644
--- a/drivers/net/qlcnic/qlcnic_ctx.c
+++ b/drivers/net/qlcnic/qlcnic_ctx.c
@@ -742,15 +742,15 @@ int qlcnic_get_pci_info(struct qlcnic_adapter *adapter,
if (err == QLCNIC_RCODE_SUCCESS) {
for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++, npar++, pci_info++) {
- pci_info->id = le32_to_cpu(npar->id);
- pci_info->active = le32_to_cpu(npar->active);
- pci_info->type = le32_to_cpu(npar->type);
+ pci_info->id = le16_to_cpu(npar->id);
+ pci_info->active = le16_to_cpu(npar->active);
+ pci_info->type = le16_to_cpu(npar->type);
pci_info->default_port =
- le32_to_cpu(npar->default_port);
+ le16_to_cpu(npar->default_port);
pci_info->tx_min_bw =
- le32_to_cpu(npar->tx_min_bw);
+ le16_to_cpu(npar->tx_min_bw);
pci_info->tx_max_bw =
- le32_to_cpu(npar->tx_max_bw);
+ le16_to_cpu(npar->tx_max_bw);
memcpy(pci_info->mac, npar->mac, ETH_ALEN);
}
} else {
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index 6146f6a..b689d1b 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -521,9 +521,9 @@ qlcnic_init_pci_info(struct qlcnic_adapter *adapter)
pfn = pci_info[i].id;
if (pfn > QLCNIC_MAX_PCI_FUNC)
return QL_STATUS_INVALID_PARAM;
- adapter->npars[pfn].active = pci_info[i].active;
- adapter->npars[pfn].type = pci_info[i].type;
- adapter->npars[pfn].phy_port = pci_info[i].default_port;
+ adapter->npars[pfn].active = (u8)pci_info[i].active;
+ adapter->npars[pfn].type = (u8)pci_info[i].type;
+ adapter->npars[pfn].phy_port = (u8)pci_info[i].default_port;
adapter->npars[pfn].min_bw = pci_info[i].tx_min_bw;
adapter->npars[pfn].max_bw = pci_info[i].tx_max_bw;
}
@@ -723,7 +723,7 @@ qlcnic_initialize_nic(struct qlcnic_adapter *adapter)
if (err)
return err;
- adapter->physical_port = nic_info.phys_port;
+ adapter->physical_port = (u8)nic_info.phys_port;
adapter->switch_mode = nic_info.switch_mode;
adapter->max_tx_ques = nic_info.max_tx_ques;
adapter->max_rx_ques = nic_info.max_rx_ques;
@@ -3811,7 +3811,7 @@ qlcnic_sysfs_read_npar_config(struct file *file, struct kobject *kobj,
return ret;
np_cfg[i].pci_func = i;
- np_cfg[i].op_mode = nic_info.op_mode;
+ np_cfg[i].op_mode = (u8)nic_info.op_mode;
np_cfg[i].port_num = nic_info.phys_port;
np_cfg[i].fw_capab = nic_info.capabilities;
np_cfg[i].min_bw = nic_info.min_tx_bw ;
--
1.6.0.2
^ permalink raw reply related
* [PATCH NEXT 8/9] qlcnic: cleanup port mode
From: Amit Kumar Salecha @ 2010-10-04 13:45 UTC (permalink / raw)
To: davem; +Cc: netdev, ameen.rahman, anirban.chakraborty, Sritej Velaga
In-Reply-To: <1286199938-17367-1-git-send-email-amit.salecha@qlogic.com>
From: Sritej Velaga <sritej.velaga@qlogic.com>
Note:Port mode is set by default to Auto neg in firmware.
Signed-off-by: Sritej Velaga <sritej.velaga@qlogic.com>
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
drivers/net/qlcnic/qlcnic_main.c | 40 --------------------------------------
1 files changed, 0 insertions(+), 40 deletions(-)
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index b689d1b..ce830c9 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -46,11 +46,6 @@ char qlcnic_driver_name[] = "qlcnic";
static const char qlcnic_driver_string[] = "QLogic 1/10 GbE "
"Converged/Intelligent Ethernet Driver v" QLCNIC_LINUX_VERSIONID;
-static int port_mode = QLCNIC_PORT_MODE_AUTO_NEG;
-
-/* Default to restricted 1G auto-neg mode */
-static int wol_port_mode = 5;
-
static int qlcnic_mac_learn;
module_param(qlcnic_mac_learn, int, 0644);
MODULE_PARM_DESC(qlcnic_mac_learn, "Mac Filter (0=disabled, 1=enabled)");
@@ -264,40 +259,6 @@ static void qlcnic_clear_stats(struct qlcnic_adapter *adapter)
memset(&adapter->stats, 0, sizeof(adapter->stats));
}
-static void qlcnic_set_port_mode(struct qlcnic_adapter *adapter)
-{
- u32 val, data;
-
- val = adapter->ahw.board_type;
- if ((val == QLCNIC_BRDTYPE_P3_HMEZ) ||
- (val == QLCNIC_BRDTYPE_P3_XG_LOM)) {
- if (port_mode == QLCNIC_PORT_MODE_802_3_AP) {
- data = QLCNIC_PORT_MODE_802_3_AP;
- QLCWR32(adapter, QLCNIC_PORT_MODE_ADDR, data);
- } else if (port_mode == QLCNIC_PORT_MODE_XG) {
- data = QLCNIC_PORT_MODE_XG;
- QLCWR32(adapter, QLCNIC_PORT_MODE_ADDR, data);
- } else if (port_mode == QLCNIC_PORT_MODE_AUTO_NEG_1G) {
- data = QLCNIC_PORT_MODE_AUTO_NEG_1G;
- QLCWR32(adapter, QLCNIC_PORT_MODE_ADDR, data);
- } else if (port_mode == QLCNIC_PORT_MODE_AUTO_NEG_XG) {
- data = QLCNIC_PORT_MODE_AUTO_NEG_XG;
- QLCWR32(adapter, QLCNIC_PORT_MODE_ADDR, data);
- } else {
- data = QLCNIC_PORT_MODE_AUTO_NEG;
- QLCWR32(adapter, QLCNIC_PORT_MODE_ADDR, data);
- }
-
- if ((wol_port_mode != QLCNIC_PORT_MODE_802_3_AP) &&
- (wol_port_mode != QLCNIC_PORT_MODE_XG) &&
- (wol_port_mode != QLCNIC_PORT_MODE_AUTO_NEG_1G) &&
- (wol_port_mode != QLCNIC_PORT_MODE_AUTO_NEG_XG)) {
- wol_port_mode = QLCNIC_PORT_MODE_AUTO_NEG;
- }
- QLCWR32(adapter, QLCNIC_WOL_PORT_MODE, wol_port_mode);
- }
-}
-
static void qlcnic_set_msix_bit(struct pci_dev *pdev, int enable)
{
u32 control;
@@ -1032,7 +993,6 @@ qlcnic_start_firmware(struct qlcnic_adapter *adapter)
err = qlcnic_pinit_from_rom(adapter);
if (err)
goto err_out;
- qlcnic_set_port_mode(adapter);
err = qlcnic_load_firmware(adapter);
if (err)
--
1.6.0.2
^ permalink raw reply related
* [patch v5 00/12] IPVS: SIP Persistence Engine
From: Simon Horman @ 2010-10-04 13:46 UTC (permalink / raw)
To: lvs-devel, netdev, netfilter, netfilter-devel
Cc: Jan Engelhardt, Stephen Hemminger, Wensong Zhang,
Julian Anastasov, Patrick McHardy
This patch series adds load-balancing of UDP SIP based on Call-ID to
IPVS as well as a frame-work for extending IPVS to handle alternate
persistence requirements.
REVISIONS
This is v5 of the patch series which fixes a typo introduced in v4.
v4 of the patch series which addressed the following concerns
raised by Julian Anastasov:
- initialize compat structures to avoid crash in
ip_vs_add_service for pe_name
- fix ip_vs_conn_out_get_proto to properly check the
ip_vs_conn_fill_param_proto result
These changes and changes from previous revisions of this patch series
are noted on a per-patch basis.
I have taken the liberty of including Acked-by: Julian Anastasov <ja@ssi.bg>
although the ack was provided before the v4 and v5 above were discovered.
OVERVIEW
The approach that I have taken is what I call persistence engines.
The basic idea being that you can provide a module to LVS that alters
the way that it handles connection templates, which are at the core
of persistence. In particular, an additional key can be added, and
any of the normal IP address, port and protocol information can either
be used or ignored.
In the case of the SIP persistence engine, the only persistence engine, all
the keys used by the default persistence behaviour are used and the callid
is added as an extra key. I originally intended to ignore the cip, but this
can optionally be done by setting the persistence mask (-M) to 0.0.0.0
while allowing the flexibility of other mask values.
It is envisaged that the SIP persistence engine will be used in conjunction
with one-packet scheduling. I'm interested to hear if that doesn't fit your
needs.
CONFIGURATION
A persistence engine is associated with a virtual service
(as are schedulers). I have added the --pe option to the
ivpsadm -A and -E commands to allow the persistence engine
of a virtual service to be added, changed, or deleted.
e.g. ipvsadm -A -u 10.4.3.192:5060 -p 60 -M 0.0.0.0 -o --pe sip
There are no other configuration parameters at this time.
RUNNING
When a connection template is created, if its virtual service
has a persistence engine, then the persistence engine can add
an extra key to the connection template. For the SIP module this
is the callid. More generically, it is known as "pe data". And
both the name of the persistence engine, "pe name", and "pe data"
can be viewed in /proc/net/ip_vs_conn and by passing the
--persistent-conn option to ipvsadm -Lc.
e.g.
# ipvsadm -Lcn --persistent-conn
UDP 00:38 UDP 10.4.3.0:0 10.4.3.192:5060 127.0.0.1:5060 sip 193373839
Here we see a single persistence template (cport is 0), which has been
handled by the sip persistence engine. The pe data (callid) is 193373839.
In the case where the persistence engine can't match a packet for some
reason, the connection will fall back to the normal persistence handling.
This seems reasonable, as that if the packet ought to be dropped, iptables
could be used.
A limited amount of debugging information has been added which
can be enabled using a value of 9 or greater in
/proc/sys/net/ipv4/vs/debug_level
CODE AVAILABILITY
The kernel patches (12) are available in git as the pe-5 branch of
git://git.kernel.org/pub/scm/linux/kernel/git/horms/lvs-test-2.6.git
The ipvsadm patches (2) are available in git as the pe-5 branch of
git://github.com/horms/ipvsadm-test.git
There is no change to the ipvsadm patches since the v2 series
so I will not repost them.
^ permalink raw reply
* [patch v5 01/12] netfilter: nf_conntrack_sip: Allow ct_sip_get_header() to be called with a null ct argument
From: Simon Horman @ 2010-10-04 13:46 UTC (permalink / raw)
To: lvs-devel, netdev, netfilter, netfilter-devel
Cc: Jan Engelhardt, Stephen Hemminger, Wensong Zhang,
Julian Anastasov, Patrick McHardy
In-Reply-To: <20101004134624.963907470@akiko.akashicho.tokyo.vergenet.net>
[-- Attachment #1: 0001-netfilter-nf_conntrack_sip-Allow-ct_sip_get_header-t.patch --]
[-- Type: text/plain, Size: 515 bytes --]
Signed-off-by: Simon Horman <horms@verge.net.au>
Acked-by: Julian Anastasov <ja@ssi.bg>
diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c
index 53d8922..2fd1ea2 100644
--- a/net/netfilter/nf_conntrack_sip.c
+++ b/net/netfilter/nf_conntrack_sip.c
@@ -152,6 +152,9 @@ static int parse_addr(const struct nf_conn *ct, const char *cp,
const char *end;
int ret = 0;
+ if (!ct)
+ return 0;
+
memset(addr, 0, sizeof(*addr));
switch (nf_ct_l3num(ct)) {
case AF_INET:
--
1.7.1
^ permalink raw reply related
* [patch v5 02/12] netfilter: nf_conntrack_sip: Add callid parser
From: Simon Horman @ 2010-10-04 13:46 UTC (permalink / raw)
To: lvs-devel, netdev, netfilter, netfilter-devel
Cc: Jan Engelhardt, Stephen Hemminger, Wensong Zhang,
Julian Anastasov, Patrick McHardy
In-Reply-To: <20101004134624.963907470@akiko.akashicho.tokyo.vergenet.net>
[-- Attachment #1: 0002-netfilter-nf_conntrack_sip-Add-callid-parser.patch --]
[-- Type: text/plain, Size: 2483 bytes --]
Signed-off-by: Simon Horman <horms@verge.net.au>
Acked-by: Julian Anastasov <ja@ssi.bg>
---
The motivation for this is for it to be used by LVS as per
subsequent patches.
* Patrick McHardy suggested changing word_len to check for the
next newline or whitespace. But I believe this is incorrect.
For example '#' would be permitted but it is invalid
in a word according to RFC3261.
diff --git a/include/linux/netfilter/nf_conntrack_sip.h b/include/linux/netfilter/nf_conntrack_sip.h
index ff8cfbc..0ce91d5 100644
--- a/include/linux/netfilter/nf_conntrack_sip.h
+++ b/include/linux/netfilter/nf_conntrack_sip.h
@@ -89,6 +89,7 @@ enum sip_header_types {
SIP_HDR_VIA_TCP,
SIP_HDR_EXPIRES,
SIP_HDR_CONTENT_LENGTH,
+ SIP_HDR_CALL_ID,
};
enum sdp_header_types {
diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c
index 2fd1ea2..715ce54 100644
--- a/net/netfilter/nf_conntrack_sip.c
+++ b/net/netfilter/nf_conntrack_sip.c
@@ -130,6 +130,44 @@ static int digits_len(const struct nf_conn *ct, const char *dptr,
return len;
}
+static int iswordc(const char c)
+{
+ if (isalnum(c) || c == '!' || c == '"' || c == '%' ||
+ (c >= '(' && c <= '/') || c == ':' || c == '<' || c == '>' ||
+ c == '?' || (c >= '[' && c <= ']') || c == '_' || c == '`' ||
+ c == '{' || c == '}' || c == '~')
+ return 1;
+ return 0;
+}
+
+static int word_len(const char *dptr, const char *limit)
+{
+ int len = 0;
+ while (dptr < limit && iswordc(*dptr)) {
+ dptr++;
+ len++;
+ }
+ return len;
+}
+
+static int callid_len(const struct nf_conn *ct, const char *dptr,
+ const char *limit, int *shift)
+{
+ int len, domain_len;
+
+ len = word_len(dptr, limit);
+ dptr += len;
+ if (!len || dptr == limit || *dptr != '@')
+ return len;
+ dptr++;
+ len++;
+
+ domain_len = word_len(dptr, limit);
+ if (!domain_len)
+ return 0;
+ return len + domain_len;
+}
+
/* get media type + port length */
static int media_len(const struct nf_conn *ct, const char *dptr,
const char *limit, int *shift)
@@ -299,6 +337,7 @@ static const struct sip_header ct_sip_hdrs[] = {
[SIP_HDR_VIA_TCP] = SIP_HDR("Via", "v", "TCP ", epaddr_len),
[SIP_HDR_EXPIRES] = SIP_HDR("Expires", NULL, NULL, digits_len),
[SIP_HDR_CONTENT_LENGTH] = SIP_HDR("Content-Length", "l", NULL, digits_len),
+ [SIP_HDR_CALL_ID] = SIP_HDR("Call-Id", "i", NULL, callid_len),
};
static const char *sip_follow_continuation(const char *dptr, const char *limit)
--
1.7.1
^ permalink raw reply related
* [patch v5 03/12] IPVS: compact ip_vs_sched_persist()
From: Simon Horman @ 2010-10-04 13:46 UTC (permalink / raw)
To: lvs-devel, netdev, netfilter, netfilter-devel
Cc: Jan Engelhardt, Stephen Hemminger, Wensong Zhang,
Julian Anastasov, Patrick McHardy
In-Reply-To: <20101004134624.963907470@akiko.akashicho.tokyo.vergenet.net>
[-- Attachment #1: 0003-IPVS-compact-ip_vs_sched_persist.patch --]
[-- Type: text/plain, Size: 5897 bytes --]
Compact ip_vs_sched_persist() by setting up parameters
and calling functions once.
Signed-off-by: Simon Horman <horms@verge.net.au>
Acked-by: Julian Anastasov <ja@ssi.bg>
---
v2
* Make "union nf_inet_addr fwmark" const
* Don't remove the comment next to the declaration of dport
* Add a comment to the declaration of vport
v3
* As suggested by Julian Anastasov
- Correct dport logic
Index: lvs-test-2.6/net/netfilter/ipvs/ip_vs_core.c
===================================================================
--- lvs-test-2.6.orig/net/netfilter/ipvs/ip_vs_core.c 2010-10-02 10:54:57.000000000 +0900
+++ lvs-test-2.6/net/netfilter/ipvs/ip_vs_core.c 2010-10-02 11:04:04.000000000 +0900
@@ -193,10 +193,14 @@ ip_vs_sched_persist(struct ip_vs_service
struct ip_vs_iphdr iph;
struct ip_vs_dest *dest;
struct ip_vs_conn *ct;
- __be16 dport; /* destination port to forward */
+ int protocol = iph.protocol;
+ __be16 dport = 0; /* destination port to forward */
+ __be16 vport = 0; /* virtual service port */
unsigned int flags;
union nf_inet_addr snet; /* source network of the client,
after masking */
+ const union nf_inet_addr fwmark = { .ip = htonl(svc->fwmark) };
+ const union nf_inet_addr *vaddr = &iph.daddr;
ip_vs_fill_iphdr(svc->af, skb_network_header(skb), &iph);
@@ -227,119 +231,61 @@ ip_vs_sched_persist(struct ip_vs_service
* service, and a template like <caddr, 0, vaddr, vport, daddr, dport>
* is created for other persistent services.
*/
- if (ports[1] == svc->port) {
- /* Check if a template already exists */
- if (svc->port != FTPPORT)
- ct = ip_vs_ct_in_get(svc->af, iph.protocol, &snet, 0,
- &iph.daddr, ports[1]);
- else
- ct = ip_vs_ct_in_get(svc->af, iph.protocol, &snet, 0,
- &iph.daddr, 0);
-
- if (!ct || !ip_vs_check_template(ct)) {
- /*
- * No template found or the dest of the connection
- * template is not available.
- */
- dest = svc->scheduler->schedule(svc, skb);
- if (dest == NULL) {
- IP_VS_DBG(1, "p-schedule: no dest found.\n");
- return NULL;
- }
-
- /*
- * Create a template like <protocol,caddr,0,
- * vaddr,vport,daddr,dport> for non-ftp service,
- * and <protocol,caddr,0,vaddr,0,daddr,0>
- * for ftp service.
+ {
+ if (ports[1] == svc->port) {
+ /* non-FTP template:
+ * <protocol, caddr, 0, vaddr, vport, daddr, dport>
+ * FTP template:
+ * <protocol, caddr, 0, vaddr, 0, daddr, 0>
*/
if (svc->port != FTPPORT)
- ct = ip_vs_conn_new(svc->af, iph.protocol,
- &snet, 0,
- &iph.daddr,
- ports[1],
- &dest->addr, dest->port,
- IP_VS_CONN_F_TEMPLATE,
- dest);
- else
- ct = ip_vs_conn_new(svc->af, iph.protocol,
- &snet, 0,
- &iph.daddr, 0,
- &dest->addr, 0,
- IP_VS_CONN_F_TEMPLATE,
- dest);
- if (ct == NULL)
- return NULL;
-
- ct->timeout = svc->timeout;
+ vport = ports[1];
} else {
- /* set destination with the found template */
- dest = ct->dest;
- }
- dport = dest->port;
- } else {
- /*
- * Note: persistent fwmark-based services and persistent
- * port zero service are handled here.
- * fwmark template: <IPPROTO_IP,caddr,0,fwmark,0,daddr,0>
- * port zero template: <protocol,caddr,0,vaddr,0,daddr,0>
- */
- if (svc->fwmark) {
- union nf_inet_addr fwmark = {
- .ip = htonl(svc->fwmark)
- };
-
- ct = ip_vs_ct_in_get(svc->af, IPPROTO_IP, &snet, 0,
- &fwmark, 0);
- } else
- ct = ip_vs_ct_in_get(svc->af, iph.protocol, &snet, 0,
- &iph.daddr, 0);
-
- if (!ct || !ip_vs_check_template(ct)) {
- /*
- * If it is not persistent port zero, return NULL,
- * otherwise create a connection template.
+ /* Note: persistent fwmark-based services and
+ * persistent port zero service are handled here.
+ * fwmark template:
+ * <IPPROTO_IP,caddr,0,fwmark,0,daddr,0>
+ * port zero template:
+ * <protocol,caddr,0,vaddr,0,daddr,0>
*/
- if (svc->port)
- return NULL;
-
- dest = svc->scheduler->schedule(svc, skb);
- if (dest == NULL) {
- IP_VS_DBG(1, "p-schedule: no dest found.\n");
- return NULL;
+ if (svc->fwmark) {
+ protocol = IPPROTO_IP;
+ vaddr = &fwmark;
}
+ }
+ }
- /*
- * Create a template according to the service
- */
- if (svc->fwmark) {
- union nf_inet_addr fwmark = {
- .ip = htonl(svc->fwmark)
- };
-
- ct = ip_vs_conn_new(svc->af, IPPROTO_IP,
- &snet, 0,
- &fwmark, 0,
- &dest->addr, 0,
- IP_VS_CONN_F_TEMPLATE,
- dest);
- } else
- ct = ip_vs_conn_new(svc->af, iph.protocol,
- &snet, 0,
- &iph.daddr, 0,
- &dest->addr, 0,
- IP_VS_CONN_F_TEMPLATE,
- dest);
- if (ct == NULL)
- return NULL;
+ /* Check if a template already exists */
+ ct = ip_vs_ct_in_get(svc->af, protocol, &snet, 0, vaddr, vport);
- ct->timeout = svc->timeout;
- } else {
- /* set destination with the found template */
- dest = ct->dest;
+ if (!ct || !ip_vs_check_template(ct)) {
+ /* No template found or the dest of the connection
+ * template is not available.
+ */
+ dest = svc->scheduler->schedule(svc, skb);
+ if (!dest) {
+ IP_VS_DBG(1, "p-schedule: no dest found.\n");
+ return NULL;
}
- dport = ports[1];
- }
+
+ if (ports[1] == svc->port && svc->port != FTPPORT)
+ dport = dest->port;
+
+ /* Create a template */
+ ct = ip_vs_conn_new(svc->af, protocol, &snet, 0,vaddr, vport,
+ &dest->addr, dport,
+ IP_VS_CONN_F_TEMPLATE, dest);
+ if (ct == NULL)
+ return NULL;
+
+ ct->timeout = svc->timeout;
+ } else
+ /* set destination with the found template */
+ dest = ct->dest;
+
+ dport = ports[1];
+ if (dport == svc->port && dest->port)
+ dport = dest->port;
flags = (svc->flags & IP_VS_SVC_F_ONEPACKET
&& iph.protocol == IPPROTO_UDP)?
^ permalink raw reply
* [patch v5 05/12] IPVS: Allow null argument to ip_vs_scheduler_put()
From: Simon Horman @ 2010-10-04 13:46 UTC (permalink / raw)
To: lvs-devel, netdev, netfilter, netfilter-devel
Cc: Jan Engelhardt, Stephen Hemminger, Wensong Zhang,
Julian Anastasov, Patrick McHardy
In-Reply-To: <20101004134624.963907470@akiko.akashicho.tokyo.vergenet.net>
[-- Attachment #1: 0005-IPVS-Allow-null-argument-to-ip_vs_scheduler_put.patch --]
[-- Type: text/plain, Size: 2081 bytes --]
This simplifies caller logic sightly.
Signed-off-by: Simon Horman <horms@verge.net.au>
Acked-by: Julian Anastasov <ja@ssi.bg>
---
v2
* Trivial rediff
Index: lvs-test-2.6/net/netfilter/ipvs/ip_vs_ctl.c
===================================================================
--- lvs-test-2.6.orig/net/netfilter/ipvs/ip_vs_ctl.c 2010-10-01 22:25:53.000000000 +0900
+++ lvs-test-2.6/net/netfilter/ipvs/ip_vs_ctl.c 2010-10-01 22:26:10.000000000 +0900
@@ -1144,7 +1144,7 @@ ip_vs_add_service(struct ip_vs_service_u
if (sched == NULL) {
pr_info("Scheduler module ip_vs_%s not found\n", u->sched_name);
ret = -ENOENT;
- goto out_mod_dec;
+ goto out_err;
}
#ifdef CONFIG_IP_VS_IPV6
@@ -1204,7 +1204,7 @@ ip_vs_add_service(struct ip_vs_service_u
*svc_p = svc;
return 0;
- out_err:
+ out_err:
if (svc != NULL) {
if (svc->scheduler)
ip_vs_unbind_scheduler(svc);
@@ -1217,7 +1217,6 @@ ip_vs_add_service(struct ip_vs_service_u
}
ip_vs_scheduler_put(sched);
- out_mod_dec:
/* decrease the module use count */
ip_vs_use_count_dec();
@@ -1300,10 +1299,7 @@ ip_vs_edit_service(struct ip_vs_service
#ifdef CONFIG_IP_VS_IPV6
out:
#endif
-
- if (old_sched)
- ip_vs_scheduler_put(old_sched);
-
+ ip_vs_scheduler_put(old_sched);
return ret;
}
@@ -1327,8 +1323,7 @@ static void __ip_vs_del_service(struct i
/* Unbind scheduler */
old_sched = svc->scheduler;
ip_vs_unbind_scheduler(svc);
- if (old_sched)
- ip_vs_scheduler_put(old_sched);
+ ip_vs_scheduler_put(old_sched);
/* Unbind app inc */
if (svc->inc) {
Index: lvs-test-2.6/net/netfilter/ipvs/ip_vs_sched.c
===================================================================
--- lvs-test-2.6.orig/net/netfilter/ipvs/ip_vs_sched.c 2010-10-01 22:25:53.000000000 +0900
+++ lvs-test-2.6/net/netfilter/ipvs/ip_vs_sched.c 2010-10-01 22:26:10.000000000 +0900
@@ -159,7 +159,7 @@ struct ip_vs_scheduler *ip_vs_scheduler_
void ip_vs_scheduler_put(struct ip_vs_scheduler *scheduler)
{
- if (scheduler->module)
+ if (scheduler && scheduler->module)
module_put(scheduler->module);
}
^ permalink raw reply
* [patch v5 06/12] IPVS: ip_vs_{un,}bind_scheduler NULL arguments
From: Simon Horman @ 2010-10-04 13:46 UTC (permalink / raw)
To: lvs-devel, netdev, netfilter, netfilter-devel
Cc: Jan Engelhardt, Stephen Hemminger, Wensong Zhang,
Julian Anastasov, Patrick McHardy
In-Reply-To: <20101004134624.963907470@akiko.akashicho.tokyo.vergenet.net>
[-- Attachment #1: 0006-IPVS-ip_vs_-un-bind_scheduler-NULL-arguments.patch --]
[-- Type: text/plain, Size: 1790 bytes --]
In general NULL arguments aren't passed by the few callers that exist,
so don't test for them.
The exception is to make passing NULL to ip_vs_unbind_scheduler() a noop.
Signed-off-by: Simon Horman <horms@verge.net.au>
Acked-by: Julian Anastasov <ja@ssi.bg>
---
v2
* Trivial rediff
v3
* Trivial rediff
Index: lvs-test-2.6/net/netfilter/ipvs/ip_vs_ctl.c
===================================================================
--- lvs-test-2.6.orig/net/netfilter/ipvs/ip_vs_ctl.c 2010-10-02 10:15:45.000000000 +0900
+++ lvs-test-2.6/net/netfilter/ipvs/ip_vs_ctl.c 2010-10-02 10:15:47.000000000 +0900
@@ -1206,8 +1206,7 @@ ip_vs_add_service(struct ip_vs_service_u
out_err:
if (svc != NULL) {
- if (svc->scheduler)
- ip_vs_unbind_scheduler(svc);
+ ip_vs_unbind_scheduler(svc);
if (svc->inc) {
local_bh_disable();
ip_vs_app_inc_put(svc->inc);
Index: lvs-test-2.6/net/netfilter/ipvs/ip_vs_sched.c
===================================================================
--- lvs-test-2.6.orig/net/netfilter/ipvs/ip_vs_sched.c 2010-10-02 10:15:45.000000000 +0900
+++ lvs-test-2.6/net/netfilter/ipvs/ip_vs_sched.c 2010-10-02 10:15:47.000000000 +0900
@@ -46,15 +46,6 @@ int ip_vs_bind_scheduler(struct ip_vs_se
{
int ret;
- if (svc == NULL) {
- pr_err("%s(): svc arg NULL\n", __func__);
- return -EINVAL;
- }
- if (scheduler == NULL) {
- pr_err("%s(): scheduler arg NULL\n", __func__);
- return -EINVAL;
- }
-
svc->scheduler = scheduler;
if (scheduler->init_service) {
@@ -74,18 +65,10 @@ int ip_vs_bind_scheduler(struct ip_vs_se
*/
int ip_vs_unbind_scheduler(struct ip_vs_service *svc)
{
- struct ip_vs_scheduler *sched;
+ struct ip_vs_scheduler *sched = svc->scheduler;
- if (svc == NULL) {
- pr_err("%s(): svc arg NULL\n", __func__);
- return -EINVAL;
- }
^ permalink raw reply
* [patch v5 08/12] IPVS: Add persistence engine data to /proc/net/ip_vs_conn
From: Simon Horman @ 2010-10-04 13:46 UTC (permalink / raw)
To: lvs-devel, netdev, netfilter, netfilter-devel
Cc: Jan Engelhardt, Stephen Hemminger, Wensong Zhang,
Julian Anastasov, Patrick McHardy
In-Reply-To: <20101004134624.963907470@akiko.akashicho.tokyo.vergenet.net>
[-- Attachment #1: 0008-IPVS-Add-persistence-engine-data-to-proc-net-ip_vs_c.patch --]
[-- Type: text/plain, Size: 3131 bytes --]
This shouldn't break compatibility with userspace as the new data
is at the end of the line.
I have confirmed that this doesn't break ipvsadm, the main (only?)
user-space user of this data.
Signed-off-by: Simon Horman <horms@verge.net.au>
Acked-by: Julian Anastasov <ja@ssi.bg>
---
* Jan Engelhardt suggested using netlink to do this, but it seems like
overkill to me. I'm willing to be convinced otherwise.
v2
* Trivial rediff
v3
* As suggested by Julian Anastasov
- ip_vs_conn_seq_show(): cp->dest is optional
so test for its presence accordingly
- Re-diff for addition of inverse parameter to ip_vs_conn_hashkey_param()
Index: lvs-test-2.6/include/net/ip_vs.h
===================================================================
--- lvs-test-2.6.orig/include/net/ip_vs.h 2010-10-02 10:55:43.000000000 +0900
+++ lvs-test-2.6/include/net/ip_vs.h 2010-10-02 10:55:49.000000000 +0900
@@ -572,6 +572,7 @@ struct ip_vs_pe {
struct ip_vs_conn *ct);
u32 (*hashkey_raw)(const struct ip_vs_conn_param *p, u32 initval,
bool inverse);
+ int (*show_pe_data)(const struct ip_vs_conn *cp, char *buf);
};
/*
Index: lvs-test-2.6/net/netfilter/ipvs/ip_vs_conn.c
===================================================================
--- lvs-test-2.6.orig/net/netfilter/ipvs/ip_vs_conn.c 2010-10-02 10:55:43.000000000 +0900
+++ lvs-test-2.6/net/netfilter/ipvs/ip_vs_conn.c 2010-10-02 10:57:00.000000000 +0900
@@ -950,30 +950,45 @@ static int ip_vs_conn_seq_show(struct se
if (v == SEQ_START_TOKEN)
seq_puts(seq,
- "Pro FromIP FPrt ToIP TPrt DestIP DPrt State Expires\n");
+ "Pro FromIP FPrt ToIP TPrt DestIP DPrt State Expires PEName PEData\n");
else {
const struct ip_vs_conn *cp = v;
+ char pe_data[IP_VS_PENAME_MAXLEN + IP_VS_PEDATA_MAXLEN + 3];
+ size_t len = 0;
+
+ if (cp->dest && cp->dest->svc->pe &&
+ cp->dest->svc->pe->show_pe_data) {
+ pe_data[0] = ' ';
+ len = strlen(cp->dest->svc->pe->name);
+ memcpy(pe_data + 1, cp->dest->svc->pe->name, len);
+ pe_data[len + 1] = ' ';
+ len += 2;
+ len += cp->dest->svc->pe->show_pe_data(cp,
+ pe_data + len);
+ }
+ pe_data[len] = '\0';
#ifdef CONFIG_IP_VS_IPV6
if (cp->af == AF_INET6)
- seq_printf(seq, "%-3s %pI6 %04X %pI6 %04X %pI6 %04X %-11s %7lu\n",
+ seq_printf(seq, "%-3s %pI6 %04X %pI6 %04X "
+ "%pI6 %04X %-11s %7lu%s\n",
ip_vs_proto_name(cp->protocol),
&cp->caddr.in6, ntohs(cp->cport),
&cp->vaddr.in6, ntohs(cp->vport),
&cp->daddr.in6, ntohs(cp->dport),
ip_vs_state_name(cp->protocol, cp->state),
- (cp->timer.expires-jiffies)/HZ);
+ (cp->timer.expires-jiffies)/HZ, pe_data);
else
#endif
seq_printf(seq,
"%-3s %08X %04X %08X %04X"
- " %08X %04X %-11s %7lu\n",
+ " %08X %04X %-11s %7lu%s\n",
ip_vs_proto_name(cp->protocol),
ntohl(cp->caddr.ip), ntohs(cp->cport),
ntohl(cp->vaddr.ip), ntohs(cp->vport),
ntohl(cp->daddr.ip), ntohs(cp->dport),
ip_vs_state_name(cp->protocol, cp->state),
- (cp->timer.expires-jiffies)/HZ);
+ (cp->timer.expires-jiffies)/HZ, pe_data);
}
return 0;
}
^ permalink raw reply
* [patch v5 09/12] IPVS: management of persistence engine modules
From: Simon Horman @ 2010-10-04 13:46 UTC (permalink / raw)
To: lvs-devel, netdev, netfilter, netfilter-devel
Cc: Jan Engelhardt, Stephen Hemminger, Wensong Zhang,
Julian Anastasov, Patrick McHardy
In-Reply-To: <20101004134624.963907470@akiko.akashicho.tokyo.vergenet.net>
[-- Attachment #1: 0009-IPVS-management-of-persistence-engine-modules.patch --]
[-- Type: text/plain, Size: 5764 bytes --]
This is based heavily on the scheduler management code
Signed-off-by: Simon Horman <horms@verge.net.au>
Acked-by: Julian Anastasov <ja@ssi.bg>
---
v0.4
* Export register_ip_vs_pe and unregister_ip_vs_pe
* Use one line comment format for one line comments.
* Only use at most one blank line consecutively
v1
* As suggested by Stephen Hemminger
- Convert __ip_vs_pe_lock from a rwlock to a spinlock.
This code isn't performance-critical, so there is no need for RCU.
- Rename __ip_vs_pe_lock as ip_vs_pe_lock
* Stephen also suggested open-coding ip_vs_{un,}bind_pe()
as they are very short. But I would prefer to keep them as they are used
along side ip_vs_{un,}bind_scheduler which are too long to be open-coded.
v2
* Update for recent addition of ip_vs_nfct.c
* Trivial rediff
v3
* Trivial rediff
Index: lvs-test-2.6/include/net/ip_vs.h
===================================================================
--- lvs-test-2.6.orig/include/net/ip_vs.h 2010-10-02 10:45:06.000000000 +0900
+++ lvs-test-2.6/include/net/ip_vs.h 2010-10-02 10:45:41.000000000 +0900
@@ -796,6 +796,12 @@ extern int ip_vs_app_pkt_in(struct ip_vs
extern int ip_vs_app_init(void);
extern void ip_vs_app_cleanup(void);
+void ip_vs_bind_pe(struct ip_vs_service *svc, struct ip_vs_pe *pe);
+void ip_vs_unbind_pe(struct ip_vs_service *svc);
+int register_ip_vs_pe(struct ip_vs_pe *pe);
+int unregister_ip_vs_pe(struct ip_vs_pe *pe);
+extern struct ip_vs_pe *ip_vs_pe_get(const char *name);
+extern void ip_vs_pe_put(struct ip_vs_pe *pe);
/*
* IPVS protocol functions (from ip_vs_proto.c)
Index: lvs-test-2.6/net/netfilter/ipvs/ip_vs_pe.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ lvs-test-2.6/net/netfilter/ipvs/ip_vs_pe.c 2010-10-02 10:45:41.000000000 +0900
@@ -0,0 +1,147 @@
+#define KMSG_COMPONENT "IPVS"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <asm/string.h>
+#include <linux/kmod.h>
+#include <linux/sysctl.h>
+
+#include <net/ip_vs.h>
+
+/* IPVS pe list */
+static LIST_HEAD(ip_vs_pe);
+
+/* lock for service table */
+static DEFINE_SPINLOCK(ip_vs_pe_lock);
+
+/* Bind a service with a pe */
+void ip_vs_bind_pe(struct ip_vs_service *svc, struct ip_vs_pe *pe)
+{
+ svc->pe = pe;
+}
+
+/* Unbind a service from its pe */
+void ip_vs_unbind_pe(struct ip_vs_service *svc)
+{
+ svc->pe = NULL;
+}
+
+/* Get pe in the pe list by name */
+static struct ip_vs_pe *
+ip_vs_pe_getbyname(const char *pe_name)
+{
+ struct ip_vs_pe *pe;
+
+ IP_VS_DBG(2, "%s(): pe_name \"%s\"\n", __func__,
+ pe_name);
+
+ spin_lock_bh(&ip_vs_pe_lock);
+
+ list_for_each_entry(pe, &ip_vs_pe, n_list) {
+ /* Test and get the modules atomically */
+ if (pe->module &&
+ !try_module_get(pe->module)) {
+ /* This pe is just deleted */
+ continue;
+ }
+ if (strcmp(pe_name, pe->name)==0) {
+ /* HIT */
+ spin_unlock_bh(&ip_vs_pe_lock);
+ return pe;
+ }
+ if (pe->module)
+ module_put(pe->module);
+ }
+
+ spin_unlock_bh(&ip_vs_pe_lock);
+ return NULL;
+}
+
+/* Lookup pe and try to load it if it doesn't exist */
+struct ip_vs_pe *ip_vs_pe_get(const char *name)
+{
+ struct ip_vs_pe *pe;
+
+ /* Search for the pe by name */
+ pe = ip_vs_pe_getbyname(name);
+
+ /* If pe not found, load the module and search again */
+ if (!pe) {
+ request_module("ip_vs_pe_%s", name);
+ pe = ip_vs_pe_getbyname(name);
+ }
+
+ return pe;
+}
+
+void ip_vs_pe_put(struct ip_vs_pe *pe)
+{
+ if (pe && pe->module)
+ module_put(pe->module);
+}
+
+/* Register a pe in the pe list */
+int register_ip_vs_pe(struct ip_vs_pe *pe)
+{
+ struct ip_vs_pe *tmp;
+
+ /* increase the module use count */
+ ip_vs_use_count_inc();
+
+ spin_lock_bh(&ip_vs_pe_lock);
+
+ if (!list_empty(&pe->n_list)) {
+ spin_unlock_bh(&ip_vs_pe_lock);
+ ip_vs_use_count_dec();
+ pr_err("%s(): [%s] pe already linked\n",
+ __func__, pe->name);
+ return -EINVAL;
+ }
+
+ /* Make sure that the pe with this name doesn't exist
+ * in the pe list.
+ */
+ list_for_each_entry(tmp, &ip_vs_pe, n_list) {
+ if (strcmp(tmp->name, pe->name) == 0) {
+ spin_unlock_bh(&ip_vs_pe_lock);
+ ip_vs_use_count_dec();
+ pr_err("%s(): [%s] pe already existed "
+ "in the system\n", __func__, pe->name);
+ return -EINVAL;
+ }
+ }
+ /* Add it into the d-linked pe list */
+ list_add(&pe->n_list, &ip_vs_pe);
+ spin_unlock_bh(&ip_vs_pe_lock);
+
+ pr_info("[%s] pe registered.\n", pe->name);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(register_ip_vs_pe);
+
+/* Unregister a pe from the pe list */
+int unregister_ip_vs_pe(struct ip_vs_pe *pe)
+{
+ spin_lock_bh(&ip_vs_pe_lock);
+ if (list_empty(&pe->n_list)) {
+ spin_unlock_bh(&ip_vs_pe_lock);
+ pr_err("%s(): [%s] pe is not in the list. failed\n",
+ __func__, pe->name);
+ return -EINVAL;
+ }
+
+ /* Remove it from the d-linked pe list */
+ list_del(&pe->n_list);
+ spin_unlock_bh(&ip_vs_pe_lock);
+
+ /* decrease the module use count */
+ ip_vs_use_count_dec();
+
+ pr_info("[%s] pe unregistered.\n", pe->name);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(unregister_ip_vs_pe);
Index: lvs-test-2.6/net/netfilter/ipvs/Makefile
===================================================================
--- lvs-test-2.6.orig/net/netfilter/ipvs/Makefile 2010-10-02 10:29:43.000000000 +0900
+++ lvs-test-2.6/net/netfilter/ipvs/Makefile 2010-10-02 10:45:41.000000000 +0900
@@ -14,7 +14,7 @@ ip_vs-extra_objs-$(CONFIG_IP_VS_NFCT) +=
ip_vs-objs := ip_vs_conn.o ip_vs_core.o ip_vs_ctl.o ip_vs_sched.o \
ip_vs_xmit.o ip_vs_app.o ip_vs_sync.o \
- ip_vs_est.o ip_vs_proto.o \
+ ip_vs_est.o ip_vs_proto.o ip_vs_pe.o \
$(ip_vs_proto-objs-y) $(ip_vs-extra_objs-y)
^ 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