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.

Signed-off-by: Chris Leech <[email protected]>
---
 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

-- 
You received this message because you are subscribed to the Google Groups 
"open-iscsi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/open-iscsi.
For more options, visit https://groups.google.com/d/optout.

Reply via email to