* Re: [RFC] Replace scatterlist with crypto_frag
From: David S. Miller @ 2005-06-06 23:18 UTC (permalink / raw)
To: herbert; +Cc: hch, jmorris, linux-crypto, netdev
In-Reply-To: <20050606231405.GA7385@gondor.apana.org.au>
From: Herbert Xu <herbert@gondor.apana.org.au>
Date: Tue, 7 Jun 2005 09:14:05 +1000
> 1) We use it directly as a scratch buffer for now since the
> frags are always linearised currently.
And since skb_shinfo(skb)->nr_frags will be zero, nobody
will mistakedly look at the contents and interpret it as
some valid frags. Right?
^ permalink raw reply
* Re: [RFC] Replace scatterlist with crypto_frag
From: Herbert Xu @ 2005-06-06 23:14 UTC (permalink / raw)
To: David S. Miller; +Cc: hch, jmorris, linux-crypto, netdev
In-Reply-To: <20050606.160947.75190168.davem@davemloft.net>
On Mon, Jun 06, 2005 at 04:09:47PM -0700, David S. Miller wrote:
>
> So you want to use this area as a sort-of temporary
> scratch pad for something other than scatterlist
> information? That's interesting if so...
There are two possibilities:
1) We use it directly as a scratch buffer for now since the
frags are always linearised currently.
2) We have a list of lists of which this is simply a member.
The meta-list itself can then be stored on the stack since
each member is only 4 bytes.
We can go with 1) for now. When it becomes possible for us
to not flatten the frags, we can switch to 2).
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
* Re: [RFC] Replace scatterlist with crypto_frag
From: David S. Miller @ 2005-06-06 23:09 UTC (permalink / raw)
To: herbert; +Cc: hch, jmorris, linux-crypto, netdev
In-Reply-To: <20050606230437.GA7172@gondor.apana.org.au>
From: Herbert Xu <herbert@gondor.apana.org.au>
Date: Tue, 7 Jun 2005 09:04:37 +1000
> Bigger is better actually :) I'm now thinking of using the
> memory occupied by the frags array for IPsec crypto operations.
> So if it's bigger then it simply means that we can store more
> fragments.
So you want to use this area as a sort-of temporary
scratch pad for something other than scatterlist
information? That's interesting if so...
^ permalink raw reply
* Re: [RFC] Replace scatterlist with crypto_frag
From: Jeff Garzik @ 2005-06-06 23:05 UTC (permalink / raw)
To: David S. Miller; +Cc: herbert, hch, jmorris, linux-crypto, netdev
In-Reply-To: <20050606.154653.64001264.davem@davemloft.net>
David S. Miller wrote:
> The question is where to put the DMA mapping cookies :-)
Indeed.
Jeff
^ permalink raw reply
* Re: [RFC] Replace scatterlist with crypto_frag
From: Herbert Xu @ 2005-06-06 23:04 UTC (permalink / raw)
To: David S. Miller; +Cc: hch, jmorris, linux-crypto, netdev
In-Reply-To: <20050606.154653.64001264.davem@davemloft.net>
On Mon, Jun 06, 2005 at 03:46:53PM -0700, David S. Miller wrote:
>
> So I guess I'm taking you a step backwards, I want to make
> skb_frag_struct a little bigger :-) Ie. put the DMA mapping
> cookies into the skb_frag_struct, then a set of accessor
> macros like we have for scatterlist. Well, in fact, it would
> become a scatterlist and therefore the only thing special
> about dma_map_skb() is that is maps a linear buffer via
> skb->data then the scatterlist in skb_shared_info(skb).
Bigger is better actually :) I'm now thinking of using the
memory occupied by the frags array for IPsec crypto operations.
So if it's bigger then it simply means that we can store more
fragments.
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
* Re: [RFC] Replace scatterlist with crypto_frag
From: David S. Miller @ 2005-06-06 22:46 UTC (permalink / raw)
To: herbert; +Cc: hch, jmorris, linux-crypto, netdev
In-Reply-To: <20050606124043.GA625@gondor.apana.org.au>
From: Herbert Xu <herbert@gondor.apana.org.au>
Date: Mon, 6 Jun 2005 22:40:43 +1000
> However, for skb_frag_t at least going to the 32-bit version on i386
> means at least 72 bytes extra for every skb->data allocation.
>
> Dave, what are your views on making skb_frag_t bigger?
Good question.
There is an ancillary issue that I'd like to address at
some point, and what you do here is tied into that.
Currently, NETIF_F_SG drivers do one DMA mapping call for
each fragment of the packet. That totally stinks performance
wise, and the PPC64 and SPARC64 folks feel this the most.
So I wanted to create a set of interfaces ala:
int dma_map_skb(struct sk_buff *skb, ...);
void dma_unmap_skb(struct sk_buff *skb, ...);
void dma_sync_skb_for_cpu(struct sk_buff *skb, ...);
void dma_sync_skb_for_device(struct sk_buff *skb, ...);
The question is where to put the DMA mapping cookies :-)
On i386 and alike, using something like the DECLARE_PCI_UNMAP_*()
macros would allow us to NOP out the DMA addresses entirely. Since
they are computable from the page struct and offset.
Note that the above interface, on IOMMU platforms, would allow
DMA coalescing to be performed. This would hit heavily with
TSO, for example. Most packets would go out with a maximum of
2 DMA descriptors, 1 for the mapping of skb->data and 1 for
all of the paged SKB data afterwards combined.
Note that, due to this coalescing, the "size" member must be
larger than a __u16.
So I guess I'm taking you a step backwards, I want to make
skb_frag_struct a little bigger :-) Ie. put the DMA mapping
cookies into the skb_frag_struct, then a set of accessor
macros like we have for scatterlist. Well, in fact, it would
become a scatterlist and therefore the only thing special
about dma_map_skb() is that is maps a linear buffer via
skb->data then the scatterlist in skb_shared_info(skb).
^ permalink raw reply
* [PATCH][5/5] RapidIO support: net driver
From: Matt Porter @ 2005-06-06 22:40 UTC (permalink / raw)
To: linux-kernel; +Cc: shemminger, linuxppc-embedded, netdev
In-Reply-To: <11180976151080@foobar.com>
Adds an "Ethernet" driver which sends Ethernet packets over the
standard RapidIO messaging. This depends on the core RIO
patch for mailbox/doorbell access.
Signed-off-by: Matt Porter <mporter@kernel.crashing.org>
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -2185,6 +2185,20 @@ config ISERIES_VETH
tristate "iSeries Virtual Ethernet driver support"
depends on NETDEVICES && PPC_ISERIES
+config RIONET
+ tristate "RapidIO Ethernet over messaging driver support"
+ depends on NETDEVICES && RAPIDIO
+
+config RIONET_TX_SIZE
+ int "Number of outbound queue entries"
+ depends on RIONET
+ default "128"
+
+config RIONET_RX_SIZE
+ int "Number of inbound queue entries"
+ depends on RIONET
+ default "128"
+
config FDDI
bool "FDDI driver support"
depends on NETDEVICES && (PCI || EISA)
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -58,6 +58,7 @@ obj-$(CONFIG_SKFP) += skfp/
obj-$(CONFIG_VIA_RHINE) += via-rhine.o
obj-$(CONFIG_VIA_VELOCITY) += via-velocity.o
obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o
+obj-$(CONFIG_RIONET) += rionet.o
#
# end link order section
diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c
new file mode 100644
--- /dev/null
+++ b/drivers/net/rionet.c
@@ -0,0 +1,597 @@
+/*
+ * rionet - Ethernet driver over RapidIO messaging services
+ *
+ * Copyright 2005 MontaVista Software, Inc.
+ * Matt Porter <mporter@kernel.crashing.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/rio.h>
+#include <linux/rio_drv.h>
+#include <linux/rio_ids.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/crc32.h>
+#include <linux/ethtool.h>
+
+#define DRV_NAME "rionet"
+#define DRV_VERSION "0.1"
+#define DRV_AUTHOR "Matt Porter <mporter@kernel.crashing.org>"
+#define DRV_DESC "Ethernet over RapidIO"
+
+MODULE_AUTHOR(DRV_AUTHOR);
+MODULE_DESCRIPTION(DRV_DESC);
+MODULE_LICENSE("GPL");
+
+#define RIONET_DEFAULT_MSGLEVEL 0
+#define RIONET_DOORBELL_JOIN 0x1000
+#define RIONET_DOORBELL_LEAVE 0x1001
+
+#define RIONET_MAILBOX 0
+
+#define RIONET_TX_RING_SIZE CONFIG_RIONET_TX_SIZE
+#define RIONET_RX_RING_SIZE CONFIG_RIONET_RX_SIZE
+
+static LIST_HEAD(rionet_peers);
+
+struct rionet_private {
+ struct rio_mport *mport;
+ struct sk_buff *rx_skb[RIONET_RX_RING_SIZE];
+ struct sk_buff *tx_skb[RIONET_TX_RING_SIZE];
+ struct net_device_stats stats;
+ int rx_slot;
+ int tx_slot;
+ int tx_cnt;
+ int ack_slot;
+ spinlock_t lock;
+ spinlock_t tx_lock;
+ u32 msg_enable;
+};
+
+struct rionet_peer {
+ struct list_head node;
+ struct rio_dev *rdev;
+ struct resource *res;
+};
+
+static int rionet_check = 0;
+static int rionet_capable = 1;
+static struct net_device *sndev = NULL;
+
+/*
+ * This is a fast lookup table for for translating TX
+ * Ethernet packets into a destination RIO device. It
+ * could be made into a hash table to save memory depending
+ * on system trade-offs.
+ */
+static struct rio_dev *rionet_active[RIO_MAX_ROUTE_ENTRIES];
+
+#define is_rionet_capable(pef, src_ops, dst_ops) \
+ ((pef & RIO_PEF_INB_MBOX) && \
+ (pef & RIO_PEF_INB_DOORBELL) && \
+ (src_ops & RIO_SRC_OPS_DOORBELL) && \
+ (dst_ops & RIO_DST_OPS_DOORBELL))
+#define dev_rionet_capable(dev) \
+ is_rionet_capable(dev->pef, dev->src_ops, dev->dst_ops)
+
+#define RIONET_MAC_MATCH(x) (*(u32 *)x == 0x00010001)
+#define RIONET_GET_DESTID(x) (*(u16 *)(x + 4))
+
+static struct net_device_stats *rionet_stats(struct net_device *ndev)
+{
+ struct rionet_private *rnet = ndev->priv;
+ return &rnet->stats;
+}
+
+static int rionet_rx_clean(struct net_device *ndev)
+{
+ int i;
+ int error = 0;
+ struct rionet_private *rnet = ndev->priv;
+ void *data;
+
+ i = rnet->rx_slot;
+
+ do {
+ if (!rnet->rx_skb[i]) {
+ rnet->stats.rx_dropped++;
+ continue;
+ }
+
+ if (!(data = rio_get_inb_message(rnet->mport, RIONET_MAILBOX)))
+ break;
+
+ rnet->rx_skb[i]->data = data;
+ skb_put(rnet->rx_skb[i], RIO_MAX_MSG_SIZE);
+ rnet->rx_skb[i]->dev = ndev;
+ rnet->rx_skb[i]->protocol =
+ eth_type_trans(rnet->rx_skb[i], ndev);
+ error = netif_rx(rnet->rx_skb[i]);
+
+ if (error == NET_RX_DROP) {
+ rnet->stats.rx_dropped++;
+ } else if (error == NET_RX_BAD) {
+ if (netif_msg_rx_err(rnet))
+ printk(KERN_WARNING "%s: bad rx packet\n",
+ DRV_NAME);
+ rnet->stats.rx_errors++;
+ } else {
+ rnet->stats.rx_packets++;
+ rnet->stats.rx_bytes += RIO_MAX_MSG_SIZE;
+ }
+
+ } while ((i = (i + 1) % RIONET_RX_RING_SIZE) != rnet->rx_slot);
+
+ return i;
+}
+
+static void rionet_rx_fill(struct net_device *ndev, int end)
+{
+ int i;
+ struct rionet_private *rnet = ndev->priv;
+
+ i = rnet->rx_slot;
+ do {
+ rnet->rx_skb[i] = dev_alloc_skb(RIO_MAX_MSG_SIZE);
+
+ if (!rnet->rx_skb[i])
+ break;
+
+ rio_add_inb_buffer(rnet->mport, RIONET_MAILBOX,
+ rnet->rx_skb[i]->data);
+ } while ((i = (i + 1) % RIONET_RX_RING_SIZE) != end);
+
+ rnet->rx_slot = i;
+}
+
+static int rionet_queue_tx_msg(struct sk_buff *skb, struct net_device *ndev,
+ struct rio_dev *rdev)
+{
+ struct rionet_private *rnet = ndev->priv;
+
+ rio_add_outb_message(rnet->mport, rdev, 0, skb->data, skb->len);
+ rnet->tx_skb[rnet->tx_slot] = skb;
+
+ rnet->stats.tx_packets++;
+ rnet->stats.tx_bytes += skb->len;
+
+ if (++rnet->tx_cnt == RIONET_TX_RING_SIZE)
+ netif_stop_queue(ndev);
+
+ if (++rnet->tx_slot == RIONET_TX_RING_SIZE)
+ rnet->tx_slot = 0;
+
+ if (netif_msg_tx_queued(rnet))
+ printk(KERN_INFO "%s: queued skb %8.8x len %8.8x\n", DRV_NAME,
+ (u32) skb, skb->len);
+
+ return 0;
+}
+
+static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
+{
+ int i;
+ struct rionet_private *rnet = ndev->priv;
+ struct ethhdr *eth = (struct ethhdr *)skb->data;
+ u16 destid;
+ unsigned long flags;
+
+ local_irq_save(flags);
+ if (!spin_trylock(&rnet->tx_lock)) {
+ local_irq_restore(flags);
+ return NETDEV_TX_LOCKED;
+ }
+
+ if ((rnet->tx_cnt + 1) > RIONET_TX_RING_SIZE) {
+ netif_stop_queue(ndev);
+ spin_unlock_irqrestore(&rnet->tx_lock, flags);
+ printk(KERN_ERR "%s: BUG! Tx Ring full when queue awake!\n",
+ ndev->name);
+ return NETDEV_TX_BUSY;
+ }
+
+ if (eth->h_dest[0] & 0x01) {
+ /*
+ * XXX Need to delay queuing if ring max is reached,
+ * flush additional packets in tx_event() before
+ * awakening the queue. We can easily exceed ring
+ * size with a large number of nodes or even a
+ * small number where the ring is relatively full
+ * on entrance to hard_start_xmit.
+ */
+ for (i = 0; i < RIO_MAX_ROUTE_ENTRIES; i++)
+ if (rionet_active[i])
+ rionet_queue_tx_msg(skb, ndev,
+ rionet_active[i]);
+ } else if (RIONET_MAC_MATCH(eth->h_dest)) {
+ destid = RIONET_GET_DESTID(eth->h_dest);
+ if (rionet_active[destid])
+ rionet_queue_tx_msg(skb, ndev, rionet_active[destid]);
+ }
+
+ spin_unlock_irqrestore(&rnet->tx_lock, flags);
+
+ return 0;
+}
+
+static int rionet_set_mac_address(struct net_device *ndev, void *p)
+{
+ struct sockaddr *addr = p;
+
+ if (!is_valid_ether_addr(addr->sa_data))
+ return -EADDRNOTAVAIL;
+
+ memcpy(ndev->dev_addr, addr->sa_data, ndev->addr_len);
+
+ return 0;
+}
+
+static void rionet_dbell_event(struct rio_mport *mport, u16 sid, u16 tid,
+ u16 info)
+{
+ struct net_device *ndev = sndev;
+ struct rionet_private *rnet = ndev->priv;
+ struct rionet_peer *peer;
+
+ if (netif_msg_intr(rnet))
+ printk(KERN_INFO "%s: doorbell sid %4.4x tid %4.4x info %4.4x",
+ DRV_NAME, sid, tid, info);
+ if (info == RIONET_DOORBELL_JOIN) {
+ if (!rionet_active[sid]) {
+ list_for_each_entry(peer, &rionet_peers, node) {
+ if (peer->rdev->destid == sid)
+ rionet_active[sid] = peer->rdev;
+ }
+ rio_mport_send_doorbell(mport, sid,
+ RIONET_DOORBELL_JOIN);
+ }
+ } else if (info == RIONET_DOORBELL_LEAVE) {
+ rionet_active[sid] = NULL;
+ } else {
+ if (netif_msg_intr(rnet))
+ printk(KERN_WARNING "%s: unhandled doorbell\n",
+ DRV_NAME);
+ }
+}
+
+static void rionet_inb_msg_event(struct rio_mport *mport, int mbox, int slot)
+{
+ int n;
+ struct net_device *ndev = sndev;
+ struct rionet_private *rnet = (struct rionet_private *)ndev->priv;
+
+ if (netif_msg_intr(rnet))
+ printk(KERN_INFO "%s: inbound message event, mbox %d slot %d\n",
+ DRV_NAME, mbox, slot);
+
+ spin_lock(&rnet->lock);
+ if ((n = rionet_rx_clean(ndev)) != rnet->rx_slot)
+ rionet_rx_fill(ndev, n);
+ spin_unlock(&rnet->lock);
+}
+
+static void rionet_outb_msg_event(struct rio_mport *mport, int mbox, int slot)
+{
+ struct net_device *ndev = sndev;
+ struct rionet_private *rnet = ndev->priv;
+
+ spin_lock(&rnet->lock);
+
+ if (netif_msg_intr(rnet))
+ printk(KERN_INFO
+ "%s: outbound message event, mbox %d slot %d\n",
+ DRV_NAME, mbox, slot);
+
+ while (rnet->tx_cnt && (rnet->ack_slot != slot)) {
+ /* dma unmap single */
+ dev_kfree_skb_irq(rnet->tx_skb[rnet->ack_slot]);
+ rnet->tx_skb[rnet->ack_slot] = NULL;
+ if (++rnet->ack_slot == RIONET_TX_RING_SIZE)
+ rnet->ack_slot = 0;
+ rnet->tx_cnt--;
+ }
+
+ if (rnet->tx_cnt < RIONET_TX_RING_SIZE)
+ netif_wake_queue(ndev);
+
+ spin_unlock(&rnet->lock);
+}
+
+static int rionet_open(struct net_device *ndev)
+{
+ int i, rc = 0;
+ struct rionet_peer *peer, *tmp;
+ u32 pwdcsr;
+ struct rionet_private *rnet = ndev->priv;
+
+ if (netif_msg_ifup(rnet))
+ printk(KERN_INFO "%s: open\n", DRV_NAME);
+
+ if ((rc = rio_request_inb_dbell(rnet->mport,
+ RIONET_DOORBELL_JOIN,
+ RIONET_DOORBELL_LEAVE,
+ rionet_dbell_event)) < 0)
+ goto out;
+
+ if ((rc = rio_request_inb_mbox(rnet->mport,
+ RIONET_MAILBOX,
+ RIONET_RX_RING_SIZE,
+ rionet_inb_msg_event)) < 0)
+ goto out;
+
+ if ((rc = rio_request_outb_mbox(rnet->mport,
+ RIONET_MAILBOX,
+ RIONET_TX_RING_SIZE,
+ rionet_outb_msg_event)) < 0)
+ goto out;
+
+ /* Initialize inbound message ring */
+ for (i = 0; i < RIONET_RX_RING_SIZE; i++)
+ rnet->rx_skb[i] = NULL;
+ rnet->rx_slot = 0;
+ rionet_rx_fill(ndev, 0);
+
+ rnet->tx_slot = 0;
+ rnet->tx_cnt = 0;
+ rnet->ack_slot = 0;
+
+ netif_carrier_on(ndev);
+ netif_start_queue(ndev);
+
+ list_for_each_entry_safe(peer, tmp, &rionet_peers, node) {
+ if (!(peer->res = rio_request_outb_dbell(peer->rdev,
+ RIONET_DOORBELL_JOIN,
+ RIONET_DOORBELL_LEAVE)))
+ {
+ printk(KERN_ERR "%s: error requesting doorbells\n",
+ DRV_NAME);
+ continue;
+ }
+
+ /*
+ * If device has initialized inbound doorbells,
+ * send a join message
+ */
+ rio_read_config_32(peer->rdev, RIO_WRITE_PORT_CSR, &pwdcsr);
+ if (pwdcsr & RIO_DOORBELL_AVAIL)
+ rio_send_doorbell(peer->rdev, RIONET_DOORBELL_JOIN);
+ }
+
+ out:
+ return rc;
+}
+
+static int rionet_close(struct net_device *ndev)
+{
+ struct rionet_private *rnet = (struct rionet_private *)ndev->priv;
+ struct rionet_peer *peer, *tmp;
+ int i;
+
+ if (netif_msg_ifup(rnet))
+ printk(KERN_INFO "%s: close\n", DRV_NAME);
+
+ netif_stop_queue(ndev);
+ netif_carrier_off(ndev);
+
+ for (i = 0; i < RIONET_RX_RING_SIZE; i++)
+ if (rnet->rx_skb[i])
+ kfree_skb(rnet->rx_skb[i]);
+
+ list_for_each_entry_safe(peer, tmp, &rionet_peers, node) {
+ if (rionet_active[peer->rdev->destid]) {
+ rio_send_doorbell(peer->rdev, RIONET_DOORBELL_LEAVE);
+ rionet_active[peer->rdev->destid] = NULL;
+ }
+ rio_release_outb_dbell(peer->rdev, peer->res);
+ }
+
+ rio_release_inb_dbell(rnet->mport, RIONET_DOORBELL_JOIN,
+ RIONET_DOORBELL_LEAVE);
+ rio_release_inb_mbox(rnet->mport, RIONET_MAILBOX);
+ rio_release_outb_mbox(rnet->mport, RIONET_MAILBOX);
+
+ return 0;
+}
+
+static void rionet_remove(struct rio_dev *rdev)
+{
+ struct net_device *ndev = NULL;
+ struct rionet_peer *peer, *tmp;
+
+ unregister_netdev(ndev);
+ kfree(ndev);
+
+ list_for_each_entry_safe(peer, tmp, &rionet_peers, node) {
+ list_del(&peer->node);
+ kfree(peer);
+ }
+}
+
+static void rionet_get_drvinfo(struct net_device *ndev,
+ struct ethtool_drvinfo *info)
+{
+ struct rionet_private *rnet = ndev->priv;
+
+ strcpy(info->driver, DRV_NAME);
+ strcpy(info->version, DRV_VERSION);
+ strcpy(info->fw_version, "n/a");
+ sprintf(info->bus_info, "RIO master port %d", rnet->mport->id);
+}
+
+static u32 rionet_get_msglevel(struct net_device *ndev)
+{
+ struct rionet_private *rnet = ndev->priv;
+
+ return rnet->msg_enable;
+}
+
+static void rionet_set_msglevel(struct net_device *ndev, u32 value)
+{
+ struct rionet_private *rnet = ndev->priv;
+
+ rnet->msg_enable = value;
+}
+
+static struct ethtool_ops rionet_ethtool_ops = {
+ .get_drvinfo = rionet_get_drvinfo,
+ .get_msglevel = rionet_get_msglevel,
+ .set_msglevel = rionet_set_msglevel,
+ .get_link = ethtool_op_get_link,
+};
+
+static int rionet_setup_netdev(struct rio_mport *mport)
+{
+ int rc = 0;
+ struct net_device *ndev = NULL;
+ struct rionet_private *rnet;
+ u16 device_id;
+
+ /* Allocate our net_device structure */
+ ndev = alloc_etherdev(sizeof(struct rionet_private));
+ if (ndev == NULL) {
+ printk(KERN_INFO "%s: could not allocate ethernet device.\n",
+ DRV_NAME);
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ /*
+ * XXX hack, store point a static at ndev so we can get it...
+ * Perhaps need an array of these that the handler can
+ * index via the mbox number.
+ */
+ sndev = ndev;
+
+ /* Set up private area */
+ rnet = (struct rionet_private *)ndev->priv;
+ rnet->mport = mport;
+
+ /* Set the default MAC address */
+ device_id = rio_local_get_device_id(mport);
+ ndev->dev_addr[0] = 0x00;
+ ndev->dev_addr[1] = 0x01;
+ ndev->dev_addr[2] = 0x00;
+ ndev->dev_addr[3] = 0x01;
+ ndev->dev_addr[4] = device_id >> 8;
+ ndev->dev_addr[5] = device_id & 0xff;
+
+ /* Fill in the driver function table */
+ ndev->open = &rionet_open;
+ ndev->hard_start_xmit = &rionet_start_xmit;
+ ndev->stop = &rionet_close;
+ ndev->get_stats = &rionet_stats;
+ ndev->set_mac_address = &rionet_set_mac_address;
+ ndev->mtu = RIO_MAX_MSG_SIZE - 14;
+ ndev->features = NETIF_F_LLTX;
+ SET_ETHTOOL_OPS(ndev, &rionet_ethtool_ops);
+
+ SET_MODULE_OWNER(ndev);
+
+ spin_lock_init(&rnet->lock);
+ spin_lock_init(&rnet->tx_lock);
+
+ rnet->msg_enable = RIONET_DEFAULT_MSGLEVEL;
+
+ rc = register_netdev(ndev);
+ if (rc != 0)
+ goto out;
+
+ printk("%s: %s %s Version %s, MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
+ ndev->name,
+ DRV_NAME,
+ DRV_DESC,
+ DRV_VERSION,
+ ndev->dev_addr[0], ndev->dev_addr[1], ndev->dev_addr[2],
+ ndev->dev_addr[3], ndev->dev_addr[4], ndev->dev_addr[5]);
+
+ out:
+ return rc;
+}
+
+/*
+ * XXX Make multi-net safe
+ */
+static int rionet_probe(struct rio_dev *rdev, const struct rio_device_id *id)
+{
+ int rc = -ENODEV;
+ u32 lpef, lsrc_ops, ldst_ops;
+ struct rionet_peer *peer;
+
+ /* If local device is not rionet capable, give up quickly */
+ if (!rionet_capable)
+ goto out;
+
+ /*
+ * First time through, make sure local device is rionet
+ * capable, setup netdev, and set flags so this is skipped
+ * on later probes
+ */
+ if (!rionet_check) {
+ rio_local_read_config_32(rdev->net->hport, RIO_PEF_CAR, &lpef);
+ rio_local_read_config_32(rdev->net->hport, RIO_SRC_OPS_CAR,
+ &lsrc_ops);
+ rio_local_read_config_32(rdev->net->hport, RIO_DST_OPS_CAR,
+ &ldst_ops);
+ if (!is_rionet_capable(lpef, lsrc_ops, ldst_ops)) {
+ printk(KERN_ERR
+ "%s: local device is not network capable\n",
+ DRV_NAME);
+ rionet_check = 1;
+ rionet_capable = 0;
+ goto out;
+ }
+
+ rc = rionet_setup_netdev(rdev->net->hport);
+ rionet_check = 1;
+ }
+
+ /*
+ * If the remote device has mailbox/doorbell capabilities,
+ * add it to the peer list.
+ */
+ if (dev_rionet_capable(rdev)) {
+ if (!(peer = kmalloc(sizeof(struct rionet_peer), GFP_KERNEL))) {
+ rc = -ENOMEM;
+ goto out;
+ }
+ peer->rdev = rdev;
+ list_add_tail(&peer->node, &rionet_peers);
+ }
+
+ out:
+ return rc;
+}
+
+static struct rio_device_id rionet_id_table[] = {
+ {RIO_DEVICE(RIO_ANY_ID, RIO_ANY_ID)}
+};
+
+static struct rio_driver rionet_driver = {
+ .name = "rionet",
+ .id_table = rionet_id_table,
+ .probe = rionet_probe,
+ .remove = rionet_remove,
+};
+
+static int __init rionet_init(void)
+{
+ return rio_register_driver(&rionet_driver);
+}
+
+static void __exit rionet_exit(void)
+{
+ rio_unregister_driver(&rionet_driver);
+}
+
+module_init(rionet_init);
+module_exit(rionet_exit);
^ permalink raw reply
* Re: [RFC] Replace scatterlist with crypto_frag
From: David S. Miller @ 2005-06-06 22:36 UTC (permalink / raw)
To: herbert; +Cc: johnpol, jmorris, linux-crypto, netdev
In-Reply-To: <20050604103249.GA1378@gondor.apana.org.au>
From: Herbert Xu <herbert@gondor.apana.org.au>
Date: Sat, 4 Jun 2005 20:32:49 +1000
> On Sat, Jun 04, 2005 at 02:29:39PM +0400, Evgeniy Polyakov wrote:
> >
> > But without sg we sill save 4*sizeof(dma addr) - is it really a price?
>
> We're also reducing the offset/length to 16 bits from 32 bits so we're
> shaving off half the size.
Note, it is still going to be a 16 byte structure on 64-bit
machines. This is mainly due to the 8-byte alignment needed
by the page pointer.
I'm not objecting to your ideas, just mentioning this fact...
I am also puzzled as to where the "4" came from :-)
^ permalink raw reply
* Re: [PATCHSET] PKT_SCHED related fixes and a meta ematch completion
From: David S. Miller @ 2005-06-06 22:29 UTC (permalink / raw)
To: tgraf; +Cc: netdev
In-Reply-To: <20050603211241.593114000@axs>
From: Thomas Graf <tgraf@suug.ch>
Date: Fri, 03 Jun 2005 23:12:41 +0200
> The following patchset fixes some serious bugs that prevent
> the basic classifier and the meta ematch from working properly.
> Patch 2 adds a few new meta collectors for socket attribtues which
> I'd like to have in 2.6.12 as well. If you think this is too
> intrusive (it isn't ;->) I'll resend patch 4 with offsets fixed.
I'll try to get these 4 patches into 2.6.12, they all look
straight forward and sane to me.
Thanks Thomas.
^ permalink raw reply
* Re: [PATCH] tg3: Fix link failure in 5701
From: David S. Miller @ 2005-06-06 22:27 UTC (permalink / raw)
To: iod00d; +Cc: mchan, peterc, netdev
In-Reply-To: <20050606222631.GE12068@esmail.cup.hp.com>
From: Grant Grundler <iod00d@hp.com>
Date: Mon, 6 Jun 2005 15:26:31 -0700
> Btw, where can I see which version of tg3 will get this fix?
>
> I'm certainly I'll be asked the question "which tg3 version
> is required" more than the few times.
It will be version "3.30" with release date "June 6, 2005"
I will push it to Linus as soon as the kernel.org mirror
system picks it up from my GIT tree at:
rsync://rsync.kernel.org/pub/scm/linux/kernel/git/davem/tg3-2.6.git/
^ permalink raw reply
* Re: [PATCH] tg3: Fix link failure in 5701
From: Grant Grundler @ 2005-06-06 22:26 UTC (permalink / raw)
To: David S. Miller; +Cc: mchan, iod00d, peterc, netdev
In-Reply-To: <20050606.151641.95895557.davem@davemloft.net>
On Mon, Jun 06, 2005 at 03:16:41PM -0700, David S. Miller wrote:
> Applied, thanks a log.
Dave,
Btw, where can I see which version of tg3 will get this fix?
I'm certainly I'll be asked the question "which tg3 version
is required" more than the few times.
thanks,
grant
ps. Thanks Michael!
^ permalink raw reply
* Re: [PATCH] tg3: Fix link failure in 5701
From: David S. Miller @ 2005-06-06 22:16 UTC (permalink / raw)
To: mchan; +Cc: iod00d, peterc, netdev
In-Reply-To: <1118086942.5008.14.camel@rh4>
From: "Michael Chan" <mchan@broadcom.com>
Date: Mon, 06 Jun 2005 12:42:22 -0700
> On some 5701 devices with older bootcode, the LED configuration bits in
> SRAM may be invalid with value zero. The fix is to check for invalid
> bits (0) and default to PHY 1 mode. Incorrect LED mode will lead to
> error in programming the PHY.
>
> Thanks to Grant Grundler for debugging the problem.
Applied, thanks a log.
^ permalink raw reply
* Fwd: [Bug 4615] Modem connection stalls out.
From: Russell King @ 2005-06-06 21:47 UTC (permalink / raw)
To: netdev
Anyone have any ideas on this bug?
The "No buffer space available" looks like the system is running low on
memory. Would networking folk concur with that?
----- Forwarded message from bugme-daemon@kernel-bugs.osdl.org -----
Date: Mon, 6 Jun 2005 09:19:47 -0700
From: bugme-daemon@kernel-bugs.osdl.org
To: rmk@arm.linux.org.uk
Subject: [Bug 4615] Modem connection stalls out.
http://bugzilla.kernel.org/show_bug.cgi?id=4615
------- Additional Comments From alangrimes@starpower.net 2005-06-06 09:19 -------
The only reliable feedback I get from the bug, asside from its obvious symptoms,
is through ping...
Here is a typical output:
64 bytes from 10.65.28.26: icmp_seq=296 ttl=255 time=2552 ms
64 bytes from 10.65.28.26: icmp_seq=297 ttl=255 time=1561 ms
64 bytes from 10.65.28.26: icmp_seq=298 ttl=255 time=567 ms
64 bytes from 10.65.28.26: icmp_seq=299 ttl=255 time=137 ms
64 bytes from 10.65.28.26: icmp_seq=300 ttl=255 time=484 ms # Hmm, exactly 5
## minutes, though I've seen it quit after only 10 seconds...)
ping: sendmsg: No buffer space available
ping: sendmsg: No buffer space available
ping: sendmsg: No buffer space available
ping: sendmsg: No buffer space available
ping: sendmsg: No buffer space available
ping: sendmsg: No buffer space available
## It would have continued repeating this message indefinitely...
## Note: many more iterations have been removed from this report!!! =P
## Below is what happens when I manually disconnect the modem by sending
## the break signal to the dialer.
ping: sendmsg: Network is unreachable
ping: sendmsg: Network is unreachable
ping: sendmsg: Network is unreachable
ping: sendmsg: Network is unreachable
--- 10.65.28.26 ping statistics ---
337 packets transmitted, 300 received, 10% packet loss, time 35529
5ms
rtt min/avg/max/mdev = 122.973/687.037/6298.163/1093.624 ms, pipe
7
###################################
After power cycling the modem here's what the dialer does:
leenooks ~ # wvdial
--> WvDial: Internet dialer version 1.54.0
--> Initializing modem.
--> Sending: ATZ
--> Sending: ATQ0
--> Re-Sending: ATZ
### the dialer is hung and will report that the modem is not responding in a
### few seconds...
### At this point I could ctrl-break the dialer and try again,
### However, this would be entirely unproductive as I'd get the same mesage
### each and every time.
### Only by allowing it to complete its cycle, will it return the modem to
### functionality. I suspect that the dialer sends an IOCTL or something to the
### driver which clears the fault...
--> Modem not responding.
leenooks ~ # wvdial
--> WvDial: Internet dialer version 1.54.0
--> Initializing modem.
--> Sending: ATZ
ATZ
OK
--> Sending: AT&F&D2&C1X4V1Q0S7=70W2\N3&K3S11=60
AT&F&D2&C1X4V1Q0S7=70W2\N3&K3S11=60
OK
--> Modem initialized.
--> Sending: ATDT7038298111
--> Waiting for carrier.
ATDT7038298111
CONNECT 49333
--> Carrier detected. Waiting for prompt.
** Ascend TNT2.LNHVA.MD.RCN.NET Terminal Server **
Login:
--> Looks like a login prompt.
--> Sending: alangrimes
alangrimes
Password:
--> Looks like a password prompt.
--> Sending: (password)
Entering PPP Session.
IP address is 66.44.56.212
MTU is 1006.
--> Looks like a welcome message.
--> Starting pppd at Tue Jun 7 04:58:30 2005
--> pid of pppd: 19733
--> Using interface ppp0
--> local IP address 66.44.56.212
--> remote IP address 10.65.28.27
--> primary DNS address 207.172.3.10
--> secondary DNS address 207.172.3.11
------- You are receiving this mail because: -------
You are the assignee for the bug, or are watching the assignee.
----- End forwarded message -----
--
Russell King
^ permalink raw reply
* RE: RFC: NAPI packet weighting patch
From: Ronciak, John @ 2005-06-06 20:29 UTC (permalink / raw)
To: David S. Miller
Cc: mchan, hadi, buytenh, Williams, Mitch A, jdmason, shemminger,
netdev, Robert.Olsson, Venkatesan, Ganesh, Brandeburg, Jesse
> If you force the e1000 driver to do RX replenishment every N
> packets it should reduce the packet drops the same (in the
> single NIC case) as if you reduced the dev->weight to that
> same value N.
But this isn't what we are seeing. Even if we just reduce the weight
value to 32 from 64, all of the drops go away. So there seems to be
other things affecting this.
We are just talking about single NIC testing at this point. I agree
that single and multi-NIC results different issues and we will need to
test this as well with whatever we come up with out of this.
I also like your idea about the weight value being adjusted based on
real work done using some measurable metric. This seems like a good
path to explore as well.
Cheers,
John
^ permalink raw reply
* Re: New address announcements in RTMGRP_IPV4_IFADDR netlink group
From: Thomas Graf @ 2005-06-06 19:54 UTC (permalink / raw)
To: Teemu Koponen; +Cc: netdev
In-Reply-To: <aa027950f2fc7f2ad640cac4a11fbe93@iki.fi>
* Teemu Koponen <aa027950f2fc7f2ad640cac4a11fbe93@iki.fi> 2005-06-06 11:59
> 0) A userspace daemon process is running and listening to the broadcast
> group.
>
> 1) Address is inserted to an interface (ip addr add ... at shell).
>
> 2) The daemon receives a NEWADDR message, just as is should, but the
> daemon is unable to bind to the address *immediately* (actually in the
> function that processes the netlink message). The result is "cannot
> assign an address" from the bind call. However, if I do insert a single
> nanosleep, even with an arbitrary low sleep value, before the bind
> call, the bind then succeeds.
>
> So, what is the semantics of NEWADDR? Should the address be bindable
> right after receiving the message?
The bind() call doesn't fail because of the address being non-existant,
it fails because the route has not been created for it. The netlink
message is generated before we notify the other subsystems about the
addition of a new address so you try to bind to an adress for which
no route has been generated yet. The best solution is probably to wait
for the route addition notification message being received and then
bind to that address.
^ permalink raw reply
* IPV6 RFC3542 compliance [PATCH]
From: David Stevens @ 2005-06-06 19:48 UTC (permalink / raw)
To: davem, yoshfuji; +Cc: netdev
[-- Attachment #1: Type: text/plain, Size: 19490 bytes --]
I've been looking at RFC 3542 (Advanced Sockets API) compliance,
and found the following:
("x" is one of {PKTINFO, HOPLIMIT, RTHDR, DSTOPTS, TCLASS })
What RFC 3542 says:
1) IPV6_x as socket options specify "sticky" option values;
getsockopt() returns the current values of the sticky options
setsockopt() sets the values for future sends
2) IPV6_RECVx are boolean socket options indicated whether the
particular field will be returned in ancillary data on a recvmsg()
getsockopt() gets the current value (1 or 0)
setsockopt() sets or clears the boolean value
3) Ancillary data (send and receive) use IPV6_x for the corresponding
data item
What current kernel does:
1) IPV6_x are boolean options
2) the sticky versions are not implemented
3) TCLASS is not implemented
The patch below adds sending and receiving of traffic class, the
definitions for IPV6_RECVx and changes the boolean socket options
to their RFC 3542 names. The original names are still there for use
with sticky options in the future (not included here), and as the
ancillary data message types.
The bad news:
This patch changes the argument lists of ip6_append_data() and
datagram_send_ctl(). This, because traffic class is not an extension
header, but part of the IPv6 header. This is analogous to the hop limit,
which is an explicit argument to these functions.
I've tested these pieces, but I have a couple open questions which
may be relevant (will continue looking myself...):
1) In ipv6_pinfo, there is a "hop_limit" field at the top level and
another
"cork.hop_limit". Why aren't these the same?
2) The (old name) IPV6_RTHDR socket option allows a value of "2",
used by TCP. Still need to see what that's about for relevance
to other options (but this code leaves that unchanged, except
the name).
+-DLS
in-line for view, attached for applying
Signed-off-by: David L Stevens <dlstevens@us.ibm.com>
diff -ruNp linux-2.6.11.10/include/linux/in6.h
linux-2.6.11.10T2/include/linux/in6.h
--- linux-2.6.11.10/include/linux/in6.h 2005-05-16 10:51:43.000000000
-0700
+++ linux-2.6.11.10T2/include/linux/in6.h 2005-05-23
14:12:59.000000000 -0700
@@ -172,6 +172,7 @@ struct in6_flowlabel_req
#define IPV6_V6ONLY 26
#define IPV6_JOIN_ANYCAST 27
#define IPV6_LEAVE_ANYCAST 28
+#define IPV6_TCLASS 30
/* IPV6_MTU_DISCOVER values */
#define IPV6_PMTUDISC_DONT 0
@@ -184,6 +185,12 @@ struct in6_flowlabel_req
#define IPV6_IPSEC_POLICY 34
#define IPV6_XFRM_POLICY 35
+#define IPV6_RTHDRDSTOPTS 36
+#define IPV6_RECVPKTINFO 37
+#define IPV6_RECVHOPLIMIT 38
+#define IPV6_RECVRTHDR 39
+#define IPV6_RECVHOPOPTS 40
+#define IPV6_RECVDSTOPTS 41
/*
* Multicast:
@@ -198,4 +205,6 @@ struct in6_flowlabel_req
* MCAST_MSFILTER 48
*/
+#define IPV6_RECVTCLASS 49
+
#endif
diff -ruNp linux-2.6.11.10/include/linux/ipv6.h
linux-2.6.11.10T2/include/linux/ipv6.h
--- linux-2.6.11.10/include/linux/ipv6.h 2005-05-16
10:51:43.000000000 -0700
+++ linux-2.6.11.10T2/include/linux/ipv6.h 2005-05-24
13:18:27.000000000 -0700
@@ -221,7 +221,8 @@ struct ipv6_pinfo {
rxhlim:1,
hopopts:1,
dstopts:1,
- rxflow:1;
+ rxflow:1,
+ rxtclass:1;
} bits;
__u8 all;
} rxopt;
@@ -244,6 +245,7 @@ struct ipv6_pinfo {
struct ipv6_txoptions *opt;
struct rt6_info *rt;
int hop_limit;
+ int tclass;
} cork;
};
diff -ruNp linux-2.6.11.10/include/net/ipv6.h
linux-2.6.11.10T2/include/net/ipv6.h
--- linux-2.6.11.10/include/net/ipv6.h 2005-05-16 10:51:49.000000000
-0700
+++ linux-2.6.11.10T2/include/net/ipv6.h 2005-05-24
14:57:23.000000000 -0700
@@ -347,6 +347,7 @@ extern int ip6_append_data(struct
sock
int length,
int transhdrlen,
int hlimit,
+ int tclass,
struct ipv6_txoptions
*opt,
struct flowi *fl,
struct rt6_info *rt,
diff -ruNp linux-2.6.11.10/include/net/transp_v6.h
linux-2.6.11.10T2/include/net/transp_v6.h
--- linux-2.6.11.10/include/net/transp_v6.h 2005-05-16
10:51:51.000000000 -0700
+++ linux-2.6.11.10T2/include/net/transp_v6.h 2005-05-24
14:04:11.000000000 -0700
@@ -37,7 +37,7 @@ extern int datagram_recv_ctl(struct
so
extern int datagram_send_ctl(struct msghdr *msg,
struct flowi *fl,
struct ipv6_txoptions
*opt,
- int *hlimit);
+ int *hlimit, int
*tclass);
#define LOOPBACK4_IPV6 __constant_htonl(0x7f000006)
diff -ruNp linux-2.6.11.10/net/ipv6/datagram.c
linux-2.6.11.10T2/net/ipv6/datagram.c
--- linux-2.6.11.10/net/ipv6/datagram.c 2005-05-16 10:52:00.000000000
-0700
+++ linux-2.6.11.10T2/net/ipv6/datagram.c 2005-05-24
14:03:56.000000000 -0700
@@ -388,6 +388,11 @@ int datagram_recv_ctl(struct sock *sk, s
int hlim = skb->nh.ipv6h->hop_limit;
put_cmsg(msg, SOL_IPV6, IPV6_HOPLIMIT, sizeof(hlim),
&hlim);
}
+ if (np->rxopt.bits.rxtclass) {
+ u8 tclass = (skb->nh.ipv6h->priority << 4) |
+ ((skb->nh.ipv6h->flow_lbl[0]>>4) & 0xf);
+ put_cmsg(msg, SOL_IPV6, IPV6_TCLASS, sizeof(tclass),
&tclass);
+ }
if (np->rxopt.bits.rxflow && (*(u32*)skb->nh.raw &
IPV6_FLOWINFO_MASK)) {
u32 flowinfo = *(u32*)skb->nh.raw & IPV6_FLOWINFO_MASK;
@@ -414,7 +419,7 @@ int datagram_recv_ctl(struct sock *sk, s
int datagram_send_ctl(struct msghdr *msg, struct flowi *fl,
struct ipv6_txoptions *opt,
- int *hlimit)
+ int *hlimit, int *tclass)
{
struct in6_pktinfo *src_info;
struct cmsghdr *cmsg;
@@ -587,6 +592,15 @@ int datagram_send_ctl(struct msghdr *msg
*hlimit = *(int *)CMSG_DATA(cmsg);
break;
+ case IPV6_TCLASS:
+ if (cmsg->cmsg_len != CMSG_LEN(sizeof(int))) {
+ err = -EINVAL;
+ goto exit_f;
+ }
+
+ *tclass = *(int *)CMSG_DATA(cmsg);
+ break;
+
default:
LIMIT_NETDEBUG(
printk(KERN_DEBUG "invalid cmsg type:
%d\n", cmsg->cmsg_type));
diff -ruNp linux-2.6.11.10/net/ipv6/icmp.c
linux-2.6.11.10T2/net/ipv6/icmp.c
--- linux-2.6.11.10/net/ipv6/icmp.c 2005-05-16 10:52:00.000000000
-0700
+++ linux-2.6.11.10T2/net/ipv6/icmp.c 2005-05-24 15:05:14.000000000
-0700
@@ -287,7 +287,7 @@ void icmpv6_send(struct sk_buff *skb, in
int iif = 0;
int addr_type = 0;
int len;
- int hlimit;
+ int hlimit, tclass;
int err = 0;
if ((u8*)hdr < skb->head || (u8*)(hdr+1) > skb->tail)
@@ -381,6 +381,9 @@ void icmpv6_send(struct sk_buff *skb, in
hlimit = np->hop_limit;
if (hlimit < 0)
hlimit = dst_metric(dst, RTAX_HOPLIMIT);
+ tclass = np->cork.tclass;
+ if (tclass < 0)
+ tclass = 0;
msg.skb = skb;
msg.offset = skb->nh.raw - skb->data;
@@ -398,7 +401,7 @@ void icmpv6_send(struct sk_buff *skb, in
err = ip6_append_data(sk, icmpv6_getfrag, &msg,
len + sizeof(struct icmp6hdr),
sizeof(struct icmp6hdr),
- hlimit, NULL, &fl, (struct rt6_info*)dst,
+ hlimit, tclass, NULL, &fl, (struct
rt6_info*)dst,
MSG_DONTWAIT);
if (err) {
ip6_flush_pending_frames(sk);
@@ -432,6 +435,7 @@ static void icmpv6_echo_reply(struct sk_
struct dst_entry *dst;
int err = 0;
int hlimit;
+ int tclass;
saddr = &skb->nh.ipv6h->daddr;
@@ -467,15 +471,18 @@ static void icmpv6_echo_reply(struct sk_
hlimit = np->hop_limit;
if (hlimit < 0)
hlimit = dst_metric(dst, RTAX_HOPLIMIT);
+ tclass = np->cork.tclass;
+ if (tclass < 0)
+ tclass = 0;
idev = in6_dev_get(skb->dev);
msg.skb = skb;
msg.offset = 0;
- err = ip6_append_data(sk, icmpv6_getfrag, &msg, skb->len +
sizeof(struct icmp6hdr),
- sizeof(struct icmp6hdr), hlimit, NULL,
&fl,
- (struct rt6_info*)dst, MSG_DONTWAIT);
+ err = ip6_append_data(sk, icmpv6_getfrag, &msg, skb->len +
+ sizeof(struct icmp6hdr), sizeof(struct icmp6hdr), hlimit,
+ tclass, NULL, &fl, (struct rt6_info*)dst, MSG_DONTWAIT);
if (err) {
ip6_flush_pending_frames(sk);
diff -ruNp linux-2.6.11.10/net/ipv6/ip6_flowlabel.c
linux-2.6.11.10T2/net/ipv6/ip6_flowlabel.c
--- linux-2.6.11.10/net/ipv6/ip6_flowlabel.c 2005-05-16
10:52:00.000000000 -0700
+++ linux-2.6.11.10T2/net/ipv6/ip6_flowlabel.c 2005-05-24
14:04:28.000000000 -0700
@@ -311,7 +311,7 @@ fl_create(struct in6_flowlabel_req *freq
msg.msg_control = (void*)(fl->opt+1);
flowi.oif = 0;
- err = datagram_send_ctl(&msg, &flowi, fl->opt, &junk);
+ err = datagram_send_ctl(&msg, &flowi, fl->opt, &junk,
&junk);
if (err)
goto done;
err = -EINVAL;
diff -ruNp linux-2.6.11.10/net/ipv6/ip6_output.c
linux-2.6.11.10T2/net/ipv6/ip6_output.c
--- linux-2.6.11.10/net/ipv6/ip6_output.c 2005-05-16
10:52:00.000000000 -0700
+++ linux-2.6.11.10T2/net/ipv6/ip6_output.c 2005-05-24
14:58:51.000000000 -0700
@@ -211,7 +211,7 @@ int ip6_xmit(struct sock *sk, struct sk_
struct ipv6hdr *hdr;
u8 proto = fl->proto;
int seg_len = skb->len;
- int hlimit;
+ int hlimit, tclass;
u32 mtu;
if (opt) {
@@ -253,6 +253,13 @@ int ip6_xmit(struct sock *sk, struct sk_
hlimit = np->hop_limit;
if (hlimit < 0)
hlimit = dst_metric(dst, RTAX_HOPLIMIT);
+ tclass = -1;
+ if (np)
+ tclass = np->cork.tclass;
+ if (tclass < 0)
+ tclass = 0;
+ hdr->priority = (np->cork.tclass>>4) &0xf;
+ hdr->flow_lbl[0] |= (np->cork.tclass & 0xf)<<4;
hdr->payload_len = htons(seg_len);
hdr->nexthdr = proto;
@@ -806,10 +813,11 @@ out_err_release:
return err;
}
-int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
int offset, int len, int odd, struct sk_buff *skb),
- void *from, int length, int transhdrlen,
- int hlimit, struct ipv6_txoptions *opt, struct flowi
*fl, struct rt6_info *rt,
- unsigned int flags)
+int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
+ int offset, int len, int odd, struct sk_buff *skb),
+ void *from, int length, int transhdrlen,
+ int hlimit, int tclass, struct ipv6_txoptions *opt, struct flowi
*fl,
+ struct rt6_info *rt, unsigned int flags)
{
struct inet_sock *inet = inet_sk(sk);
struct ipv6_pinfo *np = inet6_sk(sk);
@@ -847,6 +855,7 @@ int ip6_append_data(struct sock *sk, int
np->cork.rt = rt;
inet->cork.fl = *fl;
np->cork.hop_limit = hlimit;
+ np->cork.tclass = tclass;
inet->cork.fragsize = mtu = dst_pmtu(&rt->u.dst);
inet->cork.length = 0;
sk->sk_sndmsg_page = NULL;
@@ -1130,6 +1139,10 @@ int ip6_push_pending_frames(struct sock
*(u32*)hdr = fl->fl6_flowlabel | htonl(0x60000000);
+ /* traffic class */
+ hdr->priority = (np->cork.tclass>>4) & 0xf;
+ hdr->flow_lbl[0] |= (np->cork.tclass & 0xf)<<4;
+
if (skb->len <= sizeof(struct ipv6hdr) + IPV6_MAXPLEN)
hdr->payload_len = htons(skb->len - sizeof(struct
ipv6hdr));
else
diff -ruNp linux-2.6.11.10/net/ipv6/ipv6_sockglue.c
linux-2.6.11.10T2/net/ipv6/ipv6_sockglue.c
--- linux-2.6.11.10/net/ipv6/ipv6_sockglue.c 2005-05-16
10:52:00.000000000 -0700
+++ linux-2.6.11.10T2/net/ipv6/ipv6_sockglue.c 2005-06-06
11:52:15.000000000 -0700
@@ -208,33 +208,38 @@ int ipv6_setsockopt(struct sock *sk, int
retv = 0;
break;
- case IPV6_PKTINFO:
+ case IPV6_RECVPKTINFO:
np->rxopt.bits.rxinfo = valbool;
retv = 0;
break;
- case IPV6_HOPLIMIT:
+ case IPV6_RECVHOPLIMIT:
np->rxopt.bits.rxhlim = valbool;
retv = 0;
break;
- case IPV6_RTHDR:
+ case IPV6_RECVRTHDR:
if (val < 0 || val > 2)
goto e_inval;
np->rxopt.bits.srcrt = val;
retv = 0;
break;
- case IPV6_HOPOPTS:
+ case IPV6_RECVHOPOPTS:
np->rxopt.bits.hopopts = valbool;
retv = 0;
break;
- case IPV6_DSTOPTS:
+ case IPV6_RECVDSTOPTS:
np->rxopt.bits.dstopts = valbool;
retv = 0;
break;
+ case IPV6_RECVTCLASS:
+ np->rxopt.bits.rxtclass = valbool;
+ retv = 0;
+ break;
+
case IPV6_FLOWINFO:
np->rxopt.bits.rxflow = valbool;
retv = 0;
@@ -274,7 +279,7 @@ int ipv6_setsockopt(struct sock *sk, int
msg.msg_controllen = optlen;
msg.msg_control = (void*)(opt+1);
- retv = datagram_send_ctl(&msg, &fl, opt, &junk);
+ retv = datagram_send_ctl(&msg, &fl, opt, &junk, &junk);
if (retv)
goto done;
update:
@@ -620,26 +625,30 @@ int ipv6_getsockopt(struct sock *sk, int
val = np->ipv6only;
break;
- case IPV6_PKTINFO:
+ case IPV6_RECVPKTINFO:
val = np->rxopt.bits.rxinfo;
break;
- case IPV6_HOPLIMIT:
+ case IPV6_RECVHOPLIMIT:
val = np->rxopt.bits.rxhlim;
break;
- case IPV6_RTHDR:
+ case IPV6_RECVRTHDR:
val = np->rxopt.bits.srcrt;
break;
- case IPV6_HOPOPTS:
+ case IPV6_RECVHOPOPTS:
val = np->rxopt.bits.hopopts;
break;
- case IPV6_DSTOPTS:
+ case IPV6_RECVDSTOPTS:
val = np->rxopt.bits.dstopts;
break;
+ case IPV6_RECVTCLASS:
+ val = np->rxopt.bits.rxtclass;
+ break;
+
case IPV6_FLOWINFO:
val = np->rxopt.bits.rxflow;
break;
diff -ruNp linux-2.6.11.10/net/ipv6/raw.c linux-2.6.11.10T2/net/ipv6/raw.c
--- linux-2.6.11.10/net/ipv6/raw.c 2005-05-16 10:52:00.000000000
-0700
+++ linux-2.6.11.10T2/net/ipv6/raw.c 2005-05-24 15:09:42.000000000
-0700
@@ -617,6 +617,7 @@ static int rawv6_sendmsg(struct kiocb *i
struct flowi fl;
int addr_len = msg->msg_namelen;
int hlimit = -1;
+ int tclass = -1;
u16 proto;
int err;
@@ -702,7 +703,7 @@ static int rawv6_sendmsg(struct kiocb *i
memset(opt, 0, sizeof(struct ipv6_txoptions));
opt->tot_len = sizeof(struct ipv6_txoptions);
- err = datagram_send_ctl(msg, &fl, opt, &hlimit);
+ err = datagram_send_ctl(msg, &fl, opt, &hlimit, &tclass);
if (err < 0) {
fl6_sock_release(flowlabel);
return err;
@@ -758,6 +759,12 @@ static int rawv6_sendmsg(struct kiocb *i
hlimit = dst_metric(dst, RTAX_HOPLIMIT);
}
+ if (tclass < 0) {
+ tclass = np->cork.tclass;
+ if (tclass < 0)
+ tclass = 0;
+ }
+
if (msg->msg_flags&MSG_CONFIRM)
goto do_confirm;
@@ -766,8 +773,9 @@ back_from_confirm:
err = rawv6_send_hdrinc(sk, msg->msg_iov, len, &fl,
(struct rt6_info*)dst, msg->msg_flags);
} else {
lock_sock(sk);
- err = ip6_append_data(sk, ip_generic_getfrag,
msg->msg_iov, len, 0,
- hlimit, opt, &fl, (struct
rt6_info*)dst, msg->msg_flags);
+ err = ip6_append_data(sk, ip_generic_getfrag,
msg->msg_iov,
+ len, 0, hlimit, tclass, opt, &fl, (struct
rt6_info*)dst,
+ msg->msg_flags);
if (err)
ip6_flush_pending_frames(sk);
diff -ruNp linux-2.6.11.10/net/ipv6/udp.c linux-2.6.11.10T2/net/ipv6/udp.c
--- linux-2.6.11.10/net/ipv6/udp.c 2005-05-16 10:52:00.000000000
-0700
+++ linux-2.6.11.10T2/net/ipv6/udp.c 2005-05-24 15:11:58.000000000
-0700
@@ -637,6 +637,7 @@ static int udpv6_sendmsg(struct kiocb *i
int addr_len = msg->msg_namelen;
int ulen = len;
int hlimit = -1;
+ int tclass = -1;
int corkreq = up->corkflag || msg->msg_flags&MSG_MORE;
int err;
@@ -758,7 +759,7 @@ do_udp_sendmsg:
memset(opt, 0, sizeof(struct ipv6_txoptions));
opt->tot_len = sizeof(*opt);
- err = datagram_send_ctl(msg, fl, opt, &hlimit);
+ err = datagram_send_ctl(msg, fl, opt, &hlimit, &tclass);
if (err < 0) {
fl6_sock_release(flowlabel);
return err;
@@ -812,6 +813,11 @@ do_udp_sendmsg:
if (hlimit < 0)
hlimit = dst_metric(dst, RTAX_HOPLIMIT);
}
+ if (tclass < 0) {
+ tclass = np->cork.tclass;
+ if (tclass < 0)
+ tclass = 0;
+ }
if (msg->msg_flags&MSG_CONFIRM)
goto do_confirm;
@@ -832,9 +838,10 @@ back_from_confirm:
do_append_data:
up->len += ulen;
- err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov, ulen,
sizeof(struct udphdr),
- hlimit, opt, fl, (struct rt6_info*)dst,
- corkreq ? msg->msg_flags|MSG_MORE :
msg->msg_flags);
+ err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov, ulen,
+ sizeof(struct udphdr), hlimit, tclass, opt, fl,
+ (struct rt6_info*)dst,
+ corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags);
if (err)
udp_v6_flush_pending_frames(sk);
else if (!corkreq)
[-- Attachment #2: rfc3542.patch --]
[-- Type: application/octet-stream, Size: 13675 bytes --]
diff -ruNp linux-2.6.11.10/include/linux/in6.h linux-2.6.11.10T2/include/linux/in6.h
--- linux-2.6.11.10/include/linux/in6.h 2005-05-16 10:51:43.000000000 -0700
+++ linux-2.6.11.10T2/include/linux/in6.h 2005-05-23 14:12:59.000000000 -0700
@@ -172,6 +172,7 @@ struct in6_flowlabel_req
#define IPV6_V6ONLY 26
#define IPV6_JOIN_ANYCAST 27
#define IPV6_LEAVE_ANYCAST 28
+#define IPV6_TCLASS 30
/* IPV6_MTU_DISCOVER values */
#define IPV6_PMTUDISC_DONT 0
@@ -184,6 +185,12 @@ struct in6_flowlabel_req
#define IPV6_IPSEC_POLICY 34
#define IPV6_XFRM_POLICY 35
+#define IPV6_RTHDRDSTOPTS 36
+#define IPV6_RECVPKTINFO 37
+#define IPV6_RECVHOPLIMIT 38
+#define IPV6_RECVRTHDR 39
+#define IPV6_RECVHOPOPTS 40
+#define IPV6_RECVDSTOPTS 41
/*
* Multicast:
@@ -198,4 +205,6 @@ struct in6_flowlabel_req
* MCAST_MSFILTER 48
*/
+#define IPV6_RECVTCLASS 49
+
#endif
diff -ruNp linux-2.6.11.10/include/linux/ipv6.h linux-2.6.11.10T2/include/linux/ipv6.h
--- linux-2.6.11.10/include/linux/ipv6.h 2005-05-16 10:51:43.000000000 -0700
+++ linux-2.6.11.10T2/include/linux/ipv6.h 2005-05-24 13:18:27.000000000 -0700
@@ -221,7 +221,8 @@ struct ipv6_pinfo {
rxhlim:1,
hopopts:1,
dstopts:1,
- rxflow:1;
+ rxflow:1,
+ rxtclass:1;
} bits;
__u8 all;
} rxopt;
@@ -244,6 +245,7 @@ struct ipv6_pinfo {
struct ipv6_txoptions *opt;
struct rt6_info *rt;
int hop_limit;
+ int tclass;
} cork;
};
diff -ruNp linux-2.6.11.10/include/net/ipv6.h linux-2.6.11.10T2/include/net/ipv6.h
--- linux-2.6.11.10/include/net/ipv6.h 2005-05-16 10:51:49.000000000 -0700
+++ linux-2.6.11.10T2/include/net/ipv6.h 2005-05-24 14:57:23.000000000 -0700
@@ -347,6 +347,7 @@ extern int ip6_append_data(struct sock
int length,
int transhdrlen,
int hlimit,
+ int tclass,
struct ipv6_txoptions *opt,
struct flowi *fl,
struct rt6_info *rt,
diff -ruNp linux-2.6.11.10/include/net/transp_v6.h linux-2.6.11.10T2/include/net/transp_v6.h
--- linux-2.6.11.10/include/net/transp_v6.h 2005-05-16 10:51:51.000000000 -0700
+++ linux-2.6.11.10T2/include/net/transp_v6.h 2005-05-24 14:04:11.000000000 -0700
@@ -37,7 +37,7 @@ extern int datagram_recv_ctl(struct so
extern int datagram_send_ctl(struct msghdr *msg,
struct flowi *fl,
struct ipv6_txoptions *opt,
- int *hlimit);
+ int *hlimit, int *tclass);
#define LOOPBACK4_IPV6 __constant_htonl(0x7f000006)
diff -ruNp linux-2.6.11.10/net/ipv6/datagram.c linux-2.6.11.10T2/net/ipv6/datagram.c
--- linux-2.6.11.10/net/ipv6/datagram.c 2005-05-16 10:52:00.000000000 -0700
+++ linux-2.6.11.10T2/net/ipv6/datagram.c 2005-05-24 14:03:56.000000000 -0700
@@ -388,6 +388,11 @@ int datagram_recv_ctl(struct sock *sk, s
int hlim = skb->nh.ipv6h->hop_limit;
put_cmsg(msg, SOL_IPV6, IPV6_HOPLIMIT, sizeof(hlim), &hlim);
}
+ if (np->rxopt.bits.rxtclass) {
+ u8 tclass = (skb->nh.ipv6h->priority << 4) |
+ ((skb->nh.ipv6h->flow_lbl[0]>>4) & 0xf);
+ put_cmsg(msg, SOL_IPV6, IPV6_TCLASS, sizeof(tclass), &tclass);
+ }
if (np->rxopt.bits.rxflow && (*(u32*)skb->nh.raw & IPV6_FLOWINFO_MASK)) {
u32 flowinfo = *(u32*)skb->nh.raw & IPV6_FLOWINFO_MASK;
@@ -414,7 +419,7 @@ int datagram_recv_ctl(struct sock *sk, s
int datagram_send_ctl(struct msghdr *msg, struct flowi *fl,
struct ipv6_txoptions *opt,
- int *hlimit)
+ int *hlimit, int *tclass)
{
struct in6_pktinfo *src_info;
struct cmsghdr *cmsg;
@@ -587,6 +592,15 @@ int datagram_send_ctl(struct msghdr *msg
*hlimit = *(int *)CMSG_DATA(cmsg);
break;
+ case IPV6_TCLASS:
+ if (cmsg->cmsg_len != CMSG_LEN(sizeof(int))) {
+ err = -EINVAL;
+ goto exit_f;
+ }
+
+ *tclass = *(int *)CMSG_DATA(cmsg);
+ break;
+
default:
LIMIT_NETDEBUG(
printk(KERN_DEBUG "invalid cmsg type: %d\n", cmsg->cmsg_type));
diff -ruNp linux-2.6.11.10/net/ipv6/icmp.c linux-2.6.11.10T2/net/ipv6/icmp.c
--- linux-2.6.11.10/net/ipv6/icmp.c 2005-05-16 10:52:00.000000000 -0700
+++ linux-2.6.11.10T2/net/ipv6/icmp.c 2005-05-24 15:05:14.000000000 -0700
@@ -287,7 +287,7 @@ void icmpv6_send(struct sk_buff *skb, in
int iif = 0;
int addr_type = 0;
int len;
- int hlimit;
+ int hlimit, tclass;
int err = 0;
if ((u8*)hdr < skb->head || (u8*)(hdr+1) > skb->tail)
@@ -381,6 +381,9 @@ void icmpv6_send(struct sk_buff *skb, in
hlimit = np->hop_limit;
if (hlimit < 0)
hlimit = dst_metric(dst, RTAX_HOPLIMIT);
+ tclass = np->cork.tclass;
+ if (tclass < 0)
+ tclass = 0;
msg.skb = skb;
msg.offset = skb->nh.raw - skb->data;
@@ -398,7 +401,7 @@ void icmpv6_send(struct sk_buff *skb, in
err = ip6_append_data(sk, icmpv6_getfrag, &msg,
len + sizeof(struct icmp6hdr),
sizeof(struct icmp6hdr),
- hlimit, NULL, &fl, (struct rt6_info*)dst,
+ hlimit, tclass, NULL, &fl, (struct rt6_info*)dst,
MSG_DONTWAIT);
if (err) {
ip6_flush_pending_frames(sk);
@@ -432,6 +435,7 @@ static void icmpv6_echo_reply(struct sk_
struct dst_entry *dst;
int err = 0;
int hlimit;
+ int tclass;
saddr = &skb->nh.ipv6h->daddr;
@@ -467,15 +471,18 @@ static void icmpv6_echo_reply(struct sk_
hlimit = np->hop_limit;
if (hlimit < 0)
hlimit = dst_metric(dst, RTAX_HOPLIMIT);
+ tclass = np->cork.tclass;
+ if (tclass < 0)
+ tclass = 0;
idev = in6_dev_get(skb->dev);
msg.skb = skb;
msg.offset = 0;
- err = ip6_append_data(sk, icmpv6_getfrag, &msg, skb->len + sizeof(struct icmp6hdr),
- sizeof(struct icmp6hdr), hlimit, NULL, &fl,
- (struct rt6_info*)dst, MSG_DONTWAIT);
+ err = ip6_append_data(sk, icmpv6_getfrag, &msg, skb->len +
+ sizeof(struct icmp6hdr), sizeof(struct icmp6hdr), hlimit,
+ tclass, NULL, &fl, (struct rt6_info*)dst, MSG_DONTWAIT);
if (err) {
ip6_flush_pending_frames(sk);
diff -ruNp linux-2.6.11.10/net/ipv6/ip6_flowlabel.c linux-2.6.11.10T2/net/ipv6/ip6_flowlabel.c
--- linux-2.6.11.10/net/ipv6/ip6_flowlabel.c 2005-05-16 10:52:00.000000000 -0700
+++ linux-2.6.11.10T2/net/ipv6/ip6_flowlabel.c 2005-05-24 14:04:28.000000000 -0700
@@ -311,7 +311,7 @@ fl_create(struct in6_flowlabel_req *freq
msg.msg_control = (void*)(fl->opt+1);
flowi.oif = 0;
- err = datagram_send_ctl(&msg, &flowi, fl->opt, &junk);
+ err = datagram_send_ctl(&msg, &flowi, fl->opt, &junk, &junk);
if (err)
goto done;
err = -EINVAL;
diff -ruNp linux-2.6.11.10/net/ipv6/ip6_output.c linux-2.6.11.10T2/net/ipv6/ip6_output.c
--- linux-2.6.11.10/net/ipv6/ip6_output.c 2005-05-16 10:52:00.000000000 -0700
+++ linux-2.6.11.10T2/net/ipv6/ip6_output.c 2005-05-24 14:58:51.000000000 -0700
@@ -211,7 +211,7 @@ int ip6_xmit(struct sock *sk, struct sk_
struct ipv6hdr *hdr;
u8 proto = fl->proto;
int seg_len = skb->len;
- int hlimit;
+ int hlimit, tclass;
u32 mtu;
if (opt) {
@@ -253,6 +253,13 @@ int ip6_xmit(struct sock *sk, struct sk_
hlimit = np->hop_limit;
if (hlimit < 0)
hlimit = dst_metric(dst, RTAX_HOPLIMIT);
+ tclass = -1;
+ if (np)
+ tclass = np->cork.tclass;
+ if (tclass < 0)
+ tclass = 0;
+ hdr->priority = (np->cork.tclass>>4) &0xf;
+ hdr->flow_lbl[0] |= (np->cork.tclass & 0xf)<<4;
hdr->payload_len = htons(seg_len);
hdr->nexthdr = proto;
@@ -806,10 +813,11 @@ out_err_release:
return err;
}
-int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb),
- void *from, int length, int transhdrlen,
- int hlimit, struct ipv6_txoptions *opt, struct flowi *fl, struct rt6_info *rt,
- unsigned int flags)
+int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
+ int offset, int len, int odd, struct sk_buff *skb),
+ void *from, int length, int transhdrlen,
+ int hlimit, int tclass, struct ipv6_txoptions *opt, struct flowi *fl,
+ struct rt6_info *rt, unsigned int flags)
{
struct inet_sock *inet = inet_sk(sk);
struct ipv6_pinfo *np = inet6_sk(sk);
@@ -847,6 +855,7 @@ int ip6_append_data(struct sock *sk, int
np->cork.rt = rt;
inet->cork.fl = *fl;
np->cork.hop_limit = hlimit;
+ np->cork.tclass = tclass;
inet->cork.fragsize = mtu = dst_pmtu(&rt->u.dst);
inet->cork.length = 0;
sk->sk_sndmsg_page = NULL;
@@ -1130,6 +1139,10 @@ int ip6_push_pending_frames(struct sock
*(u32*)hdr = fl->fl6_flowlabel | htonl(0x60000000);
+ /* traffic class */
+ hdr->priority = (np->cork.tclass>>4) & 0xf;
+ hdr->flow_lbl[0] |= (np->cork.tclass & 0xf)<<4;
+
if (skb->len <= sizeof(struct ipv6hdr) + IPV6_MAXPLEN)
hdr->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
else
diff -ruNp linux-2.6.11.10/net/ipv6/ipv6_sockglue.c linux-2.6.11.10T2/net/ipv6/ipv6_sockglue.c
--- linux-2.6.11.10/net/ipv6/ipv6_sockglue.c 2005-05-16 10:52:00.000000000 -0700
+++ linux-2.6.11.10T2/net/ipv6/ipv6_sockglue.c 2005-06-06 11:52:15.000000000 -0700
@@ -208,33 +208,38 @@ int ipv6_setsockopt(struct sock *sk, int
retv = 0;
break;
- case IPV6_PKTINFO:
+ case IPV6_RECVPKTINFO:
np->rxopt.bits.rxinfo = valbool;
retv = 0;
break;
- case IPV6_HOPLIMIT:
+ case IPV6_RECVHOPLIMIT:
np->rxopt.bits.rxhlim = valbool;
retv = 0;
break;
- case IPV6_RTHDR:
+ case IPV6_RECVRTHDR:
if (val < 0 || val > 2)
goto e_inval;
np->rxopt.bits.srcrt = val;
retv = 0;
break;
- case IPV6_HOPOPTS:
+ case IPV6_RECVHOPOPTS:
np->rxopt.bits.hopopts = valbool;
retv = 0;
break;
- case IPV6_DSTOPTS:
+ case IPV6_RECVDSTOPTS:
np->rxopt.bits.dstopts = valbool;
retv = 0;
break;
+ case IPV6_RECVTCLASS:
+ np->rxopt.bits.rxtclass = valbool;
+ retv = 0;
+ break;
+
case IPV6_FLOWINFO:
np->rxopt.bits.rxflow = valbool;
retv = 0;
@@ -274,7 +279,7 @@ int ipv6_setsockopt(struct sock *sk, int
msg.msg_controllen = optlen;
msg.msg_control = (void*)(opt+1);
- retv = datagram_send_ctl(&msg, &fl, opt, &junk);
+ retv = datagram_send_ctl(&msg, &fl, opt, &junk, &junk);
if (retv)
goto done;
update:
@@ -620,26 +625,30 @@ int ipv6_getsockopt(struct sock *sk, int
val = np->ipv6only;
break;
- case IPV6_PKTINFO:
+ case IPV6_RECVPKTINFO:
val = np->rxopt.bits.rxinfo;
break;
- case IPV6_HOPLIMIT:
+ case IPV6_RECVHOPLIMIT:
val = np->rxopt.bits.rxhlim;
break;
- case IPV6_RTHDR:
+ case IPV6_RECVRTHDR:
val = np->rxopt.bits.srcrt;
break;
- case IPV6_HOPOPTS:
+ case IPV6_RECVHOPOPTS:
val = np->rxopt.bits.hopopts;
break;
- case IPV6_DSTOPTS:
+ case IPV6_RECVDSTOPTS:
val = np->rxopt.bits.dstopts;
break;
+ case IPV6_RECVTCLASS:
+ val = np->rxopt.bits.rxtclass;
+ break;
+
case IPV6_FLOWINFO:
val = np->rxopt.bits.rxflow;
break;
diff -ruNp linux-2.6.11.10/net/ipv6/raw.c linux-2.6.11.10T2/net/ipv6/raw.c
--- linux-2.6.11.10/net/ipv6/raw.c 2005-05-16 10:52:00.000000000 -0700
+++ linux-2.6.11.10T2/net/ipv6/raw.c 2005-05-24 15:09:42.000000000 -0700
@@ -617,6 +617,7 @@ static int rawv6_sendmsg(struct kiocb *i
struct flowi fl;
int addr_len = msg->msg_namelen;
int hlimit = -1;
+ int tclass = -1;
u16 proto;
int err;
@@ -702,7 +703,7 @@ static int rawv6_sendmsg(struct kiocb *i
memset(opt, 0, sizeof(struct ipv6_txoptions));
opt->tot_len = sizeof(struct ipv6_txoptions);
- err = datagram_send_ctl(msg, &fl, opt, &hlimit);
+ err = datagram_send_ctl(msg, &fl, opt, &hlimit, &tclass);
if (err < 0) {
fl6_sock_release(flowlabel);
return err;
@@ -758,6 +759,12 @@ static int rawv6_sendmsg(struct kiocb *i
hlimit = dst_metric(dst, RTAX_HOPLIMIT);
}
+ if (tclass < 0) {
+ tclass = np->cork.tclass;
+ if (tclass < 0)
+ tclass = 0;
+ }
+
if (msg->msg_flags&MSG_CONFIRM)
goto do_confirm;
@@ -766,8 +773,9 @@ back_from_confirm:
err = rawv6_send_hdrinc(sk, msg->msg_iov, len, &fl, (struct rt6_info*)dst, msg->msg_flags);
} else {
lock_sock(sk);
- err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov, len, 0,
- hlimit, opt, &fl, (struct rt6_info*)dst, msg->msg_flags);
+ err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov,
+ len, 0, hlimit, tclass, opt, &fl, (struct rt6_info*)dst,
+ msg->msg_flags);
if (err)
ip6_flush_pending_frames(sk);
diff -ruNp linux-2.6.11.10/net/ipv6/udp.c linux-2.6.11.10T2/net/ipv6/udp.c
--- linux-2.6.11.10/net/ipv6/udp.c 2005-05-16 10:52:00.000000000 -0700
+++ linux-2.6.11.10T2/net/ipv6/udp.c 2005-05-24 15:11:58.000000000 -0700
@@ -637,6 +637,7 @@ static int udpv6_sendmsg(struct kiocb *i
int addr_len = msg->msg_namelen;
int ulen = len;
int hlimit = -1;
+ int tclass = -1;
int corkreq = up->corkflag || msg->msg_flags&MSG_MORE;
int err;
@@ -758,7 +759,7 @@ do_udp_sendmsg:
memset(opt, 0, sizeof(struct ipv6_txoptions));
opt->tot_len = sizeof(*opt);
- err = datagram_send_ctl(msg, fl, opt, &hlimit);
+ err = datagram_send_ctl(msg, fl, opt, &hlimit, &tclass);
if (err < 0) {
fl6_sock_release(flowlabel);
return err;
@@ -812,6 +813,11 @@ do_udp_sendmsg:
if (hlimit < 0)
hlimit = dst_metric(dst, RTAX_HOPLIMIT);
}
+ if (tclass < 0) {
+ tclass = np->cork.tclass;
+ if (tclass < 0)
+ tclass = 0;
+ }
if (msg->msg_flags&MSG_CONFIRM)
goto do_confirm;
@@ -832,9 +838,10 @@ back_from_confirm:
do_append_data:
up->len += ulen;
- err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov, ulen, sizeof(struct udphdr),
- hlimit, opt, fl, (struct rt6_info*)dst,
- corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags);
+ err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov, ulen,
+ sizeof(struct udphdr), hlimit, tclass, opt, fl,
+ (struct rt6_info*)dst,
+ corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags);
if (err)
udp_v6_flush_pending_frames(sk);
else if (!corkreq)
^ permalink raw reply
* Re: RFC: NAPI packet weighting patch
From: David S. Miller @ 2005-06-06 19:47 UTC (permalink / raw)
To: john.ronciak
Cc: mchan, hadi, buytenh, mitch.a.williams, jdmason, shemminger,
netdev, Robert.Olsson, ganesh.venkatesan, jesse.brandeburg
In-Reply-To: <468F3FDA28AA87429AD807992E22D07E0450C002@orsmsx408>
From: "Ronciak, John" <john.ronciak@intel.com>
Date: Mon, 6 Jun 2005 08:35:26 -0700
> We are dropping packets at the HW level (FIFO errors) with 256
> descriptors and the default weight of 64. As we said reducing the
> weight eliminates this which is understandable since the driver is being
> serviced more fequently. We also hacked the driver to do a buffer
> allocation per packet sent up the stack. This reduced the number of
> dropped pacekts by about 80% but it was still a significant number of
> drops (190K to 39K dropped). So I don't think this is where the problem
> is. This is also comfimed with the tg3 driver doing the buffer update
> to the HW every 25 descriptors.
I reach a different conclusion, sorry. :-)
Here is the invariant:
If you force the e1000 driver to do RX replenishment every N
packets it should reduce the packet drops the same (in the
single NIC case) as if you reduced the dev->weight to that
same value N.
You have two test cases, single NIC and multi-NIC, so you should
be very clear in which case your drop number applies to. They
are two totally different problems.
> We did not up the descriptor ring size with the default weight but will
> try this today and report back.
Thanks for all of your test data and hard work so far.
It's very valuable.
^ permalink raw reply
* [PATCH] tg3: Fix link failure in 5701
From: Michael Chan @ 2005-06-06 19:42 UTC (permalink / raw)
To: davem; +Cc: iod00d, peterc, netdev
On some 5701 devices with older bootcode, the LED configuration bits in
SRAM may be invalid with value zero. The fix is to check for invalid
bits (0) and default to PHY 1 mode. Incorrect LED mode will lead to
error in programming the PHY.
Thanks to Grant Grundler for debugging the problem.
>From Grant:
| In May, 2004, tg3 v3.4 changed how MAC_LED_CTRL (0x40c) was getting
| programmed and how to determine what to program into LED_CTRL. The new
| code trusted NIC_SRAM_DATA_CFG (0x00000b58) to indicate what to write
| to LED_CTRL and MII EXT_CTRL registers. On "IOX Core Lan", SRAM was
| saying MODE_MAC (0x0) and that doesn't work.
Signed-off-by: Michael Chan <mchan@broadcom.com>
diff -Nru led1/drivers/net/tg3.c led2/drivers/net/tg3.c
--- led1/drivers/net/tg3.c 2005-06-06 10:19:56.692541944 -0700
+++ led2/drivers/net/tg3.c 2005-06-06 10:34:49.251852304 -0700
@@ -8555,6 +8555,16 @@
case NIC_SRAM_DATA_CFG_LED_MODE_MAC:
tp->led_ctrl = LED_CTRL_MODE_MAC;
+
+ /* Default to PHY_1_MODE if 0 (MAC_MODE) is
+ * read on some older 5700/5701 bootcode.
+ */
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) ==
+ ASIC_REV_5700 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) ==
+ ASIC_REV_5701)
+ tp->led_ctrl = LED_CTRL_MODE_PHY_1;
+
break;
case SHASTA_EXT_LED_SHARED:
^ permalink raw reply
* Re: [Linux Diffserv] GRED queueing discipline and the file sch_gred.c
From: rahul hari @ 2005-06-06 19:12 UTC (permalink / raw)
To: tgraf, hadi; +Cc: diffserv-general, netdev
In-Reply-To: <20050606121527.GE15391@postel.suug.ch>
Thanks for all the suggestions Jamal and Thomas.
>From what you people have been suggesting, i feel that i should be
giving a detailed explaination of the problem I am currently working on.
I have divided all the traffic on a network into 5 categories : Real
time video (UDP1),Real time audio (UDP2), TCP not requiring any QoS
(TCP1), TCP requiring QoS but with the size of the entire transaction
very low(TCP2), and TCP requiring QoS with the size of the transaction
in several MBs (TCP3).
Now I am putting UDP1 and TCP1 in one particular queue (say q1) and
giving priority to UDP1 (for dequeuing not caring if TCP1 is getting
starved). I am putting UDP2 ,TCP2 and TCP3 in a different queue (thus
keeping the average queue length almost constant) (say q2)and applying
RED on each of TCP2 and TCP3 (the application of the two REDs being
independent of each other). Here also I am providing priority to UDP2
(without caring if TCP2 or TCP3 is getting starved ).
To schedule between q1 and q2, I am using WRR and to schedule between
UDP1 and TCP1, I am using prio. For implementing q2, I am currently
putting UDP2,TCP2 and TCP3 in 3 different virtual queues and applying
GRED with grio. I am providing UDP2 the highest priority and providing
TCP2 and TCP3 equal priorities. To ensure that RED does not apply on
the UDP2, I have set Tmax=Tmin so that Pbmax=1. But the results I am
getting with this configuration do not match with the results that I
have got from the simulations.
So I want to implement this stuff such that the UDP2 gets highest
priority among the three, is not included while calculating the total
average queue length and the qave used for the application of REDs on
TCP2 and TCP3 should be equal to the qave of tcp2+ qave of tcp3.
To schedule between TCP2 and TCP3, I want to use WRR or something that
gives equal priority and prevents the starvation of any of these.
PS: please send any further replies to rahul.hari@cse06.itbhu.org instead of
this account
Regards,
Rahul
-------
"The fear you let build up in your mind is worse than the situation that
actually exists"
taken from "who moved my cheese"
-----------------------------------------------------------------------------
Rahul Hari
Senior Undergraduate Student,
Department of CSE,
ITBHU,
Varanasi.
Ph: +91-9845347020
-----------------------------------------------------------------------------
>
>* jamal <1118058859.6266.126.camel@localhost.localdomain> 2005-06-06 07:54
> > On Mon, 2005-06-06 at 13:39 +0200, Thomas Graf wrote:
> >
> > > Use a prio qdisc with RED leaf qdiscs. RED and GREDs purpose is to
> > > calculate a marking probability and not to provide any prioritizing
> > > schemes.
> >
> > Prioritization is still implicitly provided if you vary the queue
> > lengths or the drop probabilities.
> > For example, if you set everything to be exactly the same, and varied
> > only the drop probability - the VQ with the highest drop probability
> > will be less important (i.e relatively more of its packets will be
> > dropped; recall: the drop decision is made before the packet is queued).
>
>Absolutely, what I meant is that GRED does not take influence on the
>actual ordering of packets not dropped. The priority together with
>the qavg parameters and the thresholds only have influence on the
>probability a packet gets marked/dropped, sure this is prioritization
>as well but Rahul wanted to have one VQ strave out another VQ
>completely. My point is that this is not possible with GRED.
_________________________________________________________________
Think Rani is the best? http://server1.msn.co.in/sp05/iifa/ Make sure she
wins the award.
^ permalink raw reply
* OT: Survey facing design patterns and communication
From: Nico @ 2005-06-06 19:10 UTC (permalink / raw)
To: netdev
Hello everybody!
We are a group of students at "Freie Universitaet Berlin".
As part of our computer science studies we are going to do
a survey facing the use of design patterns in communication.
Examples of design patterns are "Abstract Factory",
"Singleton", "Composite", "Iterator" and "Listener".
If you know what we are talking about, you are welcome to
take part in our survey.
It takes about 5 minutes to fill out the form.
Just jump to:
http://study.beatdepot.de
If you agree, we will send you the results of our survey.
Thanks in advance for your participation!
And sorry for the interruption of your discussion.
^ permalink raw reply
* New address announcements in RTMGRP_IPV4_IFADDR netlink group
From: Teemu Koponen @ 2005-06-06 18:59 UTC (permalink / raw)
To: netdev
Netlink developers and gurus,
While fine-tuning the handover speed for a certain L3 mobility daemon
under Linux 2.6.11.10, I stumbled into the following behavior which
intuitively does not follow the semantics of the RTMGRP_IPV4_IFADDR
group:
0) A userspace daemon process is running and listening to the broadcast
group.
1) Address is inserted to an interface (ip addr add ... at shell).
2) The daemon receives a NEWADDR message, just as is should, but the
daemon is unable to bind to the address *immediately* (actually in the
function that processes the netlink message). The result is "cannot
assign an address" from the bind call. However, if I do insert a single
nanosleep, even with an arbitrary low sleep value, before the bind
call, the bind then succeeds.
So, what is the semantics of NEWADDR? Should the address be bindable
right after receiving the message? Or is there a race-condition between
userspace and kernel that the inserted sleep helps to overcome by
letting the kernel to run again before the bind call?
TIA,
Teemu
--
^ permalink raw reply
* Re: Automated linux kernel testing results
From: Nivedita Singhvi @ 2005-06-06 18:30 UTC (permalink / raw)
To: Jonathan Day; +Cc: netdev
In-Reply-To: <20050604050123.9897.qmail@web31504.mail.mud.yahoo.com>
Jonathan Day wrote:
> What I have not (yet) seen is any work on relating the
> results. Is a bug in the design? The implementation?
> Some combination thereof? Is something correctly
> written but not functioning because something it
> depends on isn't working correctly?
Currently, you can get some idea (kernel didn't
build, machine couldn't reboot, or if the system
crashes during the tests, crash info etc. Looking
into whether the cause is a design bug or an
implementation bug is likely beyond automation.
> It would even be useful if we could cross-reference
> some of the benchmarks with the Linux graphing
> project, so that we could see how the complexity of
I believe they do (ping Martin for details) have some
plans to graph stuff, and possibly info could be sucked
out of the data/results provided to feed other people's
needs.
> Test suites are necessary. Test suites are great.
> Anyone working on a test suite deserves many kudos and
> much praise. Test suites that are relatable enough
> that you can see the same problem from different
> angles -- those are worth their printout weight in
> gold.
Yeah. :).
thanks,
Nivedita
^ permalink raw reply
* Re: [Linux Diffserv] GRED queueing discipline and the filesch_gred.c
From: Thomas Graf @ 2005-06-06 18:28 UTC (permalink / raw)
To: rahul.hari; +Cc: hadi, diffserv-general, netdev
In-Reply-To: <4532f31705060610486ef106a1@mail.gmail.com>
* Rahul Hari <4532f31705060610486ef106a1@mail.gmail.com> 2005-06-06 23:18
> UDP1 and TCP1, I am using prio. For implementing q2, I am currently
> putting UDP2,TCP2 and TCP3 in 3 different virtual queues and applying
> GRED with grio. I am providing UDP2 the highest priority and providing
> TCP2 and TCP3 equal priorities. To ensure that RED does not apply on
> the UDP2, I have set Tmax=Tmin so that Pbmax=1. But the results I am
> getting with this configuration do not match with the results that I
> have got from the simulations.
I assume Tmax being qth_max so you basically disable probability drops
which is the main point of RED. What you do is about equal as a simple
FIFO with hard queue limit comparing against a EWMA based queue length.
Depending on whether you want UDP2 to starve out the others use either
prio or cbq/htb and a GRED in rio mode with equal vq prios for TCP2 and
TCP3. The drops should be roughly proportional to their bandwidth share
but I'm not sure if this is fair enough for you.
^ permalink raw reply
* Re: Kernel 2.4.31 - netdriver r8169
From: Francois Romieu @ 2005-06-06 18:08 UTC (permalink / raw)
To: Wolfgang Empacher; +Cc: linux-kernel, netdev
In-Reply-To: <s2a42909.094@mail.vkmb.at>
Wolfgang Empacher <w.empacher@vkmb.at> :
[...]
> in kernel 2.4.31 there is version 1.2 of r8169 driver in use. this version
> doesn't work well (RESETS of the device many and all the times). using
> version 1.6 of this driver performs smooth and well.
Where did you get your 1.6 version from ?
(netdev added to Cc: as per the r8169 entry in the MAINTAINERS file)
--
Ueimor
^ permalink raw reply
* Re: [Linux Diffserv] GRED queueing discipline and the filesch_gred.c
From: Rahul Hari @ 2005-06-06 17:48 UTC (permalink / raw)
To: hadi, tgraf; +Cc: diffserv-general, netdev
Thanks for all the suggestions Jamal and Thomas.
>From what you people have been suggesting, i feel that i should be
giving a brief explaination of the problem I am currently working on.
I have divided all the traffic on a network into 5 categories : Real
time video (UDP1),Real time audio (UDP2), TCP not requiring any QoS
(TCP1), TCP requiring QoS but with the size of the entire transaction
very low(TCP2), and TCP requiring QoS with the size of the transaction
in several MBs (TCP3).
Now I am putting UDP1 and TCP1 in one particular queue (say q1) and
giving priority to UDP1 (for dequeuing not caring if TCP1 is getting
starved). I am putting UDP2 ,TCP2 and TCP3 in a different queue (thus
keeping the average queue length almost constant) (say q2)and applying
RED on each of TCP2 and TCP3 (the application of the two REDs being
independent of each other). Here also I am providing priority to UDP2
(without caring if TCP2 or TCP3 is getting starved ).
To schedule between q1 and q2, I am using WRR and to schedule between
UDP1 and TCP1, I am using prio. For implementing q2, I am currently
putting UDP2,TCP2 and TCP3 in 3 different virtual queues and applying
GRED with grio. I am providing UDP2 the highest priority and providing
TCP2 and TCP3 equal priorities. To ensure that RED does not apply on
the UDP2, I have set Tmax=Tmin so that Pbmax=1. But the results I am
getting with this configuration do not match with the results that I
have got from the simulations.
So I want to implement this stuff such that the UDP2 gets highest
priority among the three, is not included while calculating the total
average queue length and the qave used for the application of REDs on
TCP2 and TCP3 should be equal to the qave of tcp2+ qave of tcp3.
To schedule between TCP2 and TCP3, I want to use WRR or something that
gives equal priority and prevents the starvation of any of these.
Regards,
Rahul
--
----------------------
"The fear you let build up in your mind is worse than the situation
that actually exists"
from "who moved my cheese"
---------------------------------------------------------------------------------
Rahul Hari
Senior Under Grad. Student,
Department of CSE,
ITBHU,
Varanasi.
Ph: +91-9845347020
rahul.hari@cse06.itbhu.org
------------------------------------------------------------------------------------------
>
>On Mon, 2005-06-06 at 13:39 +0200, Thomas Graf wrote:
>
> > Use a prio qdisc with RED leaf qdiscs. RED and GREDs purpose is to
> > calculate a marking probability and not to provide any prioritizing
> > schemes.
>
>Prioritization is still implicitly provided if you vary the queue
>lengths or the drop probabilities.
>For example, if you set everything to be exactly the same, and varied
>only the drop probability - the VQ with the highest drop probability
>will be less important (i.e relatively more of its packets will be
>dropped; recall: the drop decision is made before the packet is queued).
>
>cheers,
>jamal
>
>
>
^ 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