You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

200 lines
5.7 KiB

From bea3e68d7a242ff50714332598fabaf4975712a2 Mon Sep 17 00:00:00 2001
From: Chris Leech <cleech@redhat.com>
Date: Wed, 17 Jun 2015 15:07:53 -0700
Subject: [PATCH v2 6/9] iscsistart: support booting over a VLAN
Adds code to check for VLAN devices if the boot configuration specifies
a VLAN ID.
Does not create VLANs, they need to already be in place.
---
include/iscsi_net_util.h | 3 +-
usr/iscsi_net_util.c | 78 +++++++++++++++++++++++++++++++++++++++++--
utils/fwparam_ibft/fw_entry.c | 3 +-
3 files changed, 78 insertions(+), 6 deletions(-)
diff --git a/include/iscsi_net_util.h b/include/iscsi_net_util.h
index 31b80ad..cbf3637 100644
--- a/include/iscsi_net_util.h
+++ b/include/iscsi_net_util.h
@@ -6,7 +6,8 @@
extern int net_get_transport_name_from_netdev(char *netdev, char *transport);
extern int net_get_netdev_from_hwaddress(char *hwaddress, char *netdev);
extern int net_setup_netdev(char *netdev, char *local_ip, char *mask,
- char *gateway, char *remote_ip, int needs_bringup);
+ char *gateway, char *vlan, char *remote_ip,
+ int needs_bringup);
extern int net_ifup_netdev(char *netdev);
#endif
diff --git a/usr/iscsi_net_util.c b/usr/iscsi_net_util.c
index 848b4c6..06df9b3 100644
--- a/usr/iscsi_net_util.c
+++ b/usr/iscsi_net_util.c
@@ -19,6 +19,7 @@
#include <errno.h>
#include <net/if.h>
#include <unistd.h>
+#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/route.h>
@@ -27,6 +28,9 @@
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <linux/sockios.h>
+#include <linux/if_vlan.h>
+#include <net/if_arp.h>
+#include <linux/if_ether.h>
#include "sysdeps.h"
#include "ethtool-copy.h"
@@ -162,6 +166,45 @@ free_ifni:
return 0;
}
+static char *find_vlan_dev(char *netdev, int vlan_id) {
+ struct ifreq if_hwaddr;
+ struct ifreq vlan_hwaddr;
+ struct vlan_ioctl_args vlanrq = { .cmd = GET_VLAN_VID_CMD, };
+ struct if_nameindex *ifni;
+ char *vlan = NULL;
+ int sockfd, i, rc;
+
+ sockfd = socket(AF_INET, SOCK_DGRAM, 0);
+
+ strncpy(if_hwaddr.ifr_name, netdev, IFNAMSIZ);
+ ioctl(sockfd, SIOCGIFHWADDR, &if_hwaddr);
+
+ if (if_hwaddr.ifr_hwaddr.sa_family != ARPHRD_ETHER)
+ return NULL;
+
+ ifni = if_nameindex();
+ for (i = 0; ifni[i].if_index && ifni[i].if_name; i++) {
+ strncpy(vlan_hwaddr.ifr_name, ifni[i].if_name, IFNAMSIZ);
+ ioctl(sockfd, SIOCGIFHWADDR, &vlan_hwaddr);
+
+ if (vlan_hwaddr.ifr_hwaddr.sa_family != ARPHRD_ETHER)
+ continue;
+
+ if (!memcmp(if_hwaddr.ifr_hwaddr.sa_data, vlan_hwaddr.ifr_hwaddr.sa_data, ETH_ALEN)) {
+ strncpy(vlanrq.device1, ifni[i].if_name, IFNAMSIZ);
+ rc = ioctl(sockfd, SIOCGIFVLAN, &vlanrq);
+ if ((rc == 0) && (vlanrq.u.VID == vlan_id)) {
+ vlan = strdup(vlanrq.device1);
+ break;
+ }
+ }
+ }
+ if_freenameindex(ifni);
+
+ close(sockfd);
+ return vlan;
+}
+
/**
* net_setup_netdev - bring up NIC
* @netdev: network device name
@@ -175,7 +218,7 @@ free_ifni:
* to force iSCSI traffic through correct NIC.
*/
int net_setup_netdev(char *netdev, char *local_ip, char *mask, char *gateway,
- char *remote_ip, int needs_bringup)
+ char *vlan, char *remote_ip, int needs_bringup)
{
struct sockaddr_in sk_ipaddr = { .sin_family = AF_INET };
struct sockaddr_in sk_netmask = { .sin_family = AF_INET };
@@ -184,14 +227,29 @@ int net_setup_netdev(char *netdev, char *local_ip, char *mask, char *gateway,
struct sockaddr_in sk_tgt_ipaddr = { .sin_family = AF_INET };
struct rtentry rt;
struct ifreq ifr;
+ char *physdev = NULL;
int sock;
int ret;
+ int vlan_id;
if (!strlen(netdev)) {
log_error("No netdev name in fw entry.");
return EINVAL;
}
+ vlan_id = atoi(vlan);
+
+ if (vlan_id != 0) {
+ physdev = netdev;
+ netdev = find_vlan_dev(physdev, vlan_id);
+ }
+
+ if (vlan_id && !netdev) {
+ /* TODO: create vlan if not found */
+ log_error("No matching vlan found for fw entry.");
+ return EINVAL;
+ }
+
/* Create socket for making networking changes */
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
log_error("Could not open socket to manage network "
@@ -224,7 +282,19 @@ int net_setup_netdev(char *netdev, char *local_ip, char *mask, char *gateway,
/* Only set IP/NM if this is a new interface */
if (needs_bringup) {
- /* TODO: create vlan if strlen(vlan) */
+
+ if (physdev) {
+ /* Bring up interface */
+ memset(&ifr, 0, sizeof(ifr));
+ strlcpy(ifr.ifr_name, physdev, IFNAMSIZ);
+ ifr.ifr_flags = IFF_UP | IFF_RUNNING;
+ if (ioctl(sock, SIOCSIFFLAGS, &ifr) < 0) {
+ log_error("Could not bring up netdev %s (err %d - %s)",
+ physdev, errno, strerror(errno));
+ ret = errno;
+ goto done;
+ }
+ }
/* Bring up interface */
memset(&ifr, 0, sizeof(ifr));
@@ -246,7 +316,7 @@ int net_setup_netdev(char *netdev, char *local_ip, char *mask, char *gateway,
ret = errno;
goto done;
}
-
+
/* Set netmask */
memset(&ifr, 0, sizeof(ifr));
strlcpy(ifr.ifr_name, netdev, IFNAMSIZ);
@@ -303,6 +373,8 @@ int net_setup_netdev(char *netdev, char *local_ip, char *mask, char *gateway,
done:
close(sock);
+ if (vlan_id)
+ free(netdev);
return ret;
}
diff --git a/utils/fwparam_ibft/fw_entry.c b/utils/fwparam_ibft/fw_entry.c
index f94a035..0a1b46b 100644
--- a/utils/fwparam_ibft/fw_entry.c
+++ b/utils/fwparam_ibft/fw_entry.c
@@ -41,8 +41,6 @@
/**
* fw_setup_nics - setup nics (ethXs) based on ibft net info
*
- * Currently does not support vlans.
- *
* If this is a offload card, this function does nothing. The
* net info is used by the iscsi iface settings for the iscsi
* function.
@@ -82,6 +80,7 @@ int fw_setup_nics(void)
err = net_setup_netdev(context->iface, context->ipaddr,
context->mask, context->gateway,
+ context->vlan,
context->target_ipaddr, needs_bringup);
if (err)
ret = err;
--
2.5.5