/* Sockets used for ioctl operations. */
static int af_inet_sock = -1; /* AF_INET, SOCK_DGRAM. */
-static int af_packet_sock = -1; /* AF_PACKET, SOCK_RAW. */
/* A Netlink routing socket that is not subscribed to any multicast groups. */
static struct nl_sock *rtnl_sock;
const uint8_t[ETH_ADDR_LEN]);
static int get_stats_via_netlink(int ifindex, struct netdev_stats *stats);
static int get_stats_via_proc(const char *netdev_name, struct netdev_stats *stats);
+static int af_packet_sock(void);
static bool
is_netdev_linux_class(const struct netdev_class *netdev_class)
status = af_inet_sock >= 0 ? 0 : errno;
if (status) {
VLOG_ERR("failed to create inet socket: %s", strerror(status));
- } else {
- /* Create AF_PACKET socket. */
- af_packet_sock = socket(AF_PACKET, SOCK_RAW, 0);
- status = af_packet_sock >= 0 ? 0 : errno;
- if (!status) {
- set_nonblocking(af_packet_sock);
- } else {
- VLOG_ERR("failed to create packet socket: %s",
- strerror(status));
- }
}
/* Create rtnetlink socket. */
struct iovec iov;
int ifindex;
int error;
+ int sock;
+
+ sock = af_packet_sock();
+ if (sock < 0) {
+ return sock;
+ }
error = get_ifindex(netdev_, &ifindex);
if (error) {
msg.msg_controllen = 0;
msg.msg_flags = 0;
- retval = sendmsg(af_packet_sock, &msg, 0);
+ retval = sendmsg(sock, &msg, 0);
} else {
/* Use the netdev's own fd to send to this device. This is
* essential for tap devices, because packets sent to a tap device
}
return error;
}
+
+/* Returns an AF_PACKET raw socket or a negative errno value. */
+static int
+af_packet_sock(void)
+{
+ static int sock = INT_MIN;
+
+ if (sock == INT_MIN) {
+ sock = socket(AF_PACKET, SOCK_RAW, 0);
+ if (sock >= 0) {
+ set_nonblocking(sock);
+ } else {
+ sock = -errno;
+ VLOG_ERR("failed to create packet socket: %s", strerror(errno));
+ }
+ }
+
+ return sock;
+}