From 5f286e113fa377e50bd18fc45e5a0d4d83f6950c Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Sat, 28 Apr 2007 20:57:37 -0700 Subject: [NETPOLL]: Fix TX queue overflow in trapped mode. CONFIG_NETPOLL_TRAP causes the TX queue controls to be completely bypassed in the netpoll's "trapped" mode which easily causes overflows in the drivers with short TX queues (most notably, in 8139too with its 4-deep queue). So, make this option more sensible by making it only bypass the TX softirq wakeup. Signed-off-by: Sergei Shtylyov Acked-by: Jeff Garzik Acked-by: Tom Rini Acked-by: Matt Mackall Signed-off-by: David S. Miller --- include/linux/netdevice.h | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'include/linux') diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index e027a3750a77..24cef42f1e0f 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -654,8 +654,10 @@ static inline void netif_start_queue(struct net_device *dev) static inline void netif_wake_queue(struct net_device *dev) { #ifdef CONFIG_NETPOLL_TRAP - if (netpoll_trap()) + if (netpoll_trap()) { + clear_bit(__LINK_STATE_XOFF, &dev->state); return; + } #endif if (test_and_clear_bit(__LINK_STATE_XOFF, &dev->state)) __netif_schedule(dev); @@ -663,10 +665,6 @@ static inline void netif_wake_queue(struct net_device *dev) static inline void netif_stop_queue(struct net_device *dev) { -#ifdef CONFIG_NETPOLL_TRAP - if (netpoll_trap()) - return; -#endif set_bit(__LINK_STATE_XOFF, &dev->state); } -- cgit v1.2.3-71-gd317 From 5a1b5898ee9e0bf68a86609ecb9775457b1857a5 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Sat, 28 Apr 2007 21:04:03 -0700 Subject: [NET]: Remove NETIF_F_INTERNAL_STATS, default to internal stats. Herbert Xu conviced me that a new flag was overkill; every driver currently overrides get_stats, so we might as well make the internal one the default. If someone did fail to set get_stats, they would now get all 0 stats instead of "No statistics available". Signed-off-by: Rusty Russell Acked-by: Herbert Xu Signed-off-by: David S. Miller --- arch/s390/appldata/appldata_net_sum.c | 3 -- drivers/net/bonding/bond_main.c | 59 +++++++++++++++-------------------- drivers/parisc/led.c | 2 -- include/linux/netdevice.h | 1 - net/core/dev.c | 45 ++++++++++++-------------- 5 files changed, 45 insertions(+), 65 deletions(-) (limited to 'include/linux') diff --git a/arch/s390/appldata/appldata_net_sum.c b/arch/s390/appldata/appldata_net_sum.c index 516b3ac9a9b5..a43f3488fecf 100644 --- a/arch/s390/appldata/appldata_net_sum.c +++ b/arch/s390/appldata/appldata_net_sum.c @@ -109,9 +109,6 @@ static void appldata_get_net_sum_data(void *data) read_lock(&dev_base_lock); for (dev = dev_base; dev != NULL; dev = dev->next) { stats = dev->get_stats(dev); - if (stats == NULL) { - continue; - } rx_packets += stats->rx_packets; tx_packets += stats->tx_packets; rx_bytes += stats->rx_bytes; diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index cea3783c92c5..724bce51f936 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1360,13 +1360,6 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) goto err_undo_flags; } - if (slave_dev->get_stats == NULL) { - printk(KERN_NOTICE DRV_NAME - ": %s: the driver for slave device %s does not provide " - "get_stats function, network statistics will be " - "inaccurate.\n", bond_dev->name, slave_dev->name); - } - new_slave = kzalloc(sizeof(struct slave), GFP_KERNEL); if (!new_slave) { res = -ENOMEM; @@ -3641,33 +3634,31 @@ static struct net_device_stats *bond_get_stats(struct net_device *bond_dev) bond_for_each_slave(bond, slave, i) { sstats = slave->dev->get_stats(slave->dev); - if (sstats) { - stats->rx_packets += sstats->rx_packets; - stats->rx_bytes += sstats->rx_bytes; - stats->rx_errors += sstats->rx_errors; - stats->rx_dropped += sstats->rx_dropped; - - stats->tx_packets += sstats->tx_packets; - stats->tx_bytes += sstats->tx_bytes; - stats->tx_errors += sstats->tx_errors; - stats->tx_dropped += sstats->tx_dropped; - - stats->multicast += sstats->multicast; - stats->collisions += sstats->collisions; - - stats->rx_length_errors += sstats->rx_length_errors; - stats->rx_over_errors += sstats->rx_over_errors; - stats->rx_crc_errors += sstats->rx_crc_errors; - stats->rx_frame_errors += sstats->rx_frame_errors; - stats->rx_fifo_errors += sstats->rx_fifo_errors; - stats->rx_missed_errors += sstats->rx_missed_errors; - - stats->tx_aborted_errors += sstats->tx_aborted_errors; - stats->tx_carrier_errors += sstats->tx_carrier_errors; - stats->tx_fifo_errors += sstats->tx_fifo_errors; - stats->tx_heartbeat_errors += sstats->tx_heartbeat_errors; - stats->tx_window_errors += sstats->tx_window_errors; - } + stats->rx_packets += sstats->rx_packets; + stats->rx_bytes += sstats->rx_bytes; + stats->rx_errors += sstats->rx_errors; + stats->rx_dropped += sstats->rx_dropped; + + stats->tx_packets += sstats->tx_packets; + stats->tx_bytes += sstats->tx_bytes; + stats->tx_errors += sstats->tx_errors; + stats->tx_dropped += sstats->tx_dropped; + + stats->multicast += sstats->multicast; + stats->collisions += sstats->collisions; + + stats->rx_length_errors += sstats->rx_length_errors; + stats->rx_over_errors += sstats->rx_over_errors; + stats->rx_crc_errors += sstats->rx_crc_errors; + stats->rx_frame_errors += sstats->rx_frame_errors; + stats->rx_fifo_errors += sstats->rx_fifo_errors; + stats->rx_missed_errors += sstats->rx_missed_errors; + + stats->tx_aborted_errors += sstats->tx_aborted_errors; + stats->tx_carrier_errors += sstats->tx_carrier_errors; + stats->tx_fifo_errors += sstats->tx_fifo_errors; + stats->tx_heartbeat_errors += sstats->tx_heartbeat_errors; + stats->tx_window_errors += sstats->tx_window_errors; } read_unlock_bh(&bond->lock); diff --git a/drivers/parisc/led.c b/drivers/parisc/led.c index 453e6829756c..3df82fe9ce8c 100644 --- a/drivers/parisc/led.c +++ b/drivers/parisc/led.c @@ -373,8 +373,6 @@ static __inline__ int led_get_net_activity(void) if (LOOPBACK(in_dev->ifa_list->ifa_local)) continue; stats = dev->get_stats(dev); - if (!stats) - continue; rx_total += stats->rx_packets; tx_total += stats->tx_packets; } diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 24cef42f1e0f..ac0c92b1e002 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -325,7 +325,6 @@ struct net_device #define NETIF_F_VLAN_CHALLENGED 1024 /* Device cannot handle VLAN packets */ #define NETIF_F_GSO 2048 /* Enable software GSO. */ #define NETIF_F_LLTX 4096 /* LockLess TX */ -#define NETIF_F_INTERNAL_STATS 8192 /* Use stats structure in net_device */ /* Segmentation offload features */ #define NETIF_F_GSO_SHIFT 16 diff --git a/net/core/dev.c b/net/core/dev.c index d5e42d13bd67..eb999003bbb7 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2101,26 +2101,23 @@ static void dev_seq_printf_stats(struct seq_file *seq, struct net_device *dev) { struct net_device_stats *stats = dev->get_stats(dev); - if (stats) { - seq_printf(seq, "%6s:%8lu %7lu %4lu %4lu %4lu %5lu %10lu %9lu " - "%8lu %7lu %4lu %4lu %4lu %5lu %7lu %10lu\n", - dev->name, stats->rx_bytes, stats->rx_packets, - stats->rx_errors, - stats->rx_dropped + stats->rx_missed_errors, - stats->rx_fifo_errors, - stats->rx_length_errors + stats->rx_over_errors + - stats->rx_crc_errors + stats->rx_frame_errors, - stats->rx_compressed, stats->multicast, - stats->tx_bytes, stats->tx_packets, - stats->tx_errors, stats->tx_dropped, - stats->tx_fifo_errors, stats->collisions, - stats->tx_carrier_errors + - stats->tx_aborted_errors + - stats->tx_window_errors + - stats->tx_heartbeat_errors, - stats->tx_compressed); - } else - seq_printf(seq, "%6s: No statistics available.\n", dev->name); + seq_printf(seq, "%6s:%8lu %7lu %4lu %4lu %4lu %5lu %10lu %9lu " + "%8lu %7lu %4lu %4lu %4lu %5lu %7lu %10lu\n", + dev->name, stats->rx_bytes, stats->rx_packets, + stats->rx_errors, + stats->rx_dropped + stats->rx_missed_errors, + stats->rx_fifo_errors, + stats->rx_length_errors + stats->rx_over_errors + + stats->rx_crc_errors + stats->rx_frame_errors, + stats->rx_compressed, stats->multicast, + stats->tx_bytes, stats->tx_packets, + stats->tx_errors, stats->tx_dropped, + stats->tx_fifo_errors, stats->collisions, + stats->tx_carrier_errors + + stats->tx_aborted_errors + + stats->tx_window_errors + + stats->tx_heartbeat_errors, + stats->tx_compressed); } /* @@ -3257,11 +3254,9 @@ out: mutex_unlock(&net_todo_run_mutex); } -static struct net_device_stats *maybe_internal_stats(struct net_device *dev) +static struct net_device_stats *internal_stats(struct net_device *dev) { - if (dev->features & NETIF_F_INTERNAL_STATS) - return &dev->stats; - return NULL; + return &dev->stats; } /** @@ -3299,7 +3294,7 @@ struct net_device *alloc_netdev(int sizeof_priv, const char *name, if (sizeof_priv) dev->priv = netdev_priv(dev); - dev->get_stats = maybe_internal_stats; + dev->get_stats = internal_stats; setup(dev); strcpy(dev->name, name); return dev; -- cgit v1.2.3-71-gd317 From ecfd6b183780c6d9e85873693b3ce6c5f4d08b58 Mon Sep 17 00:00:00 2001 From: Jamal Hadi Salim Date: Sat, 28 Apr 2007 21:20:32 -0700 Subject: [XFRM]: Export SPD info With this patch you can use iproute2 in user space to efficiently see how many policies exist in different directions. Signed-off-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- include/linux/xfrm.h | 35 +++++++++++++++++++++++ include/net/xfrm.h | 13 +++++++++ net/xfrm/xfrm_policy.c | 16 ++++++++++- net/xfrm/xfrm_user.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 140 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h index 9c656a5cf842..a5d53e0fe152 100644 --- a/include/linux/xfrm.h +++ b/include/linux/xfrm.h @@ -185,6 +185,11 @@ enum { #define XFRM_MSG_NEWSADINFO XFRM_MSG_NEWSADINFO XFRM_MSG_GETSADINFO, #define XFRM_MSG_GETSADINFO XFRM_MSG_GETSADINFO + + XFRM_MSG_NEWSPDINFO, +#define XFRM_MSG_NEWSPDINFO XFRM_MSG_NEWSPDINFO + XFRM_MSG_GETSPDINFO, +#define XFRM_MSG_GETSPDINFO XFRM_MSG_GETSPDINFO __XFRM_MSG_MAX }; #define XFRM_MSG_MAX (__XFRM_MSG_MAX - 1) @@ -290,6 +295,36 @@ enum xfrm_sadattr_type_t { #define XFRMA_SAD_MAX (__XFRMA_SAD_MAX - 1) }; +/* SPD Table filter flags */ +enum xfrm_spd_ftype_t { + XFRM_SPD_UNSPEC, + XFRM_SPD_HMASK=1, + XFRM_SPD_HMAX=2, + XFRM_SPD_ICNT=4, + XFRM_SPD_OCNT=8, + XFRM_SPD_FCNT=16, + XFRM_SPD_ISCNT=32, + XFRM_SPD_OSCNT=64, + XFRM_SPD_FSCNT=128, + __XFRM_SPD_MAX + +#define XFRM_SPD_MAX (__XFRM_SPD_MAX - 1) +}; +enum xfrm_spdattr_type_t { + XFRMA_SPD_UNSPEC, + XFRMA_SPDHMASK, + XFRMA_SPDHMAX, + XFRMA_SPDICNT, + XFRMA_SPDOCNT, + XFRMA_SPDFCNT, + XFRMA_SPDISCNT, + XFRMA_SPDOSCNT, + XFRMA_SPDFSCNT, + __XFRMA_SPD_MAX + +#define XFRMA_SPD_MAX (__XFRMA_SPD_MAX - 1) +}; + struct xfrm_usersa_info { struct xfrm_selector sel; struct xfrm_id id; diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 8287081d77f2..9561bf817b02 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -423,6 +423,18 @@ struct xfrm_sadinfo u32 sadhmcnt; /* max allowed hash bkts */ u32 sadcnt; /* current running count */ }; + +struct xfrm_spdinfo +{ + u32 incnt; + u32 outcnt; + u32 fwdcnt; + u32 inscnt; + u32 outscnt; + u32 fwdscnt; + u32 spdhcnt; + u32 spdhmcnt; +}; #ifdef CONFIG_AUDITSYSCALL extern void xfrm_audit_log(uid_t auid, u32 secid, int type, int result, struct xfrm_policy *xp, struct xfrm_state *x); @@ -946,6 +958,7 @@ extern struct xfrm_state *xfrm_find_acq_byseq(u32 seq); extern int xfrm_state_delete(struct xfrm_state *x); extern void xfrm_state_flush(u8 proto, struct xfrm_audit *audit_info); extern void xfrm_sad_getinfo(struct xfrm_sadinfo *si); +extern void xfrm_spd_getinfo(struct xfrm_spdinfo *si); extern int xfrm_replay_check(struct xfrm_state *x, __be32 seq); extern void xfrm_replay_advance(struct xfrm_state *x, __be32 seq); extern void xfrm_replay_notify(struct xfrm_state *x, int event); diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 762926009c04..dbf9d96a2f0b 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -579,8 +579,22 @@ static inline int xfrm_byidx_should_resize(int total) return 0; } -static DEFINE_MUTEX(hash_resize_mutex); +void xfrm_spd_getinfo(struct xfrm_spdinfo *si) +{ + read_lock_bh(&xfrm_policy_lock); + si->incnt = xfrm_policy_count[XFRM_POLICY_IN]; + si->outcnt = xfrm_policy_count[XFRM_POLICY_OUT]; + si->fwdcnt = xfrm_policy_count[XFRM_POLICY_FWD]; + si->inscnt = xfrm_policy_count[XFRM_POLICY_IN+XFRM_POLICY_MAX]; + si->outscnt = xfrm_policy_count[XFRM_POLICY_OUT+XFRM_POLICY_MAX]; + si->fwdscnt = xfrm_policy_count[XFRM_POLICY_FWD+XFRM_POLICY_MAX]; + si->spdhcnt = xfrm_idx_hmask; + si->spdhmcnt = xfrm_policy_hashmax; + read_unlock_bh(&xfrm_policy_lock); +} +EXPORT_SYMBOL(xfrm_spd_getinfo); +static DEFINE_MUTEX(hash_resize_mutex); static void xfrm_hash_resize(struct work_struct *__unused) { int dir, total; diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 69110fed64b6..4210d91624cd 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -672,6 +672,81 @@ static struct sk_buff *xfrm_state_netlink(struct sk_buff *in_skb, return skb; } +static int build_spdinfo(struct sk_buff *skb, u32 pid, u32 seq, u32 flags) +{ + struct xfrm_spdinfo si; + struct nlmsghdr *nlh; + u32 *f; + + nlh = nlmsg_put(skb, pid, seq, XFRM_MSG_NEWSPDINFO, sizeof(u32), 0); + if (nlh == NULL) /* shouldnt really happen ... */ + return -EMSGSIZE; + + f = nlmsg_data(nlh); + *f = flags; + xfrm_spd_getinfo(&si); + + if (flags & XFRM_SPD_HMASK) + NLA_PUT_U32(skb, XFRMA_SPDHMASK, si.spdhcnt); + if (flags & XFRM_SPD_HMAX) + NLA_PUT_U32(skb, XFRMA_SPDHMAX, si.spdhmcnt); + if (flags & XFRM_SPD_ICNT) + NLA_PUT_U32(skb, XFRMA_SPDICNT, si.incnt); + if (flags & XFRM_SPD_OCNT) + NLA_PUT_U32(skb, XFRMA_SPDOCNT, si.outcnt); + if (flags & XFRM_SPD_FCNT) + NLA_PUT_U32(skb, XFRMA_SPDFCNT, si.fwdcnt); + if (flags & XFRM_SPD_ISCNT) + NLA_PUT_U32(skb, XFRMA_SPDISCNT, si.inscnt); + if (flags & XFRM_SPD_OSCNT) + NLA_PUT_U32(skb, XFRMA_SPDOSCNT, si.inscnt); + if (flags & XFRM_SPD_FSCNT) + NLA_PUT_U32(skb, XFRMA_SPDFSCNT, si.inscnt); + + return nlmsg_end(skb, nlh); + +nla_put_failure: + nlmsg_cancel(skb, nlh); + return -EMSGSIZE; +} + +static int xfrm_get_spdinfo(struct sk_buff *skb, struct nlmsghdr *nlh, + struct rtattr **xfrma) +{ + struct sk_buff *r_skb; + u32 *flags = NLMSG_DATA(nlh); + u32 spid = NETLINK_CB(skb).pid; + u32 seq = nlh->nlmsg_seq; + int len = NLMSG_LENGTH(sizeof(u32)); + + + if (*flags & XFRM_SPD_HMASK) + len += RTA_SPACE(sizeof(u32)); + if (*flags & XFRM_SPD_HMAX) + len += RTA_SPACE(sizeof(u32)); + if (*flags & XFRM_SPD_ICNT) + len += RTA_SPACE(sizeof(u32)); + if (*flags & XFRM_SPD_OCNT) + len += RTA_SPACE(sizeof(u32)); + if (*flags & XFRM_SPD_FCNT) + len += RTA_SPACE(sizeof(u32)); + if (*flags & XFRM_SPD_ISCNT) + len += RTA_SPACE(sizeof(u32)); + if (*flags & XFRM_SPD_OSCNT) + len += RTA_SPACE(sizeof(u32)); + if (*flags & XFRM_SPD_FSCNT) + len += RTA_SPACE(sizeof(u32)); + + r_skb = alloc_skb(len, GFP_ATOMIC); + if (r_skb == NULL) + return -ENOMEM; + + if (build_spdinfo(r_skb, spid, seq, *flags) < 0) + BUG(); + + return nlmsg_unicast(xfrm_nl, r_skb, spid); +} + static int build_sadinfo(struct sk_buff *skb, u32 pid, u32 seq, u32 flags) { struct xfrm_sadinfo si; @@ -1879,6 +1954,7 @@ static const int xfrm_msg_min[XFRM_NR_MSGTYPES] = { [XFRM_MSG_REPORT - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_report), [XFRM_MSG_MIGRATE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_id), [XFRM_MSG_GETSADINFO - XFRM_MSG_BASE] = NLMSG_LENGTH(sizeof(u32)), + [XFRM_MSG_GETSPDINFO - XFRM_MSG_BASE] = NLMSG_LENGTH(sizeof(u32)), }; #undef XMSGSIZE @@ -1907,6 +1983,7 @@ static struct xfrm_link { [XFRM_MSG_GETAE - XFRM_MSG_BASE] = { .doit = xfrm_get_ae }, [XFRM_MSG_MIGRATE - XFRM_MSG_BASE] = { .doit = xfrm_do_migrate }, [XFRM_MSG_GETSADINFO - XFRM_MSG_BASE] = { .doit = xfrm_get_sadinfo }, + [XFRM_MSG_GETSPDINFO - XFRM_MSG_BASE] = { .doit = xfrm_get_spdinfo }, }; static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) -- cgit v1.2.3-71-gd317 From 46f8914e53c28d0716c586e08a7c819d8ebb9d54 Mon Sep 17 00:00:00 2001 From: James Chapman Date: Mon, 30 Apr 2007 00:07:31 -0700 Subject: [SKB]: Introduce skb_queue_walk_safe() This patch provides a method for walking skb lists while inserting or removing skbs from the list. Signed-off-by: James Chapman Signed-off-by: David S. Miller --- include/linux/skbuff.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'include/linux') diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 2694cb3ca763..253a2b9be9d6 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -1471,6 +1471,11 @@ static inline int pskb_trim_rcsum(struct sk_buff *skb, unsigned int len) prefetch(skb->next), (skb != (struct sk_buff *)(queue)); \ skb = skb->next) +#define skb_queue_walk_safe(queue, skb, tmp) \ + for (skb = (queue)->next, tmp = skb->next; \ + skb != (struct sk_buff *)(queue); \ + skb = tmp, tmp = skb->next) + #define skb_queue_reverse_walk(queue, skb) \ for (skb = (queue)->prev; \ prefetch(skb->prev), (skb != (struct sk_buff *)(queue)); \ -- cgit v1.2.3-71-gd317 From 71ff6c0a857d11e70aec0c8f1e0d4ae9a45dd468 Mon Sep 17 00:00:00 2001 From: Mitsuru Chinen Date: Mon, 30 Apr 2007 00:45:02 -0700 Subject: [SNMP]: Add definitions for {In,Out}BcastPkts The updated IP-MIB RFC (RFC4293) specifys new objects, InBcastPkts and OutBcastPkts. This adds definitions for them. Signed-off-by: Mitsuru Chinen Signed-off-by: David S. Miller --- include/linux/snmp.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include/linux') diff --git a/include/linux/snmp.h b/include/linux/snmp.h index 854aa6b543f1..802b3a38b041 100644 --- a/include/linux/snmp.h +++ b/include/linux/snmp.h @@ -40,6 +40,8 @@ enum IPSTATS_MIB_FRAGCREATES, /* FragCreates */ IPSTATS_MIB_INMCASTPKTS, /* InMcastPkts */ IPSTATS_MIB_OUTMCASTPKTS, /* OutMcastPkts */ + IPSTATS_MIB_INBCASTPKTS, /* InBcastPkts */ + IPSTATS_MIB_OUTBCASTPKTS, /* OutBcastPkts */ __IPSTATS_MIB_MAX }; -- cgit v1.2.3-71-gd317