From: Ben Pfaff Date: Fri, 9 Apr 2010 20:54:37 +0000 (-0700) Subject: netdev: Allow recv, recv_wait, drain, send, send_wait to be null. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1ac981803fad658965714bf82fd6b17f910f4b33;p=openvswitch netdev: Allow recv, recv_wait, drain, send, send_wait to be null. Suggested by partner. --- diff --git a/lib/netdev-provider.h b/lib/netdev-provider.h index 1eb1b1e4..e1c18ccb 100644 --- a/lib/netdev-provider.h +++ b/lib/netdev-provider.h @@ -175,15 +175,28 @@ struct netdev_class { /* Attempts to receive a packet from 'netdev' into the 'size' bytes in * 'buffer'. If successful, returns the number of bytes in the received * packet, otherwise a negative errno value. Returns -EAGAIN immediately - * if no packet is ready to be received. */ + * if no packet is ready to be received. + * + * May return -EOPNOTSUPP if a network device does not implement packet + * reception through this interface. This function may be set to null if + * it would always return -EOPNOTSUPP anyhow. (This will disable the OVS + * integrated DHCP client and OpenFlow controller discovery, and prevent + * the network device from being usefully used by the netdev-based + * "userspace datapath".) */ int (*recv)(struct netdev *netdev, void *buffer, size_t size); /* Registers with the poll loop to wake up from the next call to * poll_block() when a packet is ready to be received with netdev_recv() on - * 'netdev'. */ + * 'netdev'. + * + * May be null if not needed, such as for a network device that does not + * implement packet reception through the 'recv' member function. */ void (*recv_wait)(struct netdev *netdev); - /* Discards all packets waiting to be received from 'netdev'. */ + /* Discards all packets waiting to be received from 'netdev'. + * + * May be null if not needed, such as for a network device that does not + * implement packet reception through the 'recv' member function. */ int (*drain)(struct netdev *netdev); /* Sends the 'size'-byte packet in 'buffer' on 'netdev'. Returns 0 if @@ -196,7 +209,14 @@ struct netdev_class { * * The network device is expected to maintain a packet transmission queue, * so that the caller does not ordinarily have to do additional queuing of - * packets. */ + * packets. + * + * May return EOPNOTSUPP if a network device does not implement packet + * transmission through this interface. This function may be set to null + * if it would always return EOPNOTSUPP anyhow. (This will disable the OVS + * integrated DHCP client and OpenFlow controller discovery, and prevent + * the network device from being usefully used by the netdev-based + * "userspace datapath".) */ int (*send)(struct netdev *netdev, const void *buffer, size_t size); /* Registers with the poll loop to wake up from the next call to @@ -205,7 +225,10 @@ struct netdev_class { * * The network device is expected to maintain a packet transmission queue, * so that the caller does not ordinarily have to do additional queuing of - * packets. Thus, this function is unlikely to ever be useful. */ + * packets. Thus, this function is unlikely to ever be useful. + * + * May be null if not needed, such as for a network device that does not + * implement packet transmission through the 'send' member function. */ void (*send_wait)(struct netdev *netdev); /* Sets 'netdev''s Ethernet address to 'mac' */ diff --git a/lib/netdev.c b/lib/netdev.c index 2c7b260e..99b5d243 100644 --- a/lib/netdev.c +++ b/lib/netdev.c @@ -472,17 +472,23 @@ netdev_enumerate(struct svec *svec) * guaranteed to contain at least ETH_TOTAL_MIN bytes. Otherwise, returns a * positive errno value. Returns EAGAIN immediately if no packet is ready to * be returned. + * + * Some network devices may not implement support for this function. In such + * cases this function will always return EOPNOTSUPP. */ int netdev_recv(struct netdev *netdev, struct ofpbuf *buffer) { + int (*recv)(struct netdev *, void *, size_t); int retval; assert(buffer->size == 0); assert(ofpbuf_tailroom(buffer) >= ETH_TOTAL_MIN); - retval = netdev_get_dev(netdev)->netdev_class->recv(netdev, buffer->data, - ofpbuf_tailroom(buffer)); + recv = netdev_get_dev(netdev)->netdev_class->recv; + retval = (recv + ? (recv)(netdev, buffer->data, ofpbuf_tailroom(buffer)) + : -EOPNOTSUPP); if (retval >= 0) { COVERAGE_INC(netdev_received); buffer->size += retval; @@ -500,14 +506,22 @@ netdev_recv(struct netdev *netdev, struct ofpbuf *buffer) void netdev_recv_wait(struct netdev *netdev) { - netdev_get_dev(netdev)->netdev_class->recv_wait(netdev); + void (*recv_wait)(struct netdev *); + + recv_wait = netdev_get_dev(netdev)->netdev_class->recv_wait; + if (recv_wait) { + recv_wait(netdev); + } } /* Discards all packets waiting to be received from 'netdev'. */ int netdev_drain(struct netdev *netdev) { - return netdev_get_dev(netdev)->netdev_class->drain(netdev); + int (*drain)(struct netdev *); + + drain = netdev_get_dev(netdev)->netdev_class->drain; + return drain ? drain(netdev) : 0; } /* Sends 'buffer' on 'netdev'. Returns 0 if successful, otherwise a positive @@ -518,12 +532,18 @@ netdev_drain(struct netdev *netdev) * The caller retains ownership of 'buffer' in all cases. * * The kernel maintains a packet transmission queue, so the caller is not - * expected to do additional queuing of packets. */ + * expected to do additional queuing of packets. + * + * 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) { - int error = netdev_get_dev(netdev)->netdev_class->send(netdev, - buffer->data, buffer->size); + int (*send)(struct netdev *, const void *, size_t); + int error; + + send = netdev_get_dev(netdev)->netdev_class->send; + error = send ? (send)(netdev, buffer->data, buffer->size) : EOPNOTSUPP; if (!error) { COVERAGE_INC(netdev_sent); } @@ -540,7 +560,12 @@ netdev_send(struct netdev *netdev, const struct ofpbuf *buffer) void netdev_send_wait(struct netdev *netdev) { - return netdev_get_dev(netdev)->netdev_class->send_wait(netdev); + void (*send_wait)(struct netdev *); + + send_wait = netdev_get_dev(netdev)->netdev_class->send_wait; + if (send_wait) { + send_wait(netdev); + } } /* Attempts to set 'netdev''s MAC address to 'mac'. Returns 0 if successful,