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.
199 lines
5.7 KiB
199 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 |
|
|
|
|