#include "netdev-linux.h"
-#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include "hmap.h"
#include "netdev-provider.h"
#include "netdev-vport.h"
-#include "netlink.h"
#include "netlink-notifier.h"
#include "netlink-socket.h"
+#include "netlink.h"
#include "ofpbuf.h"
#include "openflow/openflow.h"
#include "packets.h"
#include "poll-loop.h"
#include "rtnetlink-link.h"
-#include "socket-util.h"
#include "shash.h"
+#include "socket-util.h"
#include "sset.h"
#include "timer.h"
+#include "unaligned.h"
#include "vlog.h"
VLOG_DEFINE_THIS_MODULE(netdev_linux);
netdev_dev_linux_cast(const struct netdev_dev *netdev_dev)
{
const struct netdev_class *netdev_class = netdev_dev_get_class(netdev_dev);
- assert(is_netdev_linux_class(netdev_class));
+ ovs_assert(is_netdev_linux_class(netdev_class));
return CONTAINER_OF(netdev_dev, struct netdev_dev_linux, netdev_dev);
}
{
struct netdev_dev *netdev_dev = netdev_get_dev(netdev);
const struct netdev_class *netdev_class = netdev_dev_get_class(netdev_dev);
- assert(is_netdev_linux_class(netdev_class));
+ ovs_assert(is_netdev_linux_class(netdev_class));
return CONTAINER_OF(netdev, struct netdev_linux, netdev);
}
cache_notifier_ref(void)
{
if (!cache_notifier_refcount) {
- assert(!netdev_linux_cache_notifier);
+ ovs_assert(!netdev_linux_cache_notifier);
netdev_linux_cache_notifier =
rtnetlink_link_notifier_create(netdev_linux_cache_cb, NULL);
static void
cache_notifier_unref(void)
{
- assert(cache_notifier_refcount > 0);
+ ovs_assert(cache_notifier_refcount > 0);
if (!--cache_notifier_refcount) {
- assert(netdev_linux_cache_notifier);
+ ovs_assert(netdev_linux_cache_notifier);
rtnetlink_link_notifier_destroy(netdev_linux_cache_notifier);
netdev_linux_cache_notifier = NULL;
}
sock = af_packet_sock();
if (sock < 0) {
- return sock;
+ return -sock;
}
error = get_ifindex(netdev_, &ifindex);
*b = tmp;
}
+/* Copies 'src' into 'dst', performing format conversion in the process.
+ *
+ * 'src' is allowed to be misaligned. */
+static void
+netdev_stats_from_ovs_vport_stats(struct netdev_stats *dst,
+ const struct ovs_vport_stats *src)
+{
+ dst->rx_packets = get_unaligned_u64(&src->rx_packets);
+ dst->tx_packets = get_unaligned_u64(&src->tx_packets);
+ dst->rx_bytes = get_unaligned_u64(&src->rx_bytes);
+ dst->tx_bytes = get_unaligned_u64(&src->tx_bytes);
+ dst->rx_errors = get_unaligned_u64(&src->rx_errors);
+ dst->tx_errors = get_unaligned_u64(&src->tx_errors);
+ dst->rx_dropped = get_unaligned_u64(&src->rx_dropped);
+ dst->tx_dropped = get_unaligned_u64(&src->tx_dropped);
+ dst->multicast = 0;
+ dst->collisions = 0;
+ dst->rx_length_errors = 0;
+ dst->rx_over_errors = 0;
+ dst->rx_crc_errors = 0;
+ dst->rx_frame_errors = 0;
+ dst->rx_fifo_errors = 0;
+ dst->rx_missed_errors = 0;
+ dst->tx_aborted_errors = 0;
+ dst->tx_carrier_errors = 0;
+ dst->tx_fifo_errors = 0;
+ dst->tx_heartbeat_errors = 0;
+ dst->tx_window_errors = 0;
+}
+
+static int
+get_stats_via_vport__(const struct netdev *netdev, struct netdev_stats *stats)
+{
+ struct dpif_linux_vport reply;
+ struct ofpbuf *buf;
+ int error;
+
+ error = dpif_linux_vport_get(netdev_get_name(netdev), &reply, &buf);
+ if (error) {
+ return error;
+ } else if (!reply.stats) {
+ ofpbuf_delete(buf);
+ return EOPNOTSUPP;
+ }
+
+ netdev_stats_from_ovs_vport_stats(stats, reply.stats);
+
+ ofpbuf_delete(buf);
+
+ return 0;
+}
+
static void
get_stats_via_vport(const struct netdev *netdev_,
struct netdev_stats *stats)
!(netdev_dev->cache_valid & VALID_VPORT_STAT_ERROR)) {
int error;
- error = netdev_vport_get_stats(netdev_, stats);
+ error = get_stats_via_vport__(netdev_, stats);
if (error && error != ENOENT) {
VLOG_WARN_RL(&rl, "%s: obtaining netdev stats via vport failed "
"(%s)", netdev_get_name(netdev_), strerror(error));
if (error) {
return error;
}
- assert(netdev_dev->tc == NULL);
+ ovs_assert(netdev_dev->tc == NULL);
/* Install new qdisc. */
error = new_ops->tc_install(netdev, details);
- assert((error == 0) == (netdev_dev->tc != NULL));
+ ovs_assert((error == 0) == (netdev_dev->tc != NULL));
return error;
}
netdev_linux_destroy, \
NULL, /* get_config */ \
NULL, /* set_config */ \
+ NULL, /* get_tunnel_config */ \
\
netdev_linux_open, \
netdev_linux_close, \
memset(&tc_police, 0, sizeof tc_police);
tc_police.action = TC_POLICE_SHOT;
tc_police.mtu = mtu;
- tc_fill_rate(&tc_police.rate, kbits_rate/8 * 1000, mtu);
+ tc_fill_rate(&tc_police.rate, (kbits_rate * 1000)/8, mtu);
tc_police.burst = tc_bytes_to_ticks(tc_police.rate.rate,
kbits_burst * 1024);
/* Instantiate it. */
load_error = ops->tc_load(CONST_CAST(struct netdev *, netdev), qdisc);
- assert((load_error == 0) == (netdev_dev->tc != NULL));
+ ovs_assert((load_error == 0) == (netdev_dev->tc != NULL));
ofpbuf_delete(qdisc);
return error ? error : load_error;
if (sock == INT_MIN) {
sock = socket(AF_PACKET, SOCK_RAW, 0);
if (sock >= 0) {
- set_nonblocking(sock);
+ int error = set_nonblocking(sock);
+ if (error) {
+ close(sock);
+ sock = -error;
+ }
} else {
sock = -errno;
VLOG_ERR("failed to create packet socket: %s", strerror(errno));