* Re: patch tulip-natsemi-dp83840a-phy-fix.patch added to -mm tree
From: Francois Romieu @ 2005-05-20 19:15 UTC (permalink / raw)
To: Jeff Garzik; +Cc: Grant Grundler, akpm, T-Bone, varenet, Linux Kernel, Netdev
In-Reply-To: <428E3372.403@pobox.com>
Jeff Garzik <jgarzik@pobox.com> :
[snip]
I should start chewing it later today: it just reached the top of the
pile (right before the "see if Chelsio publish something within 5 days"
item).
--
Ueimor
^ permalink raw reply
* Re: patch tulip-natsemi-dp83840a-phy-fix.patch added to -mm tree
From: Jeff Garzik @ 2005-05-20 18:58 UTC (permalink / raw)
To: Grant Grundler, akpm; +Cc: T-Bone, varenet, Linux Kernel, Netdev
In-Reply-To: <20050516222612.GD9282@colo.lackof.org>
Grant Grundler wrote:
> After three years of using/maintaining the (trivial) tulip patch
> in parisc-linux tree (and shipped with RH/SuSe ia64 releases),
> I don't recall anyone complaining that udelays in tulip phy reset
> caused them problems. Sorry, I'm unmotivated to revisit this.
> Convince someone else to make tulip to use workqueues and I'll
> resubmit a clean patch on top of that for the phy init sequences.
Long delays are unacceptable in new drivers, and we are working to
remove them from older drivers. Lack of complaints is irrelevant -- its
a design requirement of all drivers.
Ingo and the real-time crowd are fighting against every delay, because
every delay causes a spin, a blip in latency, an increase in CPU usage,
and a complete stoppage of ALL work on a uniprocessor machine.
Your patch is not a special case. We have been communicating this
message on udelay/mdelay for -years-. All your patch [as-is] does is
cause more work for someone else.
This also presents a problem that Andrew points out on occasion:
what happens when a patch is useful, but the patch author isn't (for
whatever reason) doing the legwork necessary to get it into the mainline
kernel? We certainly DON'T want to lose this patch, as the changes are
useful.
Jeff
^ permalink raw reply
* Re: [PATCH] [BRIDGE] Set features based on slave's ones (was Ethernet Bridging: Enable Hardware Checksumming)
From: Jon Mason @ 2005-05-20 18:54 UTC (permalink / raw)
To: Catalin(ux aka Dino) BOIE; +Cc: netdev, davem
In-Reply-To: <Pine.LNX.4.62.0505200858480.12681@webhosting.rdsbv.ro>
On Friday 20 May 2005 01:07 am, Catalin(ux aka Dino) BOIE wrote:
> >> +static inline void br_features_change(struct net_bridge *br, struct
> >> net_device *dev) +{
> >> + br->dev->features &= dev->features | ~BR_FEAT_MASK;
> >
> > ~BR_FEAT_MASK isn't necessary. Either you wanted to do an '&' just
> > before it, so that BR_FEAT_MASK features are the only ones that you want
> > or you are enabling features that aren't necessarily supported by the
> > adapter/driver (like LLTX and HW_VLAN stuff).
>
> So, I invert BR_FEAT_MASK so I can, by default clear special features.
> Then I ored with dev->features, so I can enable special features if the
> slave device supports it. Then, I do & so I can clear stuff that is not
> supported by device, but the rest of br->dev features remains untouched.
>
> Let's test: if dev hash SG the code is like this:
> BR_FEAT_MASK = 1001 (only test SG and HW_CSUM)
> # br is inited
> br |= 1001
> br &= 0001 | ~1001
> br &= 0001 | 0110
> br &= 0111
> br = 1001 & 0111 = 0001 - so bit SG is set also in br. But not HW_CSUM
> because it's not in device.
>
> I can't see the code is wrong. Can you give me an example when it fails,
> please?
Let's use the full BR_FEAT_MASK of NETIF_F_HW_CSUM | NETIF_F_SG |
| NETIF_F_FRAGLIST | NETIF_F_IP_CSUM | NETIF_F_HIGHDMA | NETIF_F_TSO).
That is 0011 0000 0110 1011
Now, let's assume that the NIC only has NETIF_F_TSO,
NETIF_F_IP_CSUM, and NETIF_F_SG enabled.
So, that is 0000 1000 0000 0011
So, we have the following:
For the first adapter added:
br = 0001 1000 0110 1011
br = 0001 1000 0110 1011 & 0000 1000 0000 0011 | ~0001 1000 0110 1011
br = 0001 1000 0110 1011 & 0000 1000 0000 0011 | 1110 0111 1001 0100
br = 0000 1000 0000 0011 | 1110 0111 1001 0100
br = 1110 1111 1001 0111
Note - this breaks down to the following being enabled:
NETIF_F_SG
NETIF_F_IP_CSUM
NETIF_F_NO_CSUM
UNDEFINED BIT
NETIF_F_HW_VLAN_RX
NETIF_F_HW_VLAN_FILTER
NETIF_F_VLAN_CHALLENGED
NETIF_F_TSO
NETIF_F_LLTX
For a second adapter with the same features added:
br = 1110 1111 1001 0111
br = 1110 1111 1001 0111 & 0000 1000 0000 0011 | 1110 0111 1001 0100
br = 1110 1111 1001 0111 | 1110 0111 1001 0100
br = 1110 1111 1001 0111
So, NETIF_F_HW_VLAN_RX, NETIF_F_HW_VLAN_FILTER, NETIF_F_VLAN_CHALLENGED, and
NETIF_F_LLTX will be enabled, and they might not be enabled/supported. If
you take out the ~BR_FEAT_MASK then it will behave as I would expect
(verified with printks on the last patch).
On a side note: Wouldn't it make more sense to have NETIF_F_TSO defined as 16
in include/linux/netdevice.h (as it would be grouped with the other hardware
offload bits and the bit is free).
> >> +}
> >> +
> >> +/*
> >> + * Recomputes features using slave's features
> >> + */
> >> +static void br_features_recompute(struct net_bridge *br)
> >> +{
> >> + struct net_bridge_port *p;
> >> +
> >> + br->dev->features |= BR_FEAT_MASK;
> >
> > The OR is not needed. Just re-initialize features to BR_FEAT_MASK and
> > everything will take case of itself.
>
> Nope. Not correct. Because we might enable LLTX on the bridge, but not in
> BR_FEAT_MASK.
This is not the case. This is the same as re-doing the entire feature list
(as if it was being done initially). All that needs to be done is for
br->dev->features to have a initial value.
> I will post a patch in few hours with all stuff updated.
Great. Thanks.
Thanks,
Jon
^ permalink raw reply
* [PATCH] Super TSO v2
From: David S. Miller @ 2005-05-20 18:51 UTC (permalink / raw)
To: netdev
Ok, new version of the patch. Besides some cleanups,
the main change is packet send deferral at ACK arrival
time.
The issue is that an ACK can open up the window enough
for one MSS sized segment, but not necessarily enough
to send a significant portion of the TSO frame at the
head of the queue.
John Heffner described an algorithm to me which attempts
to defer so that we accumulate some more send window space.
It's quite effective.
At first, this change had a side effect I couldn't account
for, the congestion window would grow slowly and sometimes
not at all with this change. It turns out that we do not
grow the congestion window unless we had filled the current
congestion window. These tests are in tcp_input.c:tcp_ack()
where it goes:
prior_in_flight = tcp_packets_in_flight(tp);
...
if ((flag & FLAG_DATA_ACKED) &&
(tcp_vegas_enabled(tp) || prior_in_flight >= tp->snd_cwnd))
tcp_cong_avoid(tp, ack, seq_rtt);
tcp_cong_avoid() is what advances the congestion window.
This precondition is part of congestion window validation
(RFC2861), which basically states that the congestion window
should not be advanced if the connection is application limited
(and thus we are not really testing the link fully).
If we defer, to leave more space for sending larger chunks of
TSO frames, the "prior_in_flight >= tp->snd_cwnd" test will
not pass when the next ACK arrives. In order to fix this, yet
still preserve the intentions of the test, I added a tp->deferred
which keeps track of how much send window space we left intentionally
free to accumulate space.
I'm slowly gaining a lot of confidence in this patch, so more
testing would greatly be appreciated. It's pretty clear that
the "TSO Reloaded" scheme is not worth pursuing much further,
and that this stuff below is the way to go.
Thanks.
--- 1/include/linux/tcp.h.~1~ 2005-05-19 13:35:11.000000000 -0700
+++ 2/include/linux/tcp.h 2005-05-19 18:25:00.000000000 -0700
@@ -280,13 +280,15 @@ struct tcp_sock {
__u32 snd_wnd; /* The window we expect to receive */
__u32 max_window; /* Maximal window ever seen from peer */
__u32 pmtu_cookie; /* Last pmtu seen by socket */
- __u32 mss_cache; /* Cached effective mss, not including SACKS */
- __u16 mss_cache_std; /* Like mss_cache, but without TSO */
+ __u16 mss_cache; /* Cached effective mss, not including SACKS */
+ __u16 xmit_size_goal; /* Goal for segmenting output packets */
+ __u32 xmit_size_cache;/* Cache for keeping xmit_size_goal uptodate */
__u16 ext_header_len; /* Network protocol overhead (IP/IPv6 options) */
__u8 ca_state; /* State of fast-retransmit machine */
__u8 retransmits; /* Number of unrecovered RTO timeouts. */
__u16 advmss; /* Advertised MSS */
+ __u16 deferred; /* Packets deferred for segmentation */
__u32 window_clamp; /* Maximal window to advertise */
__u32 rcv_ssthresh; /* Current window clamp */
--- 1/include/net/sock.h.~1~ 2005-05-19 13:35:11.000000000 -0700
+++ 2/include/net/sock.h 2005-05-19 13:35:15.000000000 -0700
@@ -1130,13 +1130,16 @@ static inline void sk_stream_moderate_sn
static inline struct sk_buff *sk_stream_alloc_pskb(struct sock *sk,
int size, int mem, int gfp)
{
- struct sk_buff *skb = alloc_skb(size + sk->sk_prot->max_header, gfp);
+ struct sk_buff *skb;
+ int hdr_len;
+ hdr_len = SKB_DATA_ALIGN(sk->sk_prot->max_header);
+ skb = alloc_skb(size + hdr_len, gfp);
if (skb) {
skb->truesize += mem;
if (sk->sk_forward_alloc >= (int)skb->truesize ||
sk_stream_mem_schedule(sk, skb->truesize, 0)) {
- skb_reserve(skb, sk->sk_prot->max_header);
+ skb_reserve(skb, hdr_len);
return skb;
}
__kfree_skb(skb);
--- 1/include/net/tcp.h.~1~ 2005-05-19 13:35:11.000000000 -0700
+++ 2/include/net/tcp.h 2005-05-19 13:35:15.000000000 -0700
@@ -817,11 +817,18 @@ static inline int tcp_ack_scheduled(stru
return tp->ack.pending&TCP_ACK_SCHED;
}
-static __inline__ void tcp_dec_quickack_mode(struct tcp_sock *tp)
+static __inline__ void tcp_dec_quickack_mode(struct tcp_sock *tp, unsigned int pkts)
{
- if (tp->ack.quick && --tp->ack.quick == 0) {
- /* Leaving quickack mode we deflate ATO. */
- tp->ack.ato = TCP_ATO_MIN;
+ if (tp->ack.quick) {
+ if (pkts > tp->ack.quick)
+ tp->ack.quick = 0;
+ else
+ tp->ack.quick -= pkts;
+
+ if (!tp->ack.quick) {
+ /* Leaving quickack mode we deflate ATO. */
+ tp->ack.ato = TCP_ATO_MIN;
+ }
}
}
@@ -939,7 +946,14 @@ extern __u32 cookie_v4_init_sequence(str
/* tcp_output.c */
-extern int tcp_write_xmit(struct sock *, int nonagle);
+extern void __tcp_data_snd_check(struct sock *sk, struct sk_buff *skb);
+extern void __tcp_push_pending_frames(struct sock *sk,
+ struct tcp_sock *tp,
+ unsigned int cur_mss,
+ int nonagle);
+extern int tcp_may_send_now(struct sock *sk, struct tcp_sock *tp);
+extern int tcp_tso_mince(struct sock *sk, struct tcp_sock *tp,
+ struct sk_buff *skb);
extern int tcp_retransmit_skb(struct sock *, struct sk_buff *);
extern void tcp_xmit_retransmit_queue(struct sock *);
extern void tcp_simple_retransmit(struct sock *);
@@ -951,7 +965,7 @@ extern int tcp_write_wakeup(struct sock
extern void tcp_send_fin(struct sock *sk);
extern void tcp_send_active_reset(struct sock *sk, int priority);
extern int tcp_send_synack(struct sock *);
-extern void tcp_push_one(struct sock *, unsigned mss_now);
+extern void tcp_push_one(struct sock *, unsigned int mss_now);
extern void tcp_send_ack(struct sock *sk);
extern void tcp_send_delayed_ack(struct sock *sk);
@@ -1054,7 +1068,7 @@ static inline void tcp_reset_xmit_timer(
static inline void tcp_initialize_rcv_mss(struct sock *sk)
{
struct tcp_sock *tp = tcp_sk(sk);
- unsigned int hint = min(tp->advmss, tp->mss_cache_std);
+ unsigned int hint = min(tp->advmss, tp->mss_cache);
hint = min(hint, tp->rcv_wnd/2);
hint = min(hint, TCP_MIN_RCVMSS);
@@ -1353,23 +1367,23 @@ static inline void tcp_cwnd_validate(str
}
/* Set slow start threshould and cwnd not falling to slow start */
-static inline void __tcp_enter_cwr(struct tcp_sock *tp)
+static inline void __tcp_enter_cwr(struct tcp_sock *tp, unsigned int pkts)
{
tp->undo_marker = 0;
tp->snd_ssthresh = tcp_recalc_ssthresh(tp);
tp->snd_cwnd = min(tp->snd_cwnd,
- tcp_packets_in_flight(tp) + 1U);
+ tcp_packets_in_flight(tp) + pkts);
tp->snd_cwnd_cnt = 0;
tp->high_seq = tp->snd_nxt;
tp->snd_cwnd_stamp = tcp_time_stamp;
TCP_ECN_queue_cwr(tp);
}
-static inline void tcp_enter_cwr(struct tcp_sock *tp)
+static inline void tcp_enter_cwr(struct tcp_sock *tp, unsigned int pkts)
{
tp->prior_ssthresh = 0;
if (tp->ca_state < TCP_CA_CWR) {
- __tcp_enter_cwr(tp);
+ __tcp_enter_cwr(tp, pkts);
tcp_set_ca_state(tp, TCP_CA_CWR);
}
}
@@ -1397,74 +1411,6 @@ static __inline__ void tcp_minshall_upda
tp->snd_sml = TCP_SKB_CB(skb)->end_seq;
}
-/* Return 0, if packet can be sent now without violation Nagle's rules:
- 1. It is full sized.
- 2. Or it contains FIN.
- 3. Or TCP_NODELAY was set.
- 4. Or TCP_CORK is not set, and all sent packets are ACKed.
- With Minshall's modification: all sent small packets are ACKed.
- */
-
-static __inline__ int
-tcp_nagle_check(const struct tcp_sock *tp, const struct sk_buff *skb,
- unsigned mss_now, int nonagle)
-{
- return (skb->len < mss_now &&
- !(TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN) &&
- ((nonagle&TCP_NAGLE_CORK) ||
- (!nonagle &&
- tp->packets_out &&
- tcp_minshall_check(tp))));
-}
-
-extern void tcp_set_skb_tso_segs(struct sock *, struct sk_buff *);
-
-/* This checks if the data bearing packet SKB (usually sk->sk_send_head)
- * should be put on the wire right now.
- */
-static __inline__ int tcp_snd_test(struct sock *sk,
- struct sk_buff *skb,
- unsigned cur_mss, int nonagle)
-{
- struct tcp_sock *tp = tcp_sk(sk);
- int pkts = tcp_skb_pcount(skb);
-
- if (!pkts) {
- tcp_set_skb_tso_segs(sk, skb);
- pkts = tcp_skb_pcount(skb);
- }
-
- /* RFC 1122 - section 4.2.3.4
- *
- * We must queue if
- *
- * a) The right edge of this frame exceeds the window
- * b) There are packets in flight and we have a small segment
- * [SWS avoidance and Nagle algorithm]
- * (part of SWS is done on packetization)
- * Minshall version sounds: there are no _small_
- * segments in flight. (tcp_nagle_check)
- * c) We have too many packets 'in flight'
- *
- * Don't use the nagle rule for urgent data (or
- * for the final FIN -DaveM).
- *
- * Also, Nagle rule does not apply to frames, which
- * sit in the middle of queue (they have no chances
- * to get new data) and if room at tail of skb is
- * not enough to save something seriously (<32 for now).
- */
-
- /* Don't be strict about the congestion window for the
- * final FIN frame. -DaveM
- */
- return (((nonagle&TCP_NAGLE_PUSH) || tp->urg_mode
- || !tcp_nagle_check(tp, skb, cur_mss, nonagle)) &&
- (((tcp_packets_in_flight(tp) + (pkts-1)) < tp->snd_cwnd) ||
- (TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN)) &&
- !after(TCP_SKB_CB(skb)->end_seq, tp->snd_una + tp->snd_wnd));
-}
-
static __inline__ void tcp_check_probe_timer(struct sock *sk, struct tcp_sock *tp)
{
if (!tp->packets_out && !tp->pending)
@@ -1477,42 +1423,12 @@ static __inline__ int tcp_skb_is_last(co
return skb->next == (struct sk_buff *)&sk->sk_write_queue;
}
-/* Push out any pending frames which were held back due to
- * TCP_CORK or attempt at coalescing tiny packets.
- * The socket must be locked by the caller.
- */
-static __inline__ void __tcp_push_pending_frames(struct sock *sk,
- struct tcp_sock *tp,
- unsigned cur_mss,
- int nonagle)
-{
- struct sk_buff *skb = sk->sk_send_head;
-
- if (skb) {
- if (!tcp_skb_is_last(sk, skb))
- nonagle = TCP_NAGLE_PUSH;
- if (!tcp_snd_test(sk, skb, cur_mss, nonagle) ||
- tcp_write_xmit(sk, nonagle))
- tcp_check_probe_timer(sk, tp);
- }
- tcp_cwnd_validate(sk, tp);
-}
-
static __inline__ void tcp_push_pending_frames(struct sock *sk,
struct tcp_sock *tp)
{
__tcp_push_pending_frames(sk, tp, tcp_current_mss(sk, 1), tp->nonagle);
}
-static __inline__ int tcp_may_send_now(struct sock *sk, struct tcp_sock *tp)
-{
- struct sk_buff *skb = sk->sk_send_head;
-
- return (skb &&
- tcp_snd_test(sk, skb, tcp_current_mss(sk, 1),
- tcp_skb_is_last(sk, skb) ? TCP_NAGLE_PUSH : tp->nonagle));
-}
-
static __inline__ void tcp_init_wl(struct tcp_sock *tp, u32 ack, u32 seq)
{
tp->snd_wl1 = seq;
@@ -1986,7 +1902,7 @@ static inline void tcp_westwood_update_r
static inline __u32 __tcp_westwood_bw_rttmin(const struct tcp_sock *tp)
{
return max((tp->westwood.bw_est) * (tp->westwood.rtt_min) /
- (__u32) (tp->mss_cache_std),
+ (__u32) (tp->mss_cache),
2U);
}
--- 1/net/ipv4/tcp.c.~1~ 2005-05-19 13:35:11.000000000 -0700
+++ 2/net/ipv4/tcp.c 2005-05-19 13:35:15.000000000 -0700
@@ -634,7 +634,7 @@ static ssize_t do_tcp_sendpages(struct s
size_t psize, int flags)
{
struct tcp_sock *tp = tcp_sk(sk);
- int mss_now;
+ int mss_now, size_goal;
int err;
ssize_t copied;
long timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT);
@@ -647,6 +647,7 @@ static ssize_t do_tcp_sendpages(struct s
clear_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);
mss_now = tcp_current_mss(sk, !(flags&MSG_OOB));
+ size_goal = tp->xmit_size_goal;
copied = 0;
err = -EPIPE;
@@ -660,7 +661,7 @@ static ssize_t do_tcp_sendpages(struct s
int offset = poffset % PAGE_SIZE;
int size = min_t(size_t, psize, PAGE_SIZE - offset);
- if (!sk->sk_send_head || (copy = mss_now - skb->len) <= 0) {
+ if (!sk->sk_send_head || (copy = size_goal - skb->len) <= 0) {
new_segment:
if (!sk_stream_memory_free(sk))
goto wait_for_sndbuf;
@@ -671,7 +672,7 @@ new_segment:
goto wait_for_memory;
skb_entail(sk, tp, skb);
- copy = mss_now;
+ copy = size_goal;
}
if (copy > size)
@@ -712,7 +713,7 @@ new_segment:
if (!(psize -= copy))
goto out;
- if (skb->len != mss_now || (flags & MSG_OOB))
+ if (skb->len != size_goal || (flags & MSG_OOB))
continue;
if (forced_push(tp)) {
@@ -732,6 +733,7 @@ wait_for_memory:
goto do_error;
mss_now = tcp_current_mss(sk, !(flags&MSG_OOB));
+ size_goal = tp->xmit_size_goal;
}
out:
@@ -773,15 +775,11 @@ ssize_t tcp_sendpage(struct socket *sock
static inline int select_size(struct sock *sk, struct tcp_sock *tp)
{
- int tmp = tp->mss_cache_std;
+ int tmp = tp->mss_cache;
- if (sk->sk_route_caps & NETIF_F_SG) {
- int pgbreak = SKB_MAX_HEAD(MAX_TCP_HEADER);
+ if (sk->sk_route_caps & NETIF_F_SG)
+ tmp = 0;
- if (tmp >= pgbreak &&
- tmp <= pgbreak + (MAX_SKB_FRAGS - 1) * PAGE_SIZE)
- tmp = pgbreak;
- }
return tmp;
}
@@ -792,7 +790,7 @@ int tcp_sendmsg(struct kiocb *iocb, stru
struct tcp_sock *tp = tcp_sk(sk);
struct sk_buff *skb;
int iovlen, flags;
- int mss_now;
+ int mss_now, size_goal;
int err, copied;
long timeo;
@@ -811,6 +809,7 @@ int tcp_sendmsg(struct kiocb *iocb, stru
clear_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);
mss_now = tcp_current_mss(sk, !(flags&MSG_OOB));
+ size_goal = tp->xmit_size_goal;
/* Ok commence sending. */
iovlen = msg->msg_iovlen;
@@ -833,7 +832,7 @@ int tcp_sendmsg(struct kiocb *iocb, stru
skb = sk->sk_write_queue.prev;
if (!sk->sk_send_head ||
- (copy = mss_now - skb->len) <= 0) {
+ (copy = size_goal - skb->len) <= 0) {
new_segment:
/* Allocate new segment. If the interface is SG,
@@ -856,7 +855,7 @@ new_segment:
skb->ip_summed = CHECKSUM_HW;
skb_entail(sk, tp, skb);
- copy = mss_now;
+ copy = size_goal;
}
/* Try to append data to the end of skb. */
@@ -891,11 +890,6 @@ new_segment:
tcp_mark_push(tp, skb);
goto new_segment;
} else if (page) {
- /* If page is cached, align
- * offset to L1 cache boundary
- */
- off = (off + L1_CACHE_BYTES - 1) &
- ~(L1_CACHE_BYTES - 1);
if (off == PAGE_SIZE) {
put_page(page);
TCP_PAGE(sk) = page = NULL;
@@ -956,7 +950,7 @@ new_segment:
if ((seglen -= copy) == 0 && iovlen == 0)
goto out;
- if (skb->len != mss_now || (flags & MSG_OOB))
+ if (skb->len != size_goal || (flags & MSG_OOB))
continue;
if (forced_push(tp)) {
@@ -976,6 +970,7 @@ wait_for_memory:
goto do_error;
mss_now = tcp_current_mss(sk, !(flags&MSG_OOB));
+ size_goal = tp->xmit_size_goal;
}
}
@@ -2135,7 +2130,7 @@ void tcp_get_info(struct sock *sk, struc
info->tcpi_rto = jiffies_to_usecs(tp->rto);
info->tcpi_ato = jiffies_to_usecs(tp->ack.ato);
- info->tcpi_snd_mss = tp->mss_cache_std;
+ info->tcpi_snd_mss = tp->mss_cache;
info->tcpi_rcv_mss = tp->ack.rcv_mss;
info->tcpi_unacked = tp->packets_out;
@@ -2185,7 +2180,7 @@ int tcp_getsockopt(struct sock *sk, int
switch (optname) {
case TCP_MAXSEG:
- val = tp->mss_cache_std;
+ val = tp->mss_cache;
if (!val && ((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN)))
val = tp->rx_opt.user_mss;
break;
--- 1/net/ipv4/tcp_input.c.~1~ 2005-05-19 13:35:11.000000000 -0700
+++ 2/net/ipv4/tcp_input.c 2005-05-19 21:25:38.000000000 -0700
@@ -805,10 +805,10 @@ __u32 tcp_init_cwnd(struct tcp_sock *tp,
__u32 cwnd = (dst ? dst_metric(dst, RTAX_INITCWND) : 0);
if (!cwnd) {
- if (tp->mss_cache_std > 1460)
+ if (tp->mss_cache > 1460)
cwnd = 2;
else
- cwnd = (tp->mss_cache_std > 1095) ? 3 : 4;
+ cwnd = (tp->mss_cache > 1095) ? 3 : 4;
}
return min_t(__u32, cwnd, tp->snd_cwnd_clamp);
}
@@ -974,14 +974,6 @@ tcp_sacktag_write_queue(struct sock *sk,
int flag = 0;
int i;
- /* So, SACKs for already sent large segments will be lost.
- * Not good, but alternative is to resegment the queue. */
- if (sk->sk_route_caps & NETIF_F_TSO) {
- sk->sk_route_caps &= ~NETIF_F_TSO;
- sock_set_flag(sk, SOCK_NO_LARGESEND);
- tp->mss_cache = tp->mss_cache_std;
- }
-
if (!tp->sacked_out)
tp->fackets_out = 0;
prior_fackets = tp->fackets_out;
@@ -1038,6 +1030,15 @@ tcp_sacktag_write_queue(struct sock *sk,
if(!before(TCP_SKB_CB(skb)->seq, end_seq))
break;
+ /* Even if mincing a TSO frame fails, we
+ * continue anyways. We will end up with
+ * more coarse SACK information, but it is
+ * better than ignoring all the SACK information
+ * altogether.
+ */
+ if (tcp_skb_pcount(skb) > 1)
+ tcp_tso_mince(sk, tp, skb);
+
fack_count += tcp_skb_pcount(skb);
in_sack = !after(start_seq, TCP_SKB_CB(skb)->seq) &&
@@ -1142,7 +1143,7 @@ tcp_sacktag_write_queue(struct sock *sk,
(IsFack(tp) ||
!before(lost_retrans,
TCP_SKB_CB(skb)->ack_seq + tp->reordering *
- tp->mss_cache_std))) {
+ tp->mss_cache))) {
TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_RETRANS;
tp->retrans_out -= tcp_skb_pcount(skb);
@@ -1782,7 +1783,7 @@ static void tcp_try_to_open(struct sock
tp->retrans_stamp = 0;
if (flag&FLAG_ECE)
- tcp_enter_cwr(tp);
+ tcp_enter_cwr(tp, 1);
if (tp->ca_state != TCP_CA_CWR) {
int state = TCP_CA_Open;
@@ -2170,7 +2171,7 @@ static void vegas_cong_avoid(struct tcp_
* is the cwnd during the previous RTT.
*/
old_wnd = (tp->vegas.beg_snd_nxt - tp->vegas.beg_snd_una) /
- tp->mss_cache_std;
+ tp->mss_cache;
old_snd_cwnd = tp->vegas.beg_snd_cwnd;
/* Save the extent of the current window so we can use this
@@ -2799,19 +2800,19 @@ static void westwood_dupack_update(struc
{
struct tcp_sock *tp = tcp_sk(sk);
- tp->westwood.accounted += tp->mss_cache_std;
- tp->westwood.cumul_ack = tp->mss_cache_std;
+ tp->westwood.accounted += tp->mss_cache;
+ tp->westwood.cumul_ack = tp->mss_cache;
}
static inline int westwood_may_change_cumul(struct tcp_sock *tp)
{
- return (tp->westwood.cumul_ack > tp->mss_cache_std);
+ return (tp->westwood.cumul_ack > tp->mss_cache);
}
static inline void westwood_partial_update(struct tcp_sock *tp)
{
tp->westwood.accounted -= tp->westwood.cumul_ack;
- tp->westwood.cumul_ack = tp->mss_cache_std;
+ tp->westwood.cumul_ack = tp->mss_cache;
}
static inline void westwood_complete_update(struct tcp_sock *tp)
@@ -2932,7 +2933,7 @@ static int tcp_ack(struct sock *sk, stru
if (!prior_packets)
goto no_queue;
- prior_in_flight = tcp_packets_in_flight(tp);
+ prior_in_flight = tcp_packets_in_flight(tp) + tp->deferred;
/* See if we can take anything off of the retransmit queue. */
flag |= tcp_clean_rtx_queue(sk, &seq_rtt);
@@ -2948,7 +2949,7 @@ static int tcp_ack(struct sock *sk, stru
tcp_cong_avoid(tp, ack, seq_rtt);
tcp_fastretrans_alert(sk, prior_snd_una, prior_packets, flag);
} else {
- if ((flag & FLAG_DATA_ACKED) &&
+ if ((flag & FLAG_DATA_ACKED) &&
(tcp_vegas_enabled(tp) || prior_in_flight >= tp->snd_cwnd))
tcp_cong_avoid(tp, ack, seq_rtt);
}
@@ -3948,11 +3949,11 @@ static void tcp_new_space(struct sock *s
{
struct tcp_sock *tp = tcp_sk(sk);
- if (tp->packets_out < tp->snd_cwnd &&
+ if ((tp->packets_out + tp->deferred) < tp->snd_cwnd &&
!(sk->sk_userlocks & SOCK_SNDBUF_LOCK) &&
!tcp_memory_pressure &&
atomic_read(&tcp_memory_allocated) < sysctl_tcp_mem[0]) {
- int sndmem = max_t(u32, tp->rx_opt.mss_clamp, tp->mss_cache_std) +
+ int sndmem = max_t(u32, tp->rx_opt.mss_clamp, tp->mss_cache) +
MAX_TCP_HEADER + 16 + sizeof(struct sk_buff),
demanded = max_t(unsigned int, tp->snd_cwnd,
tp->reordering + 1);
@@ -3975,16 +3976,6 @@ static inline void tcp_check_space(struc
}
}
-static void __tcp_data_snd_check(struct sock *sk, struct sk_buff *skb)
-{
- struct tcp_sock *tp = tcp_sk(sk);
-
- if (after(TCP_SKB_CB(skb)->end_seq, tp->snd_una + tp->snd_wnd) ||
- tcp_packets_in_flight(tp) >= tp->snd_cwnd ||
- tcp_write_xmit(sk, tp->nonagle))
- tcp_check_probe_timer(sk, tp);
-}
-
static __inline__ void tcp_data_snd_check(struct sock *sk)
{
struct sk_buff *skb = sk->sk_send_head;
--- 1/net/ipv4/tcp_ipv4.c.~1~ 2005-05-19 13:35:11.000000000 -0700
+++ 2/net/ipv4/tcp_ipv4.c 2005-05-19 13:35:15.000000000 -0700
@@ -2060,7 +2060,8 @@ static int tcp_v4_init_sock(struct sock
*/
tp->snd_ssthresh = 0x7fffffff; /* Infinity */
tp->snd_cwnd_clamp = ~0;
- tp->mss_cache_std = tp->mss_cache = 536;
+ tp->mss_cache = 536;
+ tp->xmit_size_cache = ~0;
tp->reordering = sysctl_tcp_reordering;
--- 1/net/ipv4/tcp_output.c.~1~ 2005-05-19 13:35:11.000000000 -0700
+++ 2/net/ipv4/tcp_output.c 2005-05-19 21:34:15.000000000 -0700
@@ -58,6 +58,7 @@ static inline void update_send_head(stru
if (sk->sk_send_head == (struct sk_buff *)&sk->sk_write_queue)
sk->sk_send_head = NULL;
tp->snd_nxt = TCP_SKB_CB(skb)->end_seq;
+ tp->deferred = 0;
tcp_packets_out_inc(sk, tp, skb);
}
@@ -141,11 +142,11 @@ static inline void tcp_event_data_sent(s
tp->ack.pingpong = 1;
}
-static __inline__ void tcp_event_ack_sent(struct sock *sk)
+static __inline__ void tcp_event_ack_sent(struct sock *sk, unsigned int pkts)
{
struct tcp_sock *tp = tcp_sk(sk);
- tcp_dec_quickack_mode(tp);
+ tcp_dec_quickack_mode(tp, pkts);
tcp_clear_xmit_timer(sk, TCP_TIME_DACK);
}
@@ -361,7 +362,7 @@ static int tcp_transmit_skb(struct sock
tp->af_specific->send_check(sk, th, skb->len, skb);
if (tcb->flags & TCPCB_FLAG_ACK)
- tcp_event_ack_sent(sk);
+ tcp_event_ack_sent(sk, tcp_skb_pcount(skb));
if (skb->len != tcp_header_size)
tcp_event_data_sent(tp, skb, sk);
@@ -372,7 +373,7 @@ static int tcp_transmit_skb(struct sock
if (err <= 0)
return err;
- tcp_enter_cwr(tp);
+ tcp_enter_cwr(tp, tcp_skb_pcount(skb));
/* NET_XMIT_CN is special. It does not guarantee,
* that this packet is lost. It tells that device
@@ -409,42 +410,11 @@ static void tcp_queue_skb(struct sock *s
sk->sk_send_head = skb;
}
-static inline void tcp_tso_set_push(struct sk_buff *skb)
-{
- /* Force push to be on for any TSO frames to workaround
- * problems with busted implementations like Mac OS-X that
- * hold off socket receive wakeups until push is seen.
- */
- if (tcp_skb_pcount(skb) > 1)
- TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_PSH;
-}
-
-/* Send _single_ skb sitting at the send head. This function requires
- * true push pending frames to setup probe timer etc.
- */
-void tcp_push_one(struct sock *sk, unsigned cur_mss)
-{
- struct tcp_sock *tp = tcp_sk(sk);
- struct sk_buff *skb = sk->sk_send_head;
-
- if (tcp_snd_test(sk, skb, cur_mss, TCP_NAGLE_PUSH)) {
- /* Send it out now. */
- TCP_SKB_CB(skb)->when = tcp_time_stamp;
- tcp_tso_set_push(skb);
- if (!tcp_transmit_skb(sk, skb_clone(skb, sk->sk_allocation))) {
- sk->sk_send_head = NULL;
- tp->snd_nxt = TCP_SKB_CB(skb)->end_seq;
- tcp_packets_out_inc(sk, tp, skb);
- return;
- }
- }
-}
-
void tcp_set_skb_tso_segs(struct sock *sk, struct sk_buff *skb)
{
struct tcp_sock *tp = tcp_sk(sk);
- if (skb->len <= tp->mss_cache_std ||
+ if (skb->len <= tp->mss_cache ||
!(sk->sk_route_caps & NETIF_F_TSO)) {
/* Avoid the costly divide in the normal
* non-TSO case.
@@ -454,10 +424,10 @@ void tcp_set_skb_tso_segs(struct sock *s
} else {
unsigned int factor;
- factor = skb->len + (tp->mss_cache_std - 1);
- factor /= tp->mss_cache_std;
+ factor = skb->len + (tp->mss_cache - 1);
+ factor /= tp->mss_cache;
skb_shinfo(skb)->tso_segs = factor;
- skb_shinfo(skb)->tso_size = tp->mss_cache_std;
+ skb_shinfo(skb)->tso_size = tp->mss_cache;
}
}
@@ -662,7 +632,7 @@ unsigned int tcp_sync_mss(struct sock *s
/* And store cached results */
tp->pmtu_cookie = pmtu;
- tp->mss_cache = tp->mss_cache_std = mss_now;
+ tp->mss_cache = mss_now;
return mss_now;
}
@@ -674,117 +644,493 @@ unsigned int tcp_sync_mss(struct sock *s
* cannot be large. However, taking into account rare use of URG, this
* is not a big flaw.
*/
+static inline u32 compute_xmit_cache(u32 mss, int sacks, int tso_enabled)
+{
+ u32 ret = (mss << 16) | sacks;
-unsigned int tcp_current_mss(struct sock *sk, int large)
+ if (tso_enabled)
+ ret |= (1 << 8);
+
+ return ret;
+}
+
+unsigned int tcp_current_mss(struct sock *sk, int large_allowed)
{
struct tcp_sock *tp = tcp_sk(sk);
struct dst_entry *dst = __sk_dst_get(sk);
- unsigned int do_large, mss_now;
+ u32 mss_now;
+ u32 xmit_cache;
+ int doing_tso = 0;
+
+ mss_now = tp->mss_cache;
+
+ if (large_allowed &&
+ (sk->sk_route_caps & NETIF_F_TSO) &&
+ !tp->urg_mode)
+ doing_tso = 1;
- mss_now = tp->mss_cache_std;
if (dst) {
u32 mtu = dst_mtu(dst);
if (mtu != tp->pmtu_cookie)
mss_now = tcp_sync_mss(sk, mtu);
}
- do_large = (large &&
- (sk->sk_route_caps & NETIF_F_TSO) &&
- !tp->urg_mode);
-
- if (do_large) {
- unsigned int large_mss, factor, limit;
-
- large_mss = 65535 - tp->af_specific->net_header_len -
- tp->ext_header_len - tp->tcp_header_len;
-
- if (tp->max_window && large_mss > (tp->max_window>>1))
- large_mss = max((tp->max_window>>1),
- 68U - tp->tcp_header_len);
-
- factor = large_mss / mss_now;
-
- /* Always keep large mss multiple of real mss, but
- * do not exceed 1/tso_win_divisor of the congestion window
- * so we can keep the ACK clock ticking and minimize
- * bursting.
- */
- limit = tp->snd_cwnd;
- if (sysctl_tcp_tso_win_divisor)
- limit /= sysctl_tcp_tso_win_divisor;
- limit = max(1U, limit);
- if (factor > limit)
- factor = limit;
-
- tp->mss_cache = mss_now * factor;
-
- mss_now = tp->mss_cache;
- }
+ /* If the MSS, the TSO state, or the number of SACK blocks
+ * changes, we have to recompute tp->xmit_size_goal.
+ */
+ xmit_cache = compute_xmit_cache(mss_now, tp->rx_opt.eff_sacks,
+ doing_tso);
if (tp->rx_opt.eff_sacks)
mss_now -= (TCPOLEN_SACK_BASE_ALIGNED +
(tp->rx_opt.eff_sacks * TCPOLEN_SACK_PERBLOCK));
+
+ if (tp->xmit_size_cache != xmit_cache) {
+ u16 xmit_size_goal = mss_now;
+
+ if (doing_tso) {
+ xmit_size_goal = 65535 -
+ tp->af_specific->net_header_len -
+ tp->ext_header_len - tp->tcp_header_len;
+
+ if (tp->rx_opt.eff_sacks)
+ xmit_size_goal -= (TCPOLEN_SACK_BASE_ALIGNED +
+ (tp->rx_opt.eff_sacks *
+ TCPOLEN_SACK_PERBLOCK));
+
+ xmit_size_goal -= (xmit_size_goal % mss_now);
+ }
+ tp->xmit_size_goal = xmit_size_goal;
+ tp->xmit_size_cache = xmit_cache;
+ }
+
return mss_now;
}
+static inline unsigned int tso_size_limit(u32 window, unsigned int mss_now, unsigned int cwnd)
+{
+ u32 cwnd_len;
+
+ cwnd_len = mss_now * cwnd;
+ return min(window, cwnd_len);
+}
+
+/* Can at least one segment of SKB be sent right now, according
+ * to the congestion window rules? If so, return how many segments
+ * are allowed.
+ */
+static inline unsigned int tcp_cwnd_test(struct tcp_sock *tp, struct sk_buff *skb)
+{
+ u32 in_flight, cwnd;
+
+ /* Don't be strict about the congestion window for the
+ * final FIN frame. -DaveM
+ */
+ if (TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN)
+ return 1;
+
+ in_flight = tcp_packets_in_flight(tp);
+ cwnd = tp->snd_cwnd;
+ if (in_flight < cwnd)
+ return (cwnd - in_flight);
+
+ return 0;
+}
+
+/* This must be invoked the first time we consider transmitting
+ * SKB onto the wire.
+ */
+static inline int tcp_init_tso_segs(struct sock *sk, struct sk_buff *skb)
+{
+ int tso_segs = tcp_skb_pcount(skb);
+
+ if (!tso_segs) {
+ tcp_set_skb_tso_segs(sk, skb);
+ tso_segs = tcp_skb_pcount(skb);
+ }
+ return tso_segs;
+}
+
+/* Return 0, if packet can be sent now without violation Nagle's rules:
+ * 1. It is full sized.
+ * 2. Or it contains FIN.
+ * 3. Or TCP_NODELAY was set.
+ * 4. Or TCP_CORK is not set, and all sent packets are ACKed.
+ * With Minshall's modification: all sent small packets are ACKed.
+ */
+
+static inline int tcp_nagle_check(const struct tcp_sock *tp,
+ const struct sk_buff *skb,
+ unsigned mss_now, int nonagle)
+{
+ return (skb->len < mss_now &&
+ !(TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN) &&
+ ((nonagle&TCP_NAGLE_CORK) ||
+ (!nonagle &&
+ tp->packets_out &&
+ tcp_minshall_check(tp))));
+}
+
+/* Return non-zero if the Nagle test allows this packet to be
+ * sent now.
+ */
+static inline int tcp_nagle_test(struct tcp_sock *tp, struct sk_buff *skb, unsigned int cur_mss, int nonagle)
+{
+ /* Nagle rule does not apply to frames, which
+ * sit in the middle of queue (they have no chances
+ * to get new data).
+ *
+ * This is implemented in the callers, where they modify
+ * the 'nonagle' argument based upon the location of SKB
+ * in the send queue.
+ */
+ if (nonagle & TCP_NAGLE_PUSH)
+ return 1;
+
+ /* Don't use the nagle rule for urgent data (or
+ * for the final FIN -DaveM).
+ */
+ if (tp->urg_mode ||
+ (TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN))
+ return 1;
+
+ if (!tcp_nagle_check(tp, skb, cur_mss, nonagle))
+ return 1;
+
+ return 0;
+}
+
+/* Does at least the first segment of SKB fit into the congestion
+ * window?
+ */
+static inline int tcp_snd_wnd_test(struct tcp_sock *tp, struct sk_buff *skb, unsigned int cur_mss)
+{
+ u32 end_seq = TCP_SKB_CB(skb)->end_seq;
+
+ if (skb->len > cur_mss)
+ end_seq = TCP_SKB_CB(skb)->seq + cur_mss;
+
+ return !after(end_seq, tp->snd_una + tp->snd_wnd);
+}
+
+/* This checks if the data bearing packet SKB (usually
+ * sk->sk_send_head) should be put on the wire right now. If so, it
+ * returns the number of packets allowed by the congestion window.
+ */
+static unsigned int tcp_snd_test(struct sock *sk, struct sk_buff *skb,
+ unsigned cur_mss, int nonagle)
+{
+ struct tcp_sock *tp = tcp_sk(sk);
+ unsigned int cwnd_quota;
+
+ if (!tcp_nagle_test(tp, skb, cur_mss, nonagle))
+ return 0;
+
+ cwnd_quota = tcp_cwnd_test(tp, skb);
+ if (cwnd_quota &&
+ !tcp_snd_wnd_test(tp, skb, cur_mss))
+ cwnd_quota = 0;
+
+ return cwnd_quota;
+}
+
+int tcp_may_send_now(struct sock *sk, struct tcp_sock *tp)
+{
+ struct sk_buff *skb = sk->sk_send_head;
+
+ return (skb &&
+ tcp_snd_test(sk, skb, tcp_current_mss(sk, 1),
+ tcp_skb_is_last(sk, skb) ? TCP_NAGLE_PUSH : tp->nonagle));
+}
+
+/* Trim TSO SKB to LEN bytes, put the remaining data into a new packet
+ * which is put after SKB on the list. It is very much like
+ * tcp_fragment() except that it may make several kinds of assumptions
+ * in order to speed up the splitting operation. In particular, we
+ * know that all the data is in scatter-gather pages, and that the
+ * packet has never been sent out before (and thus is not cloned).
+ */
+static int tso_fragment(struct sock *sk, struct sk_buff *skb, unsigned int len)
+{
+ struct sk_buff *buff;
+ int nlen = skb->len - len;
+ u16 flags;
+
+ /* All of a TSO frame must be composed of paged data. */
+ BUG_ON(skb->len != skb->data_len);
+
+ buff = sk_stream_alloc_pskb(sk, 0, 0, GFP_ATOMIC);
+ if (unlikely(buff == NULL))
+ return -ENOMEM;
+ sk_charge_skb(sk, buff);
+
+ buff->truesize += nlen;
+ skb->truesize -= nlen;
+
+ /* Correct the sequence numbers. */
+ TCP_SKB_CB(buff)->seq = TCP_SKB_CB(skb)->seq + len;
+ TCP_SKB_CB(buff)->end_seq = TCP_SKB_CB(skb)->end_seq;
+ TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(buff)->seq;
+
+ /* PSH and FIN should only be set in the second packet. */
+ flags = TCP_SKB_CB(skb)->flags;
+ TCP_SKB_CB(skb)->flags = flags & ~(TCPCB_FLAG_FIN|TCPCB_FLAG_PSH);
+ TCP_SKB_CB(buff)->flags = flags;
+
+ /* This packet was never sent out yet, so no SACK bits. */
+ TCP_SKB_CB(buff)->sacked = 0;
+
+ buff->ip_summed = skb->ip_summed = CHECKSUM_HW;
+ skb_split(skb, buff, len);
+
+ /* Fix up tso_factor for both original and new SKB. */
+ tcp_set_skb_tso_segs(sk, skb);
+ tcp_set_skb_tso_segs(sk, buff);
+
+ /* Link BUFF into the send queue. */
+ __skb_append(skb, buff);
+
+ return 0;
+}
+
+/* Split TSO frame SKB into one MSS sized packet, then the rest.
+ * This is called during SACK processing when some SACK information
+ * hits a TSO packet.
+ */
+int tcp_tso_mince(struct sock *sk, struct tcp_sock *tp, struct sk_buff *skb)
+{
+ unsigned int mss_now = tcp_current_mss(sk, 1);
+
+ BUG_ON(tcp_skb_pcount(skb) <= 1);
+
+ /* We cannot use tso_fragment() in this case, because
+ * the packet has been sent once already and thus may
+ * be cloned or have other non-trivial details to deal
+ * with.
+ */
+ return tcp_fragment(sk, skb, mss_now);
+}
+
/* This routine writes packets to the network. It advances the
* send_head. This happens as incoming acks open up the remote
- * window for us.
+ * window for us. Caller makes sure sk_send_head is non-NULL.
*
* Returns 1, if no segments are in flight and we have queued segments, but
* cannot send anything now because of SWS or another problem.
*/
-int tcp_write_xmit(struct sock *sk, int nonagle)
+static int tcp_write_xmit(struct sock *sk, int nonagle)
{
struct tcp_sock *tp = tcp_sk(sk);
- unsigned int mss_now;
+ unsigned int mss_now, cwnd_quota, sent_pkts, tso_segs;
+ struct sk_buff *skb;
/* If we are closed, the bytes will have to remain here.
* In time closedown will finish, we empty the write queue and all
* will be happy.
*/
- if (sk->sk_state != TCP_CLOSE) {
- struct sk_buff *skb;
- int sent_pkts = 0;
+ if (unlikely(sk->sk_state == TCP_CLOSE))
+ return 0;
- /* Account for SACKS, we may need to fragment due to this.
- * It is just like the real MSS changing on us midstream.
- * We also handle things correctly when the user adds some
- * IP options mid-stream. Silly to do, but cover it.
- */
- mss_now = tcp_current_mss(sk, 1);
+ /* Account for SACKS, we may need to fragment due to this.
+ * It is just like the real MSS changing on us midstream.
+ * We also handle things correctly when the user adds some
+ * IP options mid-stream. Silly to do, but cover it.
+ */
+ mss_now = tcp_current_mss(sk, 1);
- while ((skb = sk->sk_send_head) &&
- tcp_snd_test(sk, skb, mss_now,
- tcp_skb_is_last(sk, skb) ? nonagle :
- TCP_NAGLE_PUSH)) {
- if (skb->len > mss_now) {
- if (tcp_fragment(sk, skb, mss_now))
- break;
- }
+ skb = sk->sk_send_head;
+ tso_segs = tcp_init_tso_segs(sk, skb);
+ cwnd_quota = tcp_cwnd_test(tp, skb);
+ sent_pkts = 0;
+
+ while (cwnd_quota) {
+ if (!tcp_nagle_test(tp, skb, mss_now,
+ (tcp_skb_is_last(sk, skb) ?
+ nonagle : TCP_NAGLE_PUSH)))
+ break;
- TCP_SKB_CB(skb)->when = tcp_time_stamp;
- tcp_tso_set_push(skb);
- if (tcp_transmit_skb(sk, skb_clone(skb, GFP_ATOMIC)))
- break;
+ if (!tcp_snd_wnd_test(tp, skb, mss_now))
+ break;
+
+ BUG_ON(!tso_segs);
- /* Advance the send_head. This one is sent out.
- * This call will increment packets_out.
+ if (tso_segs > 1) {
+ u32 window_seq = tp->snd_una + tp->snd_wnd;
+ u32 limit = tso_size_limit(window_seq -
+ TCP_SKB_CB(skb)->seq,
+ mss_now, cwnd_quota);
+ u32 naglet_size;
+
+ /* If we have sub-mss chunk at the tail,
+ * split it off so that we nagle properly.
*/
- update_send_head(sk, tp, skb);
+ naglet_size = (skb->len % mss_now);
+ if (naglet_size)
+ limit = min(limit, skb->len - naglet_size);
- tcp_minshall_update(tp, mss_now, skb);
- sent_pkts = 1;
+ if (skb->len > limit) {
+ if (tso_fragment(sk, skb, limit))
+ break;
+ }
+ } else if (skb->len > mss_now) {
+ if (tcp_fragment(sk, skb, mss_now))
+ break;
}
- if (sent_pkts) {
- tcp_cwnd_validate(sk, tp);
- return 0;
+ TCP_SKB_CB(skb)->when = tcp_time_stamp;
+ if (tcp_transmit_skb(sk, skb_clone(skb, GFP_ATOMIC)))
+ break;
+
+ /* Advance the send_head. This one is sent out.
+ * This call will increment packets_out.
+ */
+ update_send_head(sk, tp, skb);
+
+ tcp_minshall_update(tp, mss_now, skb);
+ sent_pkts++;
+
+ cwnd_quota -= tcp_skb_pcount(skb);
+ skb = sk->sk_send_head;
+ if (!skb)
+ break;
+ tso_segs = tcp_init_tso_segs(sk, skb);
+ }
+
+ if (sent_pkts) {
+ tcp_cwnd_validate(sk, tp);
+ return 0;
+ }
+
+ return !tp->packets_out && sk->sk_send_head;
+}
+
+/* Push out any pending frames which were held back due to
+ * TCP_CORK or attempt at coalescing tiny packets.
+ * The socket must be locked by the caller.
+ */
+void __tcp_push_pending_frames(struct sock *sk,
+ struct tcp_sock *tp,
+ unsigned int cur_mss,
+ int nonagle)
+{
+ if (sk->sk_send_head) {
+ if (tcp_write_xmit(sk, nonagle))
+ tcp_check_probe_timer(sk, tp);
+ }
+}
+
+/* As ACKs arrive and the send and congestion windows potentially
+ * open up, we call this to try and make write queue transmit
+ * progress.
+ *
+ * The caller has the socket locked, and has verified that
+ * sk->sk_send_head is not NULL.
+ */
+void __tcp_data_snd_check(struct sock *sk, struct sk_buff *skb)
+{
+ struct tcp_sock *tp = tcp_sk(sk);
+ unsigned int tso_segs = tcp_init_tso_segs(sk, skb);
+ u32 in_flight;
+
+ /* First, do some very cheap tests to short circuit
+ * all the expensive ones coming up.
+ */
+ if (after(TCP_SKB_CB(skb)->seq + tp->mss_cache,
+ tp->snd_una + tp->snd_wnd))
+ goto check_probe_timer;
+
+ in_flight = tcp_packets_in_flight(tp);
+ if (in_flight >= tp->snd_cwnd)
+ goto check_probe_timer;
+
+ if (tso_segs > 1) {
+ u32 send_win, cong_win, limit, chunk;
+
+ /* Try to defer sending, if possible, in order
+ * to minimize the amount of TSO splitting we do.
+ * This algorithm is from John Heffner.
+ *
+ * First, we must have at least some packets
+ * in flight to legally defer. Otherwise,
+ * no ACKs can be expected.
+ */
+ if (!in_flight)
+ goto send_it;
+
+ send_win = (tp->snd_una + tp->snd_wnd) - TCP_SKB_CB(skb)->seq;
+
+ /* From in_flight test above, we know that
+ * cwnd > in_flight.
+ */
+ cong_win = (tp->snd_cwnd - in_flight) * tp->mss_cache;
+
+ limit = min(send_win, cong_win);
+
+ /* If sk_send_head can be sent fully now, just do it. */
+ if (!after(TCP_SKB_CB(skb)->end_seq, tp->snd_una + limit))
+ goto send_it;
+
+ /* If at least some fraction of a window is available,
+ * just use it.
+ */
+ chunk = min(tp->snd_wnd, tp->snd_cwnd * tp->mss_cache);
+ chunk /= sysctl_tcp_tso_win_divisor;
+ if (limit >= chunk)
+ goto send_it;
+
+ /* Ok, it looks like it is advisable to defer. */
+ tp->deferred = tp->snd_cwnd - in_flight;
+ return;
+ }
+send_it:
+
+ if (tcp_write_xmit(sk, tp->nonagle))
+ goto check_probe_timer;
+ return;
+
+check_probe_timer:
+ tcp_check_probe_timer(sk, tp);
+}
+
+/* Send _single_ skb sitting at the send head. This function requires
+ * true push pending frames to setup probe timer etc. Caller makes
+ * sure that sk->sk_send_head is non-NULL.
+ */
+void tcp_push_one(struct sock *sk, unsigned int cur_mss)
+{
+ struct tcp_sock *tp = tcp_sk(sk);
+ struct sk_buff *skb = sk->sk_send_head;
+ unsigned int tso_segs, cwnd_quota;
+
+ tso_segs = tcp_init_tso_segs(sk, skb);
+ cwnd_quota = tcp_snd_test(sk, skb, cur_mss, TCP_NAGLE_PUSH);
+ if (cwnd_quota) {
+ u32 window_seq;
+
+ window_seq = tp->snd_una + tp->snd_wnd;
+ BUG_ON(!tso_segs);
+
+ if (tso_segs > 1) {
+ u32 limit = tso_size_limit(window_seq -
+ TCP_SKB_CB(skb)->seq,
+ cur_mss, cwnd_quota);
+
+ if (skb->len > limit) {
+ if (tso_fragment(sk, skb, limit))
+ return;
+ }
+ } else if (skb->len > cur_mss) {
+ if (tcp_fragment(sk, skb, cur_mss))
+ return;
}
- return !tp->packets_out && sk->sk_send_head;
+ /* Send it out now. */
+ TCP_SKB_CB(skb)->when = tcp_time_stamp;
+ if (!tcp_transmit_skb(sk, skb_clone(skb, sk->sk_allocation))) {
+ update_send_head(sk, tp, skb);
+ return;
+ }
}
- return 0;
}
/* This function returns the amount that we can raise the
@@ -1041,12 +1387,6 @@ int tcp_retransmit_skb(struct sock *sk,
if (before(TCP_SKB_CB(skb)->end_seq, tp->snd_una))
BUG();
- if (sk->sk_route_caps & NETIF_F_TSO) {
- sk->sk_route_caps &= ~NETIF_F_TSO;
- sock_set_flag(sk, SOCK_NO_LARGESEND);
- tp->mss_cache = tp->mss_cache_std;
- }
-
if (tcp_trim_head(sk, skb, tp->snd_una - TCP_SKB_CB(skb)->seq))
return -ENOMEM;
}
@@ -1106,7 +1446,6 @@ int tcp_retransmit_skb(struct sock *sk,
* is still in somebody's hands, else make a clone.
*/
TCP_SKB_CB(skb)->when = tcp_time_stamp;
- tcp_tso_set_push(skb);
err = tcp_transmit_skb(sk, (skb_cloned(skb) ?
pskb_copy(skb, GFP_ATOMIC):
@@ -1671,19 +2010,11 @@ int tcp_write_wakeup(struct sock *sk)
TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_PSH;
if (tcp_fragment(sk, skb, seg_size))
return -1;
- /* SWS override triggered forced fragmentation.
- * Disable TSO, the connection is too sick. */
- if (sk->sk_route_caps & NETIF_F_TSO) {
- sock_set_flag(sk, SOCK_NO_LARGESEND);
- sk->sk_route_caps &= ~NETIF_F_TSO;
- tp->mss_cache = tp->mss_cache_std;
- }
} else if (!tcp_skb_pcount(skb))
tcp_set_skb_tso_segs(sk, skb);
TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_PSH;
TCP_SKB_CB(skb)->when = tcp_time_stamp;
- tcp_tso_set_push(skb);
err = tcp_transmit_skb(sk, skb_clone(skb, GFP_ATOMIC));
if (!err) {
update_send_head(sk, tp, skb);
--- 1/net/ipv6/tcp_ipv6.c.~1~ 2005-05-19 13:35:11.000000000 -0700
+++ 2/net/ipv6/tcp_ipv6.c 2005-05-19 13:35:16.000000000 -0700
@@ -2021,7 +2021,8 @@ static int tcp_v6_init_sock(struct sock
*/
tp->snd_ssthresh = 0x7fffffff;
tp->snd_cwnd_clamp = ~0;
- tp->mss_cache_std = tp->mss_cache = 536;
+ tp->mss_cache = 536;
+ tp->xmit_size_cache = ~0;
tp->reordering = sysctl_tcp_reordering;
^ permalink raw reply
* Re: Notifier for features change? (related to Ethernet Bridging: Enable Hardware Checksumming)
From: David S. Miller @ 2005-05-20 18:10 UTC (permalink / raw)
To: util; +Cc: netdev
In-Reply-To: <Pine.LNX.4.62.0505201014340.12681@webhosting.rdsbv.ro>
From: "Catalin(ux aka Dino) BOIE" <util@deuroconsult.ro>
Date: Fri, 20 May 2005 10:17:46 +0300 (EEST)
> Because bridge can change features based on slaves features,
> may I implement NETDEV_FEAT_CHANGE?
>
> It will be used to recompute bridge features when a slave ones are
> changed.
Please do.
^ permalink raw reply
* A new driver for Broadcom bcm5706
From: Michael Chan @ 2005-05-20 17:15 UTC (permalink / raw)
To: davem, jgarzik; +Cc: netdev, ffan, lusinsky
A new driver bnx2 for Broadcom bcm5706 is available. Since the patch is
over 500K, I've put it on the ftp server:
ftp://Net_sys_anon@ftp1.broadcom.com/bnx2-2.patch
The patch also includes new 1000BASE-X advertisement bit definitions in
mii.h
Thanks to David Miller and Jeff Garzik for reviewing and their valuable
feedback.
Signed-off-by: Michael Chan <mchan@broadcom.com>
^ permalink raw reply
* Re: Network card driver problem (znb.o/tulip)
From: Ben Greear @ 2005-05-20 16:07 UTC (permalink / raw)
To: Kosta Todorovic; +Cc: jgarzik, tulip-users, netdev
In-Reply-To: <efe3b0060505192225f3cf36e@mail.gmail.com>
Kosta Todorovic wrote:
> 2 more questions:
>
> 1) Is there anything special I will need to compile in terms of the
> linux kernel for 64-bit PCI bus mode (PCI-X) ? (Currently I'm using
> kernel 2.4.x but that is because my current card drivers do not
> support 2.6.x)
Nothing special...2.4 and 2.6 kernels since way back will work just fine.
> 2) The machine actually has a PCI extension with 9 other PCI-X slots.
> The current cards are 64-bit (pci-x) but as a test i'm planning on
> replacing them with DLinks DFE-580tx's. Unfortunately these are 32-bit
> cards (legacy pci). How will these 4 ports work in 32-bit mode? What
> will the effect be on the speed?
If you put a 33Mhz NIC in a PCI-X bus it makes the entire bus run at
33Mhz speed.
If you do want full backwards compatibility, get the 'universal' 4-port
broadcom NIC from silicom-usa. It works fine in 32-bit PCI busses, and
though I haven't personally tested it, it should work fine in PCI-X
busses at high speed as well.
Ben
>
>
>
> On 5/19/05, Ben Greear <greearb@candelatech.com> wrote:
>
>>Kosta Todorovic wrote:
>>
>>>Whats the best 4-port NIC currently available? I'm interested in
>>>purchasing 10 4-port NICs as a replacement for my current cards.
>>>
>>>I am looking for 10/100Mbps and a good driver for linux (2.4.x and
>>>2.6.x). Preferably a mainstream company but thats not priority.
>>>
>>>Could the community please recommend the best card available? Money is
>>>not an issue since im really interested in the best of the best.
>>
>>Get an Intel 4-port GigE NIC. It will do 10/100/1000, and if you really
>>want to use all 4 ports at even 100Mbps, you need the 64-bit PCI bus...
>>
>>I have been getting mine from silicom-usa.com lately. They also have
>>6-port NICs, and 4-port broadcom GigE nics that can be used in 32-bit
>>PCI slots. (The Intel 4-port NICs will only work in 64-bit PCI slots.)
>>
>>If you really want 10/100 nics, try the p430tx from aei:
>>http://www.aei-it.com/hardware/fastenet/p430tx.htm
>>
>>These are like the old DFE570tx NICs, and use the tulip driver. They
>>are almost as expensive as the GigE NICs though...
>>
>>Thanks,
>>Ben
>>
>>
>>>Any suggestions?
>>>
>>>Regards,
>>>Kosta
>>>
>>>
>>>
>>>On 3/11/05, Kosta Todorovic <kostodo@gmail.com> wrote:
>>>
>>>
>>>>My company has recently purchased several ZNYX ZX274 network cards.
>>>>These cards are Four Channel, 10/100 PCI Adapters. They use Intel chipsets.
>>>>
>>>>Unfortunately there exists no drivers for linux amd64 architecture.
>>>>There are 32bit drivers found at:
>>>>http://www.znyx.com/support/drivers/ZX374_drivers.htm but naturally
>>>>they wont compile under my amd64 system.
>>>>
>>>>The driver itself is called znb.o and can be downloaded from ZNYX's
>>>>website. I spoke to support staff there but they told me they have
>>>>discontinued support and development for this series of cards.
>>>>
>>>>The system I am running gentoo and have tried both 2.4.x and 2.6.x
>>>>kernels but no luck.
>>>>
>>>>Unfortunately there is NO 64bit drivers available for ANY platform. not even MS.
>>>>
>>>>Does anyone know of a customised znb.o driver built for amd64?
>>>>Is there any chance of anyone modifying the source code of the driver
>>>>to compile under a amd64 system?
>>>>
>>>>I've noticed that "tulip" drivers get loaded as a module at boot time.
>>>>but they dont function correctly. (lets you start the device and
>>>>attach ips but cant talk through it)
>>>>
>>>>Is there any variants of the tulip driver that will work for this?
>>>>
>>>>Help much appreciated.
>>>>
>>>>
>>>>/proc/pci extract for network cards:
>>>>
>>>> Bus 5, device 5, function 0:
>>>> Ethernet controller: Digital Equipment Corporation DECchip
>>>>21142/43 (#30) (rev 65).
>>>> IRQ 30.
>>>> Master Capable. Latency=128. Min Gnt=20.Max Lat=40.
>>>> I/O at 0x0 [0x7f].
>>>> Non-prefetchable 32 bit memory at 0xfa1ff400 [0xfa1ff7ff].
>>>> Bus 5, device 4, function 0:
>>>> Ethernet controller: Digital Equipment Corporation DECchip
>>>>21142/43 (#29) (rev 65).
>>>> IRQ 29.
>>>> Master Capable. No bursts. Min Gnt=20.Max Lat=40.
>>>> I/O at 0x0 [0x7f].
>>>> Non-prefetchable 32 bit memory at 0xf9f00000 [0xf9f003ff].
>>>>
>>>
>>>
>>
>>--
>>Ben Greear <greearb@candelatech.com>
>>Candela Technologies Inc http://www.candelatech.com
>>
>>
>
>
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply
* Re: 2.6.12-rc4-mm[12] - ULOG problem
From: Evgeniy Polyakov @ 2005-05-20 14:15 UTC (permalink / raw)
To: hadi; +Cc: David S. Miller, akpm, herbert, netdev
In-Reply-To: <1116589367.6308.36.camel@localhost.localdomain>
[-- Attachment #1: Type: text/plain, Size: 1079 bytes --]
On Fri, 2005-05-20 at 07:42 -0400, jamal wrote:
> On Fri, 2005-20-05 at 10:39 +0400, Evgeniy Polyakov wrote:
>
> > I just want to note, that if you want message bus, you require
> > at least oppsite direction, and thus input callback, and
> > either several socket number for each user [kobject, audit, iscsi,
> > xfrm - all they implement what connector already does] or
> > some header and thus parser in input callback, and thus
> > some registration mechanism.
>
>
> But if you are given your own ID, there should no issues, correct?
Yes.
> i.e it will be no different than say rtnetlink. Users would still have
> to subscribe to topics etc, but thats something you already handle.
> IOW, Iam hoping you are not resorting to a single socket with some user
> space mux to do filtering.
Not following, sorry.
Userspace should use the same socket as kernel - my application
previously
obtained it from dmesg and later used ULOG.
> cheers,
> jamal
>
--
Evgeniy Polyakov
Crash is better than data corruption -- Arthur Grabowski
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Re: sendmsg ignoring bind?
From: Wichert Akkerman @ 2005-05-20 13:31 UTC (permalink / raw)
To: Herbert Xu; +Cc: netdev
In-Reply-To: <20050520132429.GA32695@gondor.apana.org.au>
Previously Herbert Xu wrote:
> I suppose we can expect to have this in a future release of strace :)
It just might happen :)
> > cmsg_type=IP_PKTINFO, {ifindex=0,ipi_spec_dst=inet_addr("0.0.0.0"),ipi_addr=("0.0.0.0")}}, msg_flags=0},
>
> This is far from useless. This will set the source address back to zero
> which essentially means that the bound address is ignored.
I can see it being useful, except in my case it is somewhat unexpected
and undesirable behaviour. I'll make sure to have that fixed in
FreeRADIUS though.
Wichert.
--
Wichert Akkerman <wichert@wiggy.net> It is simple to make things.
http://www.wiggy.net/ It is hard to make things simple.
^ permalink raw reply
* Re: sendmsg ignoring bind?
From: Herbert Xu @ 2005-05-20 13:24 UTC (permalink / raw)
To: Wichert Akkerman; +Cc: netdev
In-Reply-To: <20050520132009.GD4151@wiggy.net>
On Fri, May 20, 2005 at 03:20:09PM +0200, Wichert Akkerman wrote:
>
> I had to hack strace a bit to decode that. The cmsg option turns out
> to be somewhat useless:
I suppose we can expect to have this in a future release of strace :)
> cmsg_type=IP_PKTINFO, {ifindex=0,ipi_spec_dst=inet_addr("0.0.0.0"),ipi_addr=("0.0.0.0")}}, msg_flags=0},
This is far from useless. This will set the source address back to zero
which essentially means that the bound address is ignored.
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply
* Re: sendmsg ignoring bind?
From: Wichert Akkerman @ 2005-05-20 13:20 UTC (permalink / raw)
To: Herbert Xu; +Cc: netdev
In-Reply-To: <20050520101749.GA8661@gondor.apana.org.au>
Previously Herbert Xu wrote:
> This could be a cmsg option that overrode the bind address. Please
> decode it so that we know what it's doing.
I had to hack strace a bit to decode that. The cmsg option turns out
to be somewhat useless:
cmsg_type=IP_PKTINFO, {ifindex=0,ipi_spec_dst=inet_addr("0.0.0.0"),ipi_addr=("0.0.0.0")}}, msg_flags=0},
Wichert.
--
Wichert Akkerman <wichert@wiggy.net> It is simple to make things.
http://www.wiggy.net/ It is hard to make things simple.
^ permalink raw reply
* Re: 2.6.12-rc4-mm[12] - ULOG problem
From: jamal @ 2005-05-20 11:42 UTC (permalink / raw)
To: johnpol; +Cc: David S. Miller, akpm, herbert, netdev
In-Reply-To: <1116571178.21310.124.camel@uganda>
On Fri, 2005-20-05 at 10:39 +0400, Evgeniy Polyakov wrote:
> I just want to note, that if you want message bus, you require
> at least oppsite direction, and thus input callback, and
> either several socket number for each user [kobject, audit, iscsi,
> xfrm - all they implement what connector already does] or
> some header and thus parser in input callback, and thus
> some registration mechanism.
But if you are given your own ID, there should no issues, correct?
i.e it will be no different than say rtnetlink. Users would still have
to subscribe to topics etc, but thats something you already handle.
IOW, Iam hoping you are not resorting to a single socket with some user
space mux to do filtering.
cheers,
jamal
^ permalink raw reply
* IPv6 Tunneling (reverse tunnel need)
From: Felix Fischer @ 2005-05-20 11:19 UTC (permalink / raw)
To: netdev
I'm currently working on a research project and ran into a
question regarding tunneling/decapsulation in IPv6.
<------> [ A ] ===== tunnel from A to B =====> [ B ] <------->
Packets tunneled from A to B are only decapsulated at node B if
B has setup a tunnel-device in direction from B to A (reverse tunnel).
Is the need for the tunnel-device on node B an implementation
issue to handle tunneling, or does it come from something
else (i.e. standard requirement) ?
Further, I am wondering why the possibility to use the ANY_ADDRESS
as tunnel-end-point isn't present in IPv6 ?
The IPv4 implementation allows the usage of "0.0.0.0" as remote_address for
tunnel-end-points.
Any help would be greatly appreciated.
Regards,
Felix Fischer
--
-------------------------------------------------------------------
Institute of Communication Networks and Computer Engineering (IKR)
University of Stuttgart, Germany
-------------------------------------------------------------------
^ permalink raw reply
* Re: sendmsg ignoring bind?
From: Herbert Xu @ 2005-05-20 10:17 UTC (permalink / raw)
To: Wichert Akkerman; +Cc: netdev
In-Reply-To: <20050520081805.GR25658@wiggy.net>
On Fri, May 20, 2005 at 08:18:05AM +0000, Wichert Akkerman wrote:
>
> sendmsg(7, {msg_name(16)={sa_family=AF_INET, sin_port=htons(1812),
> sin_addr=inet_addr("212.100.254.89")},
> msg_iov(1)=[{"....", 249}], msg_controllen=24, {cmsg_len=24,
> cmsg_level=SOL_IP, cmsg_type=, ...}, msg_flags=0}, 0) = 249
This could be a cmsg option that overrode the bind address. Please
decode it so that we know what it's doing.
Cheers,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply
* [PATCH] dummy: improve performance
From: Catalin(ux aka Dino) BOIE @ 2005-05-20 10:11 UTC (permalink / raw)
To: netdev; +Cc: davem
[-- Attachment #1: Type: TEXT/PLAIN, Size: 522 bytes --]
Hello!
Attached patch tries to improve performance of dummy device by activating
NETIF_F_SG, NETIF_F_NO_CSUM, NETIF_F_HIGHDMA, NETIF_F_FRAGLIST,
NETIF_F_TSO and NETIF_F_LLTX.
Patch compiles and runs.
I tested the speed and seems very low (both old version and the new one).
Something like 37Mbits/s. It is normal?
I can easily get 80Mbit/s on the same machine on ethernet.
Thank you!
Signed-off-by: Catalin BOIE <catab at umbrella.ro>
---
Catalin(ux aka Dino) BOIE
catab at deuroconsult.ro
http://kernel.umbrella.ro/
[-- Attachment #2: Type: TEXT/PLAIN, Size: 726 bytes --]
--- dummy1/drivers/net/dummy.c 2005-03-26 05:28:20.000000000 +0200
+++ linux/drivers/net/dummy.c 2005-05-20 11:57:44.000000000 +0300
@@ -26,6 +26,8 @@
Nick Holloway, 27th May 1994
[I tweaked this explanation a little but that's all]
Alan Cox, 30th May 1994
+
+ Add special features to improve performance - Catalin BOIE
*/
#include <linux/config.h>
@@ -73,6 +75,8 @@ static void __init dummy_setup(struct ne
dev->flags &= ~IFF_MULTICAST;
SET_MODULE_OWNER(dev);
random_ether_addr(dev->dev_addr);
+ dev->features = NETIF_F_SG | NETIF_F_NO_CSUM | NETIF_F_HIGHDMA
+ | NETIF_F_FRAGLIST | NETIF_F_TSO | NETIF_F_LLTX;
}
static int dummy_xmit(struct sk_buff *skb, struct net_device *dev)
^ permalink raw reply
* sendmsg ignoring bind?
From: Wichert Akkerman @ 2005-05-20 8:18 UTC (permalink / raw)
To: netdev
After moving a RADIUS server from a machine running 2.6.8.1 to
to another host running 2.6.11.9 yesterday things suddenly
broke: proxy requests were send from the wrong IP address.
Here is the network configuration:
1: eth0: <BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast qlen 1000
link/ether 00:13:21:b3:ba:ef brd ff:ff:ff:ff:ff:ff
inet 212.123.202.85/26 brd 212.123.202.127 scope global eth0
inet 212.123.202.78/26 scope global secondary eth0
inet 212.123.202.70/26 scope global secondary eth0
inet 212.123.202.73/26 scope global secondary eth0
inet 212.123.202.76/26 scope global secondary eth0
inet 212.123.202.74/26 scope global secondary eth0
inet6 2001:960:6a6:2:213:21ff:feb3:baef/64 scope global dynamic
valid_lft 2591728sec preferred_lft 604528sec
inet6 fe80::213:21ff:feb3:baef/64 scope link
valid_lft forever preferred_lft forever
This is an strace of the relevant code:
socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 7
setsockopt(7, SOL_IP, IP_PKTINFO, [1], 4) = 0
bind(7, {sa_family=AF_INET, sin_port=htons(1814),
sin_addr=inet_addr("212.123.202.74")}, 16) = 0
sendmsg(7, {msg_name(16)={sa_family=AF_INET, sin_port=htons(1812),
sin_addr=inet_addr("212.100.254.89")},
msg_iov(1)=[{"....", 249}], msg_controllen=24, {cmsg_len=24,
cmsg_level=SOL_IP, cmsg_type=, ...}, msg_flags=0}, 0) = 249
One would expect that packet to be send from 212.123.202.74, but instead
it is send using the machine's primary IP address 212.123.202.85. As a
temporary workaround I added routes for the relevant targets that
explicitly set the src to 212.123.202.74.
Wichert.
--
Wichert Akkerman <wichert@wiggy.net> It is simple to make things.
http://www.wiggy.net/ It is hard to make things simple.
^ permalink raw reply
* Notifier for features change? (related to Ethernet Bridging: Enable Hardware Checksumming)
From: Catalin(ux aka Dino) BOIE @ 2005-05-20 7:17 UTC (permalink / raw)
To: netdev
Hello!
Because bridge can change features based on slaves features,
may I implement NETDEV_FEAT_CHANGE?
It will be used to recompute bridge features when a slave ones are
changed.
Thank you.
---
Catalin(ux aka Dino) BOIE
catab at deuroconsult.ro
http://kernel.umbrella.ro/
^ permalink raw reply
* Re: 2.6.12-rc4-mm[12] - ULOG problem
From: Evgeniy Polyakov @ 2005-05-20 6:39 UTC (permalink / raw)
To: David S. Miller; +Cc: akpm, herbert, netdev
In-Reply-To: <20050519.114425.18307286.davem@davemloft.net>
[-- Attachment #1: Type: text/plain, Size: 1992 bytes --]
On Thu, 2005-05-19 at 11:44 -0700, David S. Miller wrote:
> From: Andrew Morton <akpm@osdl.org>
> Date: Wed, 18 May 2005 23:45:52 -0700
>
> > > Should I ask David Miller to allocate new one specially for connector?
> >
> > Dave?
>
> Giving the connector a single value 10 is OK, the rest of
> what the connector is doing in this area is not.
>
> I wish you hadn't put the connector into -mm, it's really
> in need of several fixups still. The bogus reuse of the
> ULOG netlink number is simply indicative of that.
And how does it indicate that it is bogus? :)
It is one netlink user that can use any socket number - and now
it is called bogus.
What other people suggest is just create some wrapper over
netlink_broadcast() and alloc_skb().
if you do think it will solve all problems, then I even will not
say anything. Point.
I just want to note, that if you want message bus, you require
at least oppsite direction, and thus input callback, and
either several socket number for each user [kobject, audit, iscsi,
xfrm - all they implement what connector already does] or
some header and thus parser in input callback, and thus
some registration mechanism. Magically it is what connector does.
And nothing more, btw.
It only allows not to rewrite the whole driver just to move
to new transport layer, only register new cn_dev device
with different method.
Ok, Dave, we all see your point, feel free to remove connector,
I will not bother people to include it yet another time...
But I believe in a month or two someone will reinvent the wheel
and create somthing similar. If it will be simple wrapper, then
it just can not solve message bus problem, only notification,
and thus someone will create it again.
Thank you.
P.S. smtp server from my old university years seems to still drop
your messages, sorry for that, I will kick admins again.
--
Evgeniy Polyakov
Crash is better than data corruption -- Arthur Grabowski
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Re: 2.6.12-rc4-mm[12] - ULOG problem
From: Evgeniy Polyakov @ 2005-05-20 6:27 UTC (permalink / raw)
To: David S. Miller; +Cc: akpm, herbert, netdev
In-Reply-To: <20050519.114241.59656850.davem@davemloft.net>
[-- Attachment #1: Type: text/plain, Size: 795 bytes --]
On Thu, 2005-05-19 at 11:42 -0700, David S. Miller wrote:
> From: Evgeniy Polyakov <johnpol@2ka.mipt.ru>
> Date: Thu, 19 May 2005 11:06:25 +0400
>
> > It was created to be able to load several different connector devices
> > from different modules [basically it was module1.ko unit=10, module2.ko
> > unit=11 and so on].
>
> That's bogus, each connector will need to allocate it's own
> specific define in the netlink header, and we're about to
> run out of numbers.
>
> Please redesign the connector so that it doesn't eat more than
> one netlink number, we're running out of them soon.
It does not require more than one socket number.
It just can use any other number provided.
--
Evgeniy Polyakov
Crash is better than data corruption -- Arthur Grabowski
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Re: 2.6.12-rc4-mm[12] - ULOG problem
From: Evgeniy Polyakov @ 2005-05-20 6:27 UTC (permalink / raw)
To: David S. Miller; +Cc: jmorris, akpm, herbert, netdev
In-Reply-To: <20050519.114813.85686672.davem@davemloft.net>
[-- Attachment #1: Type: text/plain, Size: 983 bytes --]
On Thu, 2005-05-19 at 11:48 -0700, David S. Miller wrote:
> From: James Morris <jmorris@redhat.com>
> Date: Thu, 19 May 2005 09:19:33 -0400 (EDT)
>
> > On Thu, 19 May 2005, Andrew Morton wrote:
> >
> > > We should remove the feature. If there is demonstrated need for multiple
> > > instances then it should be done by more conventional means - syscall,
> > > allocation of a device major then use the minor as a selector or whatever.
> >
> > I'd suggest removing the connector code completely.
>
> I totally agree, it's crap at the current time and the author doesn't
> fix the problems being shown in it, in fact he defends some of them
> even this one. It needs lots of work still.
There were no problems reported.
Completely.
What I defend is ability to function correctly when some changes
may be introduced by providing some extensions that may be used.
--
Evgeniy Polyakov
Crash is better than data corruption -- Arthur Grabowski
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Re: 2.6.12-rc4-mm[12] - ULOG problem
From: Evgeniy Polyakov @ 2005-05-20 6:25 UTC (permalink / raw)
To: David S. Miller; +Cc: hadi, jmorris, akpm, herbert, netdev
In-Reply-To: <20050519.114901.108984882.davem@davemloft.net>
[-- Attachment #1: Type: text/plain, Size: 463 bytes --]
On Thu, 2005-05-19 at 11:49 -0700, David S. Miller wrote:
> From: jamal <hadi@cyberus.ca>
> Date: Thu, 19 May 2005 09:46:50 -0400
>
> > However, something like connector should only get one ID and it can do
> > its own multiplexing based on "units".
>
> Yes. There is no reason connector needs more than one
> netlink ID.
It does not require several IDs.
--
Evgeniy Polyakov
Crash is better than data corruption -- Arthur Grabowski
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Re: [PATCH] [BRIDGE] Set features based on slave's ones (was Ethernet Bridging: Enable Hardware Checksumming)
From: Catalin(ux aka Dino) BOIE @ 2005-05-20 6:07 UTC (permalink / raw)
To: Jon Mason; +Cc: netdev, davem
In-Reply-To: <20050519214015.GA19961@us.ibm.com>
>> +static inline void br_features_change(struct net_bridge *br, struct net_device *dev)
>> +{
>> + br->dev->features &= dev->features | ~BR_FEAT_MASK;
>
> ~BR_FEAT_MASK isn't necessary. Either you wanted to do an '&' just
> before it, so that BR_FEAT_MASK features are the only ones that you want
> or you are enabling features that aren't necessarily supported by the
> adapter/driver (like LLTX and HW_VLAN stuff).
So, I invert BR_FEAT_MASK so I can, by default clear special features.
Then I ored with dev->features, so I can enable special features if the
slave device supports it. Then, I do & so I can clear stuff that is not
supported by device, but the rest of br->dev features remains untouched.
Let's test: if dev hash SG the code is like this:
BR_FEAT_MASK = 1001 (only test SG and HW_CSUM)
# br is inited
br |= 1001
br &= 0001 | ~1001
br &= 0001 | 0110
br &= 0111
br = 1001 & 0111 = 0001 - so bit SG is set also in br. But not HW_CSUM
because it's not in device.
I can't see the code is wrong. Can you give me an example when it fails,
please?
>> +}
>> +
>> +/*
>> + * Recomputes features using slave's features
>> + */
>> +static void br_features_recompute(struct net_bridge *br)
>> +{
>> + struct net_bridge_port *p;
>> +
>> + br->dev->features |= BR_FEAT_MASK;
>
> The OR is not needed. Just re-initialize features to BR_FEAT_MASK and
> everything will take case of itself.
Nope. Not correct. Because we might enable LLTX on the bridge, but not in
BR_FEAT_MASK.
I will post a patch in few hours with all stuff updated.
---
Catalin(ux aka Dino) BOIE
catab at deuroconsult.ro
http://kernel.umbrella.ro/
^ permalink raw reply
* Re: Network card driver problem (znb.o/tulip)
From: Kosta Todorovic @ 2005-05-20 5:25 UTC (permalink / raw)
To: Ben Greear; +Cc: jgarzik, tulip-users, netdev
In-Reply-To: <428CC958.1080909@candelatech.com>
2 more questions:
1) Is there anything special I will need to compile in terms of the
linux kernel for 64-bit PCI bus mode (PCI-X) ? (Currently I'm using
kernel 2.4.x but that is because my current card drivers do not
support 2.6.x)
2) The machine actually has a PCI extension with 9 other PCI-X slots.
The current cards are 64-bit (pci-x) but as a test i'm planning on
replacing them with DLinks DFE-580tx's. Unfortunately these are 32-bit
cards (legacy pci). How will these 4 ports work in 32-bit mode? What
will the effect be on the speed?
On 5/19/05, Ben Greear <greearb@candelatech.com> wrote:
> Kosta Todorovic wrote:
> > Whats the best 4-port NIC currently available? I'm interested in
> > purchasing 10 4-port NICs as a replacement for my current cards.
> >
> > I am looking for 10/100Mbps and a good driver for linux (2.4.x and
> > 2.6.x). Preferably a mainstream company but thats not priority.
> >
> > Could the community please recommend the best card available? Money is
> > not an issue since im really interested in the best of the best.
>
> Get an Intel 4-port GigE NIC. It will do 10/100/1000, and if you really
> want to use all 4 ports at even 100Mbps, you need the 64-bit PCI bus...
>
> I have been getting mine from silicom-usa.com lately. They also have
> 6-port NICs, and 4-port broadcom GigE nics that can be used in 32-bit
> PCI slots. (The Intel 4-port NICs will only work in 64-bit PCI slots.)
>
> If you really want 10/100 nics, try the p430tx from aei:
> http://www.aei-it.com/hardware/fastenet/p430tx.htm
>
> These are like the old DFE570tx NICs, and use the tulip driver. They
> are almost as expensive as the GigE NICs though...
>
> Thanks,
> Ben
>
> >
> > Any suggestions?
> >
> > Regards,
> > Kosta
> >
> >
> >
> > On 3/11/05, Kosta Todorovic <kostodo@gmail.com> wrote:
> >
> >>My company has recently purchased several ZNYX ZX274 network cards.
> >>These cards are Four Channel, 10/100 PCI Adapters. They use Intel chipsets.
> >>
> >>Unfortunately there exists no drivers for linux amd64 architecture.
> >>There are 32bit drivers found at:
> >>http://www.znyx.com/support/drivers/ZX374_drivers.htm but naturally
> >>they wont compile under my amd64 system.
> >>
> >>The driver itself is called znb.o and can be downloaded from ZNYX's
> >>website. I spoke to support staff there but they told me they have
> >>discontinued support and development for this series of cards.
> >>
> >>The system I am running gentoo and have tried both 2.4.x and 2.6.x
> >>kernels but no luck.
> >>
> >>Unfortunately there is NO 64bit drivers available for ANY platform. not even MS.
> >>
> >>Does anyone know of a customised znb.o driver built for amd64?
> >>Is there any chance of anyone modifying the source code of the driver
> >>to compile under a amd64 system?
> >>
> >>I've noticed that "tulip" drivers get loaded as a module at boot time.
> >>but they dont function correctly. (lets you start the device and
> >>attach ips but cant talk through it)
> >>
> >>Is there any variants of the tulip driver that will work for this?
> >>
> >>Help much appreciated.
> >>
> >>
> >>/proc/pci extract for network cards:
> >>
> >> Bus 5, device 5, function 0:
> >> Ethernet controller: Digital Equipment Corporation DECchip
> >>21142/43 (#30) (rev 65).
> >> IRQ 30.
> >> Master Capable. Latency=128. Min Gnt=20.Max Lat=40.
> >> I/O at 0x0 [0x7f].
> >> Non-prefetchable 32 bit memory at 0xfa1ff400 [0xfa1ff7ff].
> >> Bus 5, device 4, function 0:
> >> Ethernet controller: Digital Equipment Corporation DECchip
> >>21142/43 (#29) (rev 65).
> >> IRQ 29.
> >> Master Capable. No bursts. Min Gnt=20.Max Lat=40.
> >> I/O at 0x0 [0x7f].
> >> Non-prefetchable 32 bit memory at 0xf9f00000 [0xf9f003ff].
> >>
> >
> >
>
>
> --
> Ben Greear <greearb@candelatech.com>
> Candela Technologies Inc http://www.candelatech.com
>
>
^ permalink raw reply
* Re: [PATCH] Super TSO
From: David S. Miller @ 2005-05-20 1:28 UTC (permalink / raw)
To: leonid.grossman; +Cc: netdev
In-Reply-To: <200505200125.j4K1PaVG015780@guinness.s2io.com>
From: "Leonid Grossman" <leonid.grossman@neterion.com>
Date: Thu, 19 May 2005 18:25:35 -0700
> Yes, I think I'm actually with you. As long as each page is physically
> continuous and therefore requires one descriptor per page, the total
> number of descriptors per packet will be only 64K / PAGE_SIZE (plus
> some for headers), and this is fully manageable from a NIC
> prospective.
Yes, that is exactly what happens.
^ permalink raw reply
* RE: [PATCH] Super TSO
From: Leonid Grossman @ 2005-05-20 1:25 UTC (permalink / raw)
To: 'David S.Miller'; +Cc: netdev
In-Reply-To: <20050519.175542.07642115.davem@davemloft.net>
> > > We always chop up the user data into individual system
> pages when we
> > > build TSO frames, so I can't see how any kind of memory
> > > fragmentation could be an issue.
> >
> > This is exactly what I wanted to hear :-) If the TSO implementation
> > guarantees that the payload comes (for the most
> > part)
> > in physically continuous pages, then the number of fragments will
> > never get out of whack, and my argument indeed becomes invalid.
>
> You misunderstand me. The TCP segmenter splits the incoming
> user data into page size'd chunks. So a 64K packet uses 64K
> / PAGE_SIZE individual pages.
Yes, I think I'm actually with you. As long as each page is physically
continuous
and therefore requires one descriptor per page, the total number of
descriptors per packet
will be only 64K / PAGE_SIZE (plus some for headers), and this is fully
manageable from a NIC prospective.
>
> The only thing the driver author needs to be aware of wrt.
> this is to never wake up the TX netif queue until at least
> "MAX_SKB_FRAGS + 1" transmit descriptors are available.
>
> You'll see that every driver setting NETIF_F_SG implements this test.
>
> > Sure. On the other hand, the TCP code is unaware of the
> copy vs. DMA
> > costs on a particular NIC (well, this is actually more
> specific to a
> > system than to a NIC). But I guess as long as both the packet size
> > and the number of fragments will not get very big at the
> same time, A
> > NIC will be OK.
>
> They can and will be as large as "MAX_SKB_FRAGS + 1".
>
>
^ 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