From: Pravin Date: Thu, 20 Mar 2014 17:56:51 +0000 (-0700) Subject: netdev: Send ofpbuf directly to netdev. X-Git-Tag: sliver-openvswitch-2.2.90-1~6^2~45 X-Git-Url: http://git.onelab.eu/?a=commitdiff_plain;h=40d26f04b2588632cf08e2ca3ea2cee40402a3f9;p=sliver-openvswitch.git netdev: Send ofpbuf directly to netdev. DPDK netdev need to access ofpbuf while sending buffer. Following patch changes netdev_send accordingly. Signed-off-by: Pravin B Shelar Acked-by: Thomas Graf --- diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c index 254f8b840..f1bc10a77 100644 --- a/lib/dpif-netdev.c +++ b/lib/dpif-netdev.c @@ -1937,7 +1937,7 @@ dp_execute_cb(void *aux_, struct ofpbuf *packet, case OVS_ACTION_ATTR_OUTPUT: p = dp_netdev_lookup_port(aux->dp, u32_to_odp(nl_attr_get_u32(a))); if (p) { - netdev_send(p->netdev, packet); + netdev_send(p->netdev, packet, may_steal); } break; @@ -1951,6 +1951,10 @@ dp_execute_cb(void *aux_, struct ofpbuf *packet, % aux->dp->n_handlers, DPIF_UC_ACTION, aux->key, userdata); + + if (may_steal) { + ofpbuf_delete(packet); + } break; } case OVS_ACTION_ATTR_PUSH_VLAN: @@ -1964,9 +1968,6 @@ dp_execute_cb(void *aux_, struct ofpbuf *packet, OVS_NOT_REACHED(); } - if (may_steal) { - ofpbuf_delete(packet); - } } static void diff --git a/lib/netdev-bsd.c b/lib/netdev-bsd.c index cb996194f..99a60f169 100644 --- a/lib/netdev-bsd.c +++ b/lib/netdev-bsd.c @@ -683,10 +683,12 @@ netdev_bsd_rx_drain(struct netdev_rx *rx_) * system or a tap device. */ static int -netdev_bsd_send(struct netdev *netdev_, const void *data, size_t size) +netdev_bsd_send(struct netdev *netdev_, struct ofpbuf *pkt, bool may_steal) { struct netdev_bsd *dev = netdev_bsd_cast(netdev_); const char *name = netdev_get_name(netdev_); + const void *data = pkt->data; + size_t size = pkt->size; int error; ovs_mutex_lock(&dev->mutex); @@ -723,6 +725,10 @@ netdev_bsd_send(struct netdev *netdev_, const void *data, size_t size) } ovs_mutex_unlock(&dev->mutex); + if (may_steal) { + ofpbuf_delete(pkt); + } + return error; } diff --git a/lib/netdev-dummy.c b/lib/netdev-dummy.c index ecd7317df..a1d1b79d8 100644 --- a/lib/netdev-dummy.c +++ b/lib/netdev-dummy.c @@ -818,9 +818,11 @@ netdev_dummy_rx_drain(struct netdev_rx *rx_) } static int -netdev_dummy_send(struct netdev *netdev, const void *buffer, size_t size) +netdev_dummy_send(struct netdev *netdev, struct ofpbuf *pkt, bool may_steal) { struct netdev_dummy *dev = netdev_dummy_cast(netdev); + const void *buffer = pkt->data; + size_t size = pkt->size; if (size < ETH_HEADER_LEN) { return EMSGSIZE; @@ -855,6 +857,9 @@ netdev_dummy_send(struct netdev *netdev, const void *buffer, size_t size) } ovs_mutex_unlock(&dev->mutex); + if (may_steal) { + ofpbuf_delete(pkt); + } return 0; } diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c index 2aa674a9a..5d7bfa1b8 100644 --- a/lib/netdev-linux.c +++ b/lib/netdev-linux.c @@ -1054,8 +1054,11 @@ netdev_linux_rx_drain(struct netdev_rx *rx_) * The kernel maintains a packet transmission queue, so the caller is not * expected to do additional queuing of packets. */ static int -netdev_linux_send(struct netdev *netdev_, const void *data, size_t size) +netdev_linux_send(struct netdev *netdev_, struct ofpbuf *pkt, bool may_steal) { + const void *data = pkt->data; + size_t size = pkt->size; + for (;;) { ssize_t retval; @@ -1106,6 +1109,10 @@ netdev_linux_send(struct netdev *netdev_, const void *data, size_t size) retval = write(netdev->tap_fd, data, size); } + if (may_steal) { + ofpbuf_delete(pkt); + } + if (retval < 0) { /* The Linux AF_PACKET implementation never blocks waiting for room * for packets, instead returning ENOBUFS. Translate this into diff --git a/lib/netdev-provider.h b/lib/netdev-provider.h index 0711bb997..6a38e1f85 100644 --- a/lib/netdev-provider.h +++ b/lib/netdev-provider.h @@ -223,13 +223,13 @@ struct netdev_class { const struct netdev_tunnel_config * (*get_tunnel_config)(const struct netdev *netdev); - /* Sends the 'size'-byte packet in 'buffer' on 'netdev'. Returns 0 if - * successful, otherwise a positive errno value. Returns EAGAIN without - * blocking if the packet cannot be queued immediately. Returns EMSGSIZE - * if a partial packet was transmitted or if the packet is too big or too - * small to transmit on the device. + /* Sends the buffer on 'netdev'. + * Returns 0 if successful, otherwise a positive errno value. Returns + * EAGAIN without blocking if the packet cannot be queued immediately. + * Returns EMSGSIZE if a partial packet was transmitted or if the packet + * is too big or too small to transmit on the device. * - * The caller retains ownership of 'buffer' in all cases. + * To retain ownership of 'buffer' caller can set may_steal to false. * * The network device is expected to maintain a packet transmission queue, * so that the caller does not ordinarily have to do additional queuing of @@ -241,7 +241,7 @@ struct netdev_class { * network device from being usefully used by the netdev-based "userspace * datapath". It will also prevent the OVS implementation of bonding from * working properly over 'netdev'.) */ - int (*send)(struct netdev *netdev, const void *buffer, size_t size); + int (*send)(struct netdev *netdev, struct ofpbuf *buffer, bool may_steal); /* Registers with the poll loop to wake up from the next call to * poll_block() when the packet transmission queue for 'netdev' has diff --git a/lib/netdev.c b/lib/netdev.c index 0d7b69d24..0d408bfe0 100644 --- a/lib/netdev.c +++ b/lib/netdev.c @@ -599,7 +599,7 @@ netdev_rx_drain(struct netdev_rx *rx) * immediately. Returns EMSGSIZE if a partial packet was transmitted or if * the packet is too big or too small to transmit on the device. * - * The caller retains ownership of 'buffer' in all cases. + * To retain ownership of 'buffer' caller can set may_steal to false. * * The kernel maintains a packet transmission queue, so the caller is not * expected to do additional queuing of packets. @@ -607,12 +607,12 @@ netdev_rx_drain(struct netdev_rx *rx) * Some network devices may not implement support for this function. In such * cases this function will always return EOPNOTSUPP. */ int -netdev_send(struct netdev *netdev, const struct ofpbuf *buffer) +netdev_send(struct netdev *netdev, struct ofpbuf *buffer, bool may_steal) { int error; error = (netdev->netdev_class->send - ? netdev->netdev_class->send(netdev, buffer->data, buffer->size) + ? netdev->netdev_class->send(netdev, buffer, may_steal) : EOPNOTSUPP); if (!error) { COVERAGE_INC(netdev_sent); diff --git a/lib/netdev.h b/lib/netdev.h index a4dd99b26..bbd717f26 100644 --- a/lib/netdev.h +++ b/lib/netdev.h @@ -166,7 +166,7 @@ void netdev_rx_wait(struct netdev_rx *); int netdev_rx_drain(struct netdev_rx *); /* Packet transmission. */ -int netdev_send(struct netdev *, const struct ofpbuf *); +int netdev_send(struct netdev *, struct ofpbuf *, bool may_steal); void netdev_send_wait(struct netdev *); /* Hardware address. */