sunvnet: Schedule maybe_tx_wakeup as a tasklet from ldc_rx path
Subsystems (2)
PATCH 3/3 sunvnet: Schedule maybe_tx_wakeup as a tasklet from ldc_rx path
This patch must be applied after
"[PATCH net-next 2/3] sunvnet: Do not spin in an infinite loop when vio_ldc_send() returns EAGAIN"
At the tail of vnet_event(), if we hit the maybe_tx_wakeup() condition, we try to take the netif_tx_lock() in the recv-interrupt-context and can deadlock with dev_watchdog(). Two changes to fix this:
- The contents of maybe_tx_wakeup() should be moved into vnet_tx_timeout
- vnet_event() should kick off a tasklet that triggers netif_wake_queue()
--- drivers/net/ethernet/sun/sunvnet.c | 52 +++++++++++++++++++++++--------------- drivers/net/ethernet/sun/sunvnet.h | 4 +++ 2 files changed, 36 insertions(+), 20 deletions(-)
drivers/net/ethernet/sun/sunvnet.c +32 -20
@@ -32,6 +32,8 @@ MODULE_DESCRIPTION("Sun LDOM virtual network driver");MODULE_LICENSE ("GPL" );MODULE_VERSION (DRV_MODULE_VERSION ); +static void vnet_tx_timeout (struct net_device *dev); +/* Heuristic for the number of times to exponentially backoff and * retry sending an LDC trigger when EAGAIN is encountered */
@@ -489,28 +491,13 @@ static int handle_mcast(struct vnet_port *port, void *msgbuf)return 0 ; } -static void maybe_tx_wakeup (struct vnet *vp) +static void maybe_tx_wakeup (unsigned long param) { +struct vnet *vp = (struct vnet *)param;struct net_device *dev = vp->dev;netif_tx_lock (dev); -if (likely (netif_queue_stopped (dev))) { -struct vnet_port *port; -int wake =1 ; - -list_for_each_entry (port, &vp->port_list, list) { -struct vio_dring_state *dr; - - dr = &port->vio.drings[VIO_DRIVER_TX_RING ]; -if (vnet_tx_dring_avail (dr) < -VNET_TX_WAKEUP_THRESH (dr)) { - wake =0 ; -break ; - } - } -if (wake) -netif_wake_queue (dev); - } +vnet_tx_timeout (dev);netif_tx_unlock (dev); }
@@ -587,8 +574,13 @@ static void vnet_event(void *arg, int event)break ; }spin_unlock (&vio->lock); +/* Kick off a tasklet to wake the queue. We cannot call +* maybe_tx_wakeup directly here because we could deadlock on +* netif_tx_lock() with dev_watchdog() +*/ if (unlikely (tx_wakeup && err != -ECONNRESET )) -maybe_tx_wakeup (port->vp); +tasklet_schedule (&port->vp->vnet_tx_wakeup); +local_irq_restore (flags); }
@@ -764,7 +756,25 @@ out_dropped:static void vnet_tx_timeout (struct net_device *dev) { -/* XXX Implement me XXX */ +struct vnet *vp =netdev_priv (dev); + +if (likely (netif_queue_stopped (dev))) { +struct vnet_port *port; +int wake =1 ; + +list_for_each_entry (port, &vp->port_list, list) { +struct vio_dring_state *dr; + + dr = &port->vio.drings[VIO_DRIVER_TX_RING ]; +if (vnet_tx_dring_avail (dr) < +VNET_TX_WAKEUP_THRESH (dr)) { + wake =0 ; +break ; + } + } +if (wake) +netif_wake_queue (dev); + } }static int vnet_open (struct net_device *dev)
@@ -1071,6 +1081,7 @@ static struct vnet *vnet_new(const u64 *local_mac) vp =netdev_priv (dev);spin_lock_init (&vp->lock); +tasklet_init (&vp->vnet_tx_wakeup, maybe_tx_wakeup, (unsigned long )vp); vp->dev = dev;INIT_LIST_HEAD (&vp->port_list);
@@ -1130,6 +1141,7 @@ static void vnet_cleanup(void) vp = list_first_entry(&vnet_list, struct vnet, list);list_del (&vp->list); dev = vp->dev; +tasklet_kill (&vp->vnet_tx_wakeup);/* vio_unregister_driver() should have cleaned up port_list */ BUG_ON (!list_empty (&vp->port_list));unregister_netdev (dev);
drivers/net/ethernet/sun/sunvnet.h +4 -0
@@ -1,6 +1,8 @@#ifndef _SUNVNET_H#define _SUNVNET_H +#include <linux/interrupt.h> +#define DESC_NCOOKIES (entry_size) \ ((entry_size) - sizeof(struct vio_net_desc))
@@ -78,6 +80,8 @@ struct vnet {struct list_head list;u64 local_mac; + + struct tasklet_struct vnet_tx_wakeup; };#endif /* _SUNVNET_H */
Signature · 1 line
1.8.4.2
David Miller
maintainerFrom: Sowmini Varadhan <[email protected]>
Date: Tue, 12 Aug 2014 10:35:31 -0400
Quoted 10 lines
drivers/net/ethernet/sun/sunvnet.c +2
-1@@ -489,28 +491,13 @@ static int handle_mcast(struct vnet_port *port, void *msgbuf)return 0 ; } -static void maybe_tx_wakeup (struct vnet *vp) +static void maybe_tx_wakeup (unsigned long param) { +struct vnet *vp = (struct vnet *)param;struct net_device *dev = vp->dev;
...
drivers/net/ethernet/sun/sunvnet.c out_dropped: · line 760
Quoted 12 lines
drivers/net/ethernet/sun/sunvnet.c +3
-2- } +vnet_tx_timeout (dev);netif_tx_unlock (dev); }@@ -764,7 +756,25 @@ out_dropped:static void vnet_tx_timeout (struct net_device *dev) { -/* XXX Implement me XXX */ +struct vnet *vp =netdev_priv (dev); +
Please do not usurp vnet_tx_timeout() to handle queue waking.
It is hooked up to netdev_ops->ndo_tx_timeout() which is invoked when the qdisc watchdog triggers after dev->watchdog_timeout time elapses after the queue is stopped without a subsequent wake.
This method is a therefore executed after a hard timeout, meaning that the device should probably be reset, whereas maybe_tx_wakeup() is normal processing meant to drive the engine of TX flow control.
In the context of sunvnet, vnet_tx_timeout() should probably reset the LDC channel(s) of the unresponsive peer(s).
Thanks.
Quoted 7 lines
Please do not usurp
vnet_tx_timeout()to handle queue waking.It is hooked up to
netdev_ops->ndo_tx_timeout()which is invoked when the qdisc watchdog triggers afterdev->watchdog_timeouttime elapses after the queue is stopped without a subsequent wake.
Quoted 6 lines
This method is a therefore executed after a hard timeout, meaning that the device should probably be reset, whereas
maybe_tx_wakeup()is normal processing meant to drive the engine of TX flow control.In the context of sunvnet,
vnet_tx_timeout()should probably reset the LDC channel(s) of the unresponsive peer(s).
yes, after a couple of days of reflection on the lingering issues in
http://www.spinics.net/lists/sparclinux/msg12360.html
I too was starting to arrive at similar conclusions about maybe_tx_wakeup vs vnet_tx_timeout.
First case 2 in the "todo" list (cannot send DRING_STOPPED):
If we cannot send a vnet_send_ack() we should invoke ldc_disconnect() for this peer. The ldc_disconnect() will reset hs_state and flags in the ldc_channel, so subsequent attempts to ldc_write() (e.g., from vio_ldc_send()) will return -ENOTCONN. So, for that case, a subsequent vnet_start_xmit() would *not* netif_stop_queue(), but just drop the packet, reset the dring, and keep driving.
To recover the disconnected channel, the admin would need to (ldm) unbind/bind the offender, identifiable by their mac address. And none of the other channels shold be affected (assuming inter-vnet-links is set to on)
So for case 1 we could do something very similar- I haven't tried this yet, but here's what I'm thinking: vnet_start_xmit() should not do a netif_stop_queue. Instead it should do a (new function) "vio_stop_queue()" which sets some (new) VIO_DR_FLOW_CONTROLLED state in the vio_driver_state, (or perhaps some flag bit in the ldc_channel?) and also marks a (new) boolean is_flow_controlled state variable in the struct vnet as TRUE.
The modified maybe_tx_wakeup would check is_flow_controlled on the vnet, and call a new vnet_wake_queue() to reset VIO_DR_FLOW_CONTROLLED if appropriate.
vnet_start_xmit should drop packets as long as VIO_DR_FLOW_CONTROLLED is set.
The above sketch has a deficiency that it doesnt avoid packet drops at the net_device layer itself - packets that can't make it out because of FLOW_CONTROLLED will get dropped - I think the Qdisc code path deals better with the back-pressure. I dont know if there is a way to leverage that path and still avoid the head-of-line blocking due to one flow-controlled ldc_channel.
I'm a little hesitant to ldc_disconnect a peer from the vnet_start_xmit path- if we have a super-efficient Tx path, we dont want to reset things merely because the receiver can't keep up- we just want to flow-control the Tx? Whereas the inability to transmit a DRING_STOPPED from the Rx side is likely to be a more unusual situation (would need the peer to send a burst of packets and then not be prepared to do even a single ldc_read()!)?
thoughts?
--Sowmini
David Miller
maintainerFrom: Sowmini Varadhan <[email protected]>
Date: Tue, 12 Aug 2014 21:58:17 -0400
Quoted 11 lines
Quoted 11 lines
Please do not usurp
vnet_tx_timeout()to handle queue waking.It is hooked up to
netdev_ops->ndo_tx_timeout()which is invoked when the qdisc watchdog triggers afterdev->watchdog_timeouttime elapses after the queue is stopped without a subsequent wake.This method is a therefore executed after a hard timeout, meaning that the device should probably be reset, whereas
maybe_tx_wakeup()is normal processing meant to drive the engine of TX flow control.
Quoted 7 lines
Quoted 2 lines
In the context of sunvnet,
vnet_tx_timeout()should probably reset the LDC channel(s) of the unresponsive peer(s).yes, after a couple of days of reflection on the lingering issues in
http://www.spinics.net/lists/sparclinux/msg12360.html
I too was starting to arrive at similar conclusions aboutmaybe_tx_wakeupvsvnet_tx_timeout.
However, don't get ahead of yourself. All I'm saying in the context of reviewing this patch #3 is that you should leave vnet_tx_timeout() alone and just put what you were putting into vnet_tx_timeout() into maybe_tx_wakeup().
Quoted 8 lines
First case 2 in the "todo" list (cannot send
DRING_STOPPED):
If we cannot send avnet_send_ack()we should invokeldc_disconnect()for this peer. Theldc_disconnect()will reseths_stateand flags in theldc_channel, so subsequent attempts toldc_write()(e.g., fromvio_ldc_send()) will return-ENOTCONN. So, for that case, a subsequentvnet_start_xmit()would *not*netif_stop_queue(), but just drop the packet, reset the dring, and keep driving.
Quoted 4 lines
To recover the disconnected channel, the admin would need to (ldm) unbind/bind the offender, identifiable by their mac address. And none of the other channels shold be affected (assuming inter-vnet-links is set to on)
This doesn't match my understanding. My understanding is that when
an LDC connection resets, the peer on the other side should automatically try to re-bind or whatever is necessary to re-establish the LDC link.
It's supposed to be fault tolerant in as many situations as possible without the need for explicit adminstrator intervention.
But besides that, an LDC reset is a big hammer. So I would say that it should be deferred to the last possible point.
So initially we do the backoff spinning loop synchronously. If that doesn't succeed, we schedule a workqueue that can poll the LDC channel some more trying to do the write, in a sleepable context (so a loop with delays and preemption points) until a much larger timeout. Only at this second timeout do we declare things to be serious enough for an LDC channel reset.
Quoted 8 lines
So for case 1 we could do something very similar- I haven't tried this yet, but here's what I'm thinking:
vnet_start_xmit()should not do anetif_stop_queue. Instead it should do a (new function) "vio_stop_queue()" which sets some (new)VIO_DR_FLOW_CONTROLLEDstate in thevio_driver_state, (or perhaps some flag bit in theldc_channel?) and also marks a (new) booleanis_flow_controlledstate variable in the struct vnet as TRUE.
Quoted 6 lines
The modified
maybe_tx_wakeupwould checkis_flow_controlledon the vnet, and call a newvnet_wake_queue()to resetVIO_DR_FLOW_CONTROLLEDif appropriate.
vnet_start_xmitshould drop packets as long asVIO_DR_FLOW_CONTROLLEDis set.
Again, as I stated yesterday, you really cannot do this. Head of line blocking when one peer gets wedged is absolutely necessary.
If a packet for a blocked peer is pending, you have to make the other guys wait until either the blocked peer gets unstuck or you reset the blocked peer's LDC channel on a hard timeout.
Quoted 2 lines
I dont know if there is a way to leverage that path and still avoid the head-of-line blocking due to one flow-controlled
ldc_channel.
Again, I don't think the semantics resulting from head-of-line blocking avoidance are acceptable.
Quoted 5 lines · David Miller
However, don't get ahead of yourself. All I'm saying in the context of reviewing this patch #3 is that you should leave
vnet_tx_timeout()alone and just put what you were putting intovnet_tx_timeout()intomaybe_tx_wakeup().
And just leave vnet_tx_timeout() as before (i.e, "XXX implement me"?)?
Sure, I can generate that (as a stand-alone unified-diff patch?) it would be the minimum fix needed to avoid the deadlock on netif_tx_lock() itself.
Quoted 6 lines
This doesn't match my understanding. My understanding is that when
an LDC connection resets, the peer on the other side should automatically try to re-bind or whatever is necessary to re-establish the LDC link.It's supposed to be fault tolerant in as many situations as possible without the need for explicit adminstrator intervention.
Ideally, yes. But that's not what I was observing when I tested this.
Quoted 2 lines
But besides that, an LDC reset is a big hammer. So I would say that it should be deferred to the last possible point.
Correct, and that's why it feels ok (to me) to do this when the DRING_STOPPED fails (so that we also fail subsequent ldc_write's from vnet_start_xmit()) but not in any other case.
Note that, as I pointed out to Raghuram already, doing ldc_disconnect does *not* send any reset events. The code may have other missing functionality.
Quoted 19 lines
So initially we do the backoff spinning loop synchronously. If that doesn't succeed, we schedule a workqueue that can poll the LDC channel some more trying to do the write, in a sleepable context (so a loop with delays and preemption points) until a much larger timeout. Only at this second timeout do we declare things to be serious enough for an LDC channel reset.
Quoted 12 lines
So for case 1 we could do something very similar- I haven't tried this yet, but here's what I'm thinking:
vnet_start_xmit()should not do anetif_stop_queue. Instead it should do a (new function) "vio_stop_queue()" which sets some (new)VIO_DR_FLOW_CONTROLLEDstate in thevio_driver_state, (or perhaps some flag bit in theldc_channel?) and also marks a (new) booleanis_flow_controlledstate variable in the struct vnet as TRUE.The modified
maybe_tx_wakeupwould checkis_flow_controlledon the vnet, and call a newvnet_wake_queue()to resetVIO_DR_FLOW_CONTROLLEDif appropriate.
Quoted 5 lines
Quoted 2 lines
vnet_start_xmitshould drop packets as long asVIO_DR_FLOW_CONTROLLEDis set.Again, as I stated yesterday, you really cannot do this. Head of line blocking when one peer gets wedged is absolutely necessary.
In the light of the subsequent discussion about head-of-line blocking (and it's applicability per ldc_channel, instead of per-net_device), do we still think the above has issues, or is otherwise not worth doing?
Quoted 4 lines · David Miller
So the question is how to manage this on the driver side, and the most natural way I see do this would be to use multiple TX netdev queues and a custom
netdev_ops->ndo_select_queue()method which selects the queue based upon the peer that would be selected.
This might work well for the current sunvnet model (and even there, it has limitations- if all the traffic is going out via the switchport to a gateway, you are again back to the head-of-line blocking model).
But how generally useful is this model? For point-to-multipoint links like ethernet, I dont think you actually track one channel per peer.
--Sowmini
David Miller
maintainerFrom: Sowmini Varadhan <[email protected]>
Date: Wed, 13 Aug 2014 07:20:10 -0400
Quoted 8 lines · David Miller
Quoted 5 lines
However, don't get ahead of yourself. All I'm saying in the context of reviewing this patch #3 is that you should leave
vnet_tx_timeout()alone and just put what you were putting intovnet_tx_timeout()intomaybe_tx_wakeup().And just leave
vnet_tx_timeout()as before (i.e, "XXX implement me"?)?
Yes, and I see this is what you have done.
Quoted 3 lines
Note that, as I pointed out to Raghuram already, doing
ldc_disconnectdoes *not* send any reset events. The code may have other missing functionality.
For the caller of ldc_disconnect() the reset is implied, if this is what you are talking about.
I don't see any value for generating an event the user of the LDC channel itself generated.
Quoted 5 lines
Quoted 4 lines
So the question is how to manage this on the driver side, and the most natural way I see do this would be to use multiple TX netdev queues and a custom
netdev_ops->ndo_select_queue()method which selects the queue based upon the peer that would be selected.
Quoted 8 lines
This might work well for the current sunvnet model (and even there, it has limitations- if all the traffic is going out via the switchport to a gateway, you are again back to the head-of-line blocking model).
But how generally useful is this model? For point-to-multipoint links like ethernet, I dont think you actually track one channel per peer.
I don't understand what your concern could be.
Ethernet is a broadcast medium, so all traffic (as far as the NIC is concerned) goes via the same single queue.
But here we have independent queues leading up to different destinations, so representing that as independent queues makes sense.
This way, if one non-switch peer goes down, all switch based traffic will still continue to flow, and vice versa.
Quoted 27 lines · Sowmini Varadhan
Quoted 7 lines
Please do not usurp
vnet_tx_timeout()to handle queue waking.It is hooked up to
netdev_ops->ndo_tx_timeout()which is invoked when the qdisc watchdog triggers afterdev->watchdog_timeouttime elapses after the queue is stopped without a subsequent wake.Quoted 6 lines
This method is a therefore executed after a hard timeout, meaning that the device should probably be reset, whereas
maybe_tx_wakeup()is normal processing meant to drive the engine of TX flow control.In the context of sunvnet,
vnet_tx_timeout()should probably reset the LDC channel(s) of the unresponsive peer(s).yes, after a couple of days of reflection on the lingering issues in
http://www.spinics.net/lists/sparclinux/msg12360.html
I too was starting to arrive at similar conclusions aboutmaybe_tx_wakeupvsvnet_tx_timeout.First case 2 in the "todo" list (cannot send
DRING_STOPPED):
If we cannot send avnet_send_ack()we should invokeldc_disconnect()for this peer. Theldc_disconnect()will reseths_stateand flags in theldc_channel, so subsequent attempts toldc_write()(e.g., fromvio_ldc_send()) will return-ENOTCONN. So, for that case, a subsequentvnet_start_xmit()would *not*netif_stop_queue(), but just drop the packet, reset the dring, and keep driving.
Quoted 4 lines
To recover the disconnected channel, the admin would need to (ldm) unbind/bind the offender, identifiable by their mac address. And none of the other channels shold be affected (assuming inter-vnet-links is set to on)
We do not consider a peer which couldn't process LDC messages as an offender but just a peer in a broken state. A peer could get into this type of situation due to many different reasons for example a hang or lockup in an entirely unrelated code or stuck in a debugger or due to a bug in the sunvnet driver itself. Such a guest should be able to recover when it is rebooted. Requiring an unbind/bind is not considered a solution, we don't expect admins to perform unbind/bind unless they are really trying to destroy the domain. Note, an unbind of a domain causes the vnet device ports in all of the peer domains removed and the bind brings back, which is a heavy hammer. What we really want is an LDC reset which puts the LDC state in a clean state to allow the peer to restart the handshake and establish communication again. This can be accomplished either by rebooting the peer or unload/load the sunvnet driver in the peer domain. It could also automatically recover too. You can see this as something similar to resetting a NIC when the NIC h/w is locked up.
Quoted 1 line
From what I read the
ldc_disconect()code, it seems like it is reconfiguring
the queues, so I assume a reset event would re-enable the communication fine, but I don't know for sure without testing this specific condition.
Quoted 9 lines
So for case 1 we could do something very similar- I haven't tried this yet, but here's what I'm thinking:
vnet_start_xmit()should not do anetif_stop_queue. Instead it should do a (new function) "vio_stop_queue()" which sets some (new)VIO_DR_FLOW_CONTROLLEDstate in thevio_driver_state, (or perhaps some flag bit in theldc_channel?) and also marks a (new) booleanis_flow_controlledstate variable in the struct vnet as TRUE.
Quoted 7 lines
The modified
maybe_tx_wakeupwould checkis_flow_controlledon the vnet, and call a newvnet_wake_queue()to resetVIO_DR_FLOW_CONTROLLEDif appropriate.
vnet_start_xmitshould drop packets as long asVIO_DR_FLOW_CONTROLLEDis set.
One important point to keep in mind that packets to different peers shouldn't be blocked by one blocked peer. Any flow controlling or dropping of the packets needs to be done on a per-port basis.
-Raghuram
Quoted 18 lines
The above sketch has a deficiency that it doesnt avoid packet drops at the
net_devicelayer itself - packets that can't make it out because ofFLOW_CONTROLLEDwill get dropped - I think the Qdisc code path deals better with the back-pressure. I dont know if there is a way to leverage that path and still avoid the head-of-line blocking due to one flow-controlledldc_channel.I'm a little hesitant to
ldc_disconnecta peer from thevnet_start_xmitpath- if we have a super-efficient Tx path, we dont want to reset things merely because the receiver can't keep up- we just want to flow-control the Tx? Whereas the inability to transmit aDRING_STOPPEDfrom the Rx side is likely to be a more unusual situation (would need the peer to send a burst of packets and then not be prepared to do even a singleldc_read()!)?thoughts?
--Sowmini
David Miller
maintainerFrom: Raghuram Kothakota <[email protected]>
Date: Tue, 12 Aug 2014 21:26:28 -0700
Quoted 3 lines
One important point to keep in mind that packets to different peers shouldn't be blocked by one blocked peer. Any flow controlling or dropping of the packets needs to be done on a per-port basis.
Until we use a big hammer and reset the LDC channel of that peer, we _absolutely_ should not reorder traffic and send to non-stuck peers.
A networking stack should avoid packet reordering in all cases when it has the ability to do so, and sending packets which came in later to unstuck peers when there are older packets still pending to the stuck peer violates that requirement.
Quoted 9 lines · David Miller
From: Raghuram Kothakota <[email protected]>
Date: Tue, 12 Aug 2014 21:26:28 -0700Quoted 3 lines
One important point to keep in mind that packets to different peers shouldn't be blocked by one blocked peer. Any flow controlling or dropping of the packets needs to be done on a per-port basis.
Until we use a big hammer and reset the LDC channel of that peer, we _absolutely_ should not reorder traffic and send to non-stuck peers.
The packet ordering requirement applies only for packets destined to a specific destination. The packets to different destinations can flow as long as they do not cause ordering issues. In case of sunvnet, each peer except the switch-port would be for a specific destination, so sending packets to other ports would not result in re-ordering of the packets.
Even if the peer to peer LDC is the one that is blocked then disconnecting that LDC channel and sending the packets via switch-port would not be expected to change the order of the packet as the LDC reset is expect to drop all packets in the ring so far.
-Raghuram
Quoted 5 lines
A networking stack should avoid packet reordering in all cases when it has the ability to do so, and sending packets which came in later to unstuck peers when there are older packets still pending to the stuck peer violates that requirement.
David Miller
maintainerFrom: Raghuram Kothakota <[email protected]>
Date: Tue, 12 Aug 2014 22:14:09 -0700
Quoted 18 lines · David Miller
Quoted 10 lines
From: Raghuram Kothakota <[email protected]>
Date: Tue, 12 Aug 2014 21:26:28 -0700Quoted 3 lines
One important point to keep in mind that packets to different peers shouldn't be blocked by one blocked peer. Any flow controlling or dropping of the packets needs to be done on a per-port basis.
Until we use a big hammer and reset the LDC channel of that peer, we _absolutely_ should not reorder traffic and send to non-stuck peers.
The packet ordering requirement applies only for packets destined to a specific destination. The packets to different destinations can flow as long as they do not cause ordering issues. In case of sunvnet, each peer except the switch-port would be for a specific destination, so sending packets to other ports would not result in re-ordering of the packets.
Quoted 4 lines
Even if the peer to peer LDC is the one that is blocked then disconnecting that LDC channel and sending the packets via switch-port would not be expected to change the order of the packet as the LDC reset is expect to drop all packets in the ring so far.
Ok, that makes sense.
So the question is how to manage this on the driver side, and the most natural way I see do this would be to use multiple TX netdev queues and a custom netdev_ops->ndo_select_queue() method which selects the queue based upon the peer that would be selected.
Quoted 26 lines · David Miller
From: Raghuram Kothakota <[email protected]>
Date: Tue, 12 Aug 2014 22:14:09 -0700Quoted 18 lines · David Miller
Quoted 10 lines
From: Raghuram Kothakota <[email protected]>
Date: Tue, 12 Aug 2014 21:26:28 -0700Quoted 3 lines
One important point to keep in mind that packets to different peers shouldn't be blocked by one blocked peer. Any flow controlling or dropping of the packets needs to be done on a per-port basis.
Until we use a big hammer and reset the LDC channel of that peer, we _absolutely_ should not reorder traffic and send to non-stuck peers.
The packet ordering requirement applies only for packets destined to a specific destination. The packets to different destinations can flow as long as they do not cause ordering issues. In case of sunvnet, each peer except the switch-port would be for a specific destination, so sending packets to other ports would not result in re-ordering of the packets.
Quoted 4 lines
Even if the peer to peer LDC is the one that is blocked then disconnecting that LDC channel and sending the packets via switch-port would not be expected to change the order of the packet as the LDC reset is expect to drop all packets in the ring so far.
Quoted 6 lines
Ok, that makes sense.
So the question is how to manage this on the driver side, and the most natural way I see do this would be to use multiple TX netdev queues and a custom
netdev_ops->ndo_select_queue()method which selects the queue based upon the peer that would be selected.
Thanks, if there is a method to accomplish this with multiple Tx netdev queues would be wonderful. We will research on the custom ndo_selec_queue() method to direct traffic automatically at the network stack level. We probably also need to look for methods to increase parallelism to boost performance, I assume multiple Tx queues would be a method to accomplish that as well.
-Raghuram
David Miller
maintainerFrom: Raghuram Kothakota <[email protected]>
Date: Tue, 12 Aug 2014 22:44:27 -0700
Quoted 6 lines
Thanks, if there is a method to accomplish this with multiple Tx netdev queues would be wonderful. We will research on the custom
ndo_selec_queue()method to direct traffic automatically at the network stack level. We probably also need to look for methods to increase parallelism to boost performance, I assume multiple Tx queues would be a method to accomplish that as well.
It will introduce parallelism only when there is traffic to multiple peers at the same time.
Quoted 10 lines · David Miller
From: Raghuram Kothakota <[email protected]>
Date: Tue, 12 Aug 2014 22:44:27 -0700Quoted 6 lines
Thanks, if there is a method to accomplish this with multiple Tx netdev queues would be wonderful. We will research on the custom
ndo_selec_queue()method to direct traffic automatically at the network stack level. We probably also need to look for methods to increase parallelism to boost performance, I assume multiple Tx queues would be a method to accomplish that as well.
Quoted 2 lines
It will introduce parallelism only when there is traffic to multiple peers at the same time.
Yes, I should not have related these two things, especially without
proper experimentation. In other implementations, we have used
techniques such as multiple Tx queues to increase parallelism but
path selection is done within the driver to get the benefit of the parallelism for all peers. We need to see what method suites best for sunvnet, we hope to know
more once we investigate all methods available.
In case of custom ndo_select_queue() method, we need to see if there are methods to deal with ports dynamically added/removed too.
-Raghuram
Quoted 3 lines · Raghuram Kothakota
We do not consider a peer which couldn't process LDC messages as an offender but just a peer in a broken state. A peer could get
So I was using "offender" in the same way that one typically talks about sending ICMP errors for "offending IP packets" (nothing pesonal :-)). I dont want to quibble over terminology here.
Quoted 3 lines
From what I read the
ldc_disconect()code, it seems like it is reconfiguring the queues, so I assume a reset event would re-enable the communication fine, but I don't know for sure without testing this specific condition.
No such events were generated by the code when I tested it.
I'll send a consolidated reply to the rest of that very long thread in a bit.
--Sowmini
Quoted 9 lines · Sowmini Varadhan
Quoted 3 lines · Raghuram Kothakota
We do not consider a peer which couldn't process LDC messages as an offender but just a peer in a broken state. A peer could get
So I was using "offender" in the same way that one typically talks about sending ICMP errors for "offending IP packets" (nothing pesonal :-)). I dont want to quibble over terminology here.
Quoted 5 lines
Quoted 3 lines
From what I read the
ldc_disconect()code, it seems like it is reconfiguring the queues, so I assume a reset event would re-enable the communication fine, but I don't know for sure without testing this specific condition.No such events were generated by the code when I tested it.
The reset event is expected for the peer, if it is not happening then we probably need to check why.
-Raghuram
Quoted 6 lines
I'll send a consolidated reply to the rest of that very long thread in a bit.
--Sowmini