These will be used in both fipvlan and fcoemon for VLAN discovery

Signed-off-by: Chris Leech <[email protected]>
---

 fipvlan.c       |  150 ++++++++++++-----------------------------------------
 include/fip.h   |   22 ++++++++
 lib/Makefile.am |    2 -
 lib/fip.c       |  155 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 212 insertions(+), 117 deletions(-)
 create mode 100644 lib/fip.c

diff --git a/fipvlan.c b/fipvlan.c
index 3217a82..0e2141c 100644
--- a/fipvlan.c
+++ b/fipvlan.c
@@ -66,7 +66,7 @@ struct iff_list_head interfaces = 
TAILQ_HEAD_INITIALIZER(interfaces);
 TAILQ_HEAD(fcf_list_head, fcf);
 
 struct fcf {
-       struct iff *interface;
+       int ifindex;
        uint16_t vlan;
        unsigned char mac_addr[ETHER_ADDR_LEN];
        TAILQ_ENTRY(fcf) list_node;
@@ -74,6 +74,20 @@ struct fcf {
 
 struct fcf_list_head fcfs = TAILQ_HEAD_INITIALIZER(fcfs);
 
+struct iff *lookup_iff(int ifindex, char *ifname)
+{
+       struct iff *iff;
+
+       if (!ifindex && !ifname)
+               return NULL;
+
+       TAILQ_FOREACH(iff, &interfaces, list_node)
+               if ((!ifindex || ifindex == iff->ifindex) &&
+                   (!ifname  || strcmp(ifname, iff->ifname) == 0))
+                       return iff;
+       return NULL;
+}
+
 /**
  * packet_socket - create a packet socket bound to the FIP ethertype
  */
@@ -89,61 +103,6 @@ int packet_socket(void)
        return s;
 }
 
-/**
- * fip_send_vlan_request - send a FIP VLAN request
- * @s: ETH_P_FIP packet socket
- * @iff: network interface to send from
- *
- * Note: sends to FIP_ALL_FCF_MACS
- */
-ssize_t fip_send_vlan_request(int s, struct iff *iff)
-{
-       struct sockaddr_ll sa = {
-               .sll_family = AF_PACKET,
-               .sll_protocol = htons(ETH_P_FIP),
-               .sll_ifindex = iff->ifindex,
-               .sll_hatype = ARPHRD_ETHER,
-               .sll_pkttype = PACKET_MULTICAST,
-               .sll_halen = ETHER_ADDR_LEN,
-               .sll_addr = FIP_ALL_FCF_MACS,
-       };
-       struct fiphdr fh = {
-               .fip_version = FIP_VERSION(1),
-               .fip_proto = htons(FIP_PROTO_VLAN),
-               .fip_subcode = FIP_VLAN_REQ,
-               .fip_desc_len = htons(2),
-               .fip_flags = 0,
-       };
-       struct {
-               struct fip_tlv_mac_addr mac;
-       } tlvs = {
-               .mac = {
-                       .hdr.tlv_type = FIP_TLV_MAC_ADDR,
-                       .hdr.tlv_len = 2,
-               },
-       };
-       struct iovec iov[] = {
-               { .iov_base = &fh, .iov_len = sizeof(fh), },
-               { .iov_base = &tlvs, .iov_len = sizeof(tlvs), },
-       };
-       struct msghdr msg = {
-               .msg_name = &sa,
-               .msg_namelen = sizeof(sa),
-               .msg_iov = iov,
-               .msg_iovlen = ARRAY_SIZE(iov),
-       };
-       int rc;
-
-       memcpy(tlvs.mac.mac_addr, iff->mac_addr, ETHER_ADDR_LEN);
-
-       FIP_LOG_DBG("sending FIP VLAN request");
-       rc = sendmsg(s, &msg, 0);
-       if (rc < 0)
-               FIP_LOG_ERRNO("sendmsg error");
-
-       return rc;
-}
-
 struct fip_tlv_ptrs {
        struct fip_tlv_mac_addr         *mac;
        struct fip_tlv_vlan             *vlan[370];
@@ -199,26 +158,23 @@ unsigned int fip_parse_tlvs(void *ptr, int len, struct 
fip_tlv_ptrs *tlv_ptrs)
 /**
  * fip_recv_vlan_note - parse a FIP VLAN Notification
  * @fh: FIP header, the beginning of the received FIP frame
- * @len: total length of the received FIP frame
- * @iff: interface this notification was received on
+ * @ifindex: index of interface this was received on
  */
-int fip_recv_vlan_note(struct fiphdr *fh, ssize_t len, struct iff *iff)
+int fip_recv_vlan_note(struct fiphdr *fh, int ifindex)
 {
        struct fip_tlv_ptrs tlvs;
        struct fcf *fcf;
        unsigned int bitmap, required_tlvs;
-       int desc_len;
+       int len;
        int i;
 
        FIP_LOG_DBG("received FIP VLAN Notification");
 
-       desc_len = ntohs(fh->fip_desc_len);
-       if (len < (sizeof(*fh) + (desc_len << 2)))
-               return -1;
+       len = ntohs(fh->fip_desc_len);
 
        required_tlvs = (1 << FIP_TLV_MAC_ADDR) | (1 << FIP_TLV_VLAN);
 
-       bitmap = fip_parse_tlvs((fh + 1), desc_len, &tlvs);
+       bitmap = fip_parse_tlvs((fh + 1), len, &tlvs);
        if ((bitmap & required_tlvs) != required_tlvs)
                return -1;
 
@@ -229,7 +185,7 @@ int fip_recv_vlan_note(struct fiphdr *fh, ssize_t len, 
struct iff *iff)
                        break;
                }
                memset(fcf, 0, sizeof(*fcf));
-               fcf->interface = iff;
+               fcf->ifindex = ifindex;
                fcf->vlan = ntohs(tlvs.vlan[i]->vlan);
                memcpy(fcf->mac_addr, tlvs.mac->mac_addr, ETHER_ADDR_LEN);
                TAILQ_INSERT_TAIL(&fcfs, fcf, list_node);
@@ -238,67 +194,27 @@ int fip_recv_vlan_note(struct fiphdr *fh, ssize_t len, 
struct iff *iff)
        return 0;
 }
 
-/**
- * fip_recv - receive from a FIP packet socket
- * @s: packet socket with data ready to be received
- */
-int fip_recv(int s)
+int fip_vlan_handler(struct fiphdr *fh, struct sockaddr_ll *sa, void *arg)
 {
-       char buf[4096];
-       struct sockaddr_ll sa;
-       struct iovec iov[] = {
-               { .iov_base = &buf[0], .iov_len = sizeof(buf), },
-       };
-       struct msghdr msg = {
-               .msg_name = &sa,
-               .msg_namelen = sizeof(sa),
-               .msg_iov = iov,
-               .msg_iovlen = ARRAY_SIZE(iov),
-       };
-       struct fiphdr *fh;
-       struct iff *iff;
-       ssize_t len;
-
-       FIP_LOG_DBG("%s", __func__);
-
-       len = recvmsg(s, &msg, 0);
-       if (len < 0) {
-               FIP_LOG_ERRNO("packet socket recv error");
-               return len;
-       }
-
-       if (len < sizeof(*fh)) {
-               FIP_LOG_ERR(EINVAL, "received packed smaller that FIP header");
-               return -1;
-       }
-
-       fh = (struct fiphdr *) buf;
+       int rc = -1;
 
        /* We only care about VLAN Notifications */
        if (ntohs(fh->fip_proto) != FIP_PROTO_VLAN) {
                FIP_LOG_DBG("ignoring FIP packet, protocol %d",
-                         ntohs(fh->fip_proto));
-               return -1;
-       }
-       TAILQ_FOREACH(iff, &interfaces, list_node) {
-               if (iff->ifindex == sa.sll_ifindex)
-                       break;
-       }
-       if (!iff) {
-               FIP_LOG("received packet on unexpected interface");
+                           ntohs(fh->fip_proto));
                return -1;
        }
 
        switch (fh->fip_subcode) {
        case FIP_VLAN_NOTE:
-               fip_recv_vlan_note(fh, len, iff);
+               rc = fip_recv_vlan_note(fh, sa->sll_ifindex);
                break;
        default:
-               FIP_LOG("FIP packet with unknown subcode %d", fh->fip_subcode);
-               return -1;
+               FIP_LOG_DBG("ignored FIP VLAN packet with subcode %d",
+                           fh->fip_subcode);
+               break;
        }
-
-       return 0;
+       return rc;
 }
 
 /**
@@ -634,6 +550,7 @@ err:
 
 void print_results()
 {
+       struct iff *iff;
        struct fcf *fcf;
 
        if (TAILQ_EMPTY(&fcfs)) {
@@ -645,8 +562,9 @@ void print_results()
        printf("%-10.10s| %-5.5s| %-10.10s\n", "interface", "VLAN", "FCF MAC");
        printf("------------------------------------\n");
        TAILQ_FOREACH(fcf, &fcfs, list_node) {
+               iff = lookup_iff(fcf->ifindex, NULL);
                printf("%-10.10s| %-5d| %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
-                       fcf->interface->ifname, fcf->vlan,
+                       iff->ifname, fcf->vlan,
                        fcf->mac_addr[0], fcf->mac_addr[1], fcf->mac_addr[2],
                        fcf->mac_addr[3], fcf->mac_addr[4], fcf->mac_addr[5]);
        }
@@ -670,7 +588,7 @@ void recv_loop(int ps)
                        break;
                }
                if (pfd[0].revents)
-                       fip_recv(pfd[0].fd);
+                       fip_recv(pfd[0].fd, fip_vlan_handler, NULL);
                pfd[0].revents = 0;
        }
 }
@@ -709,7 +627,7 @@ int main(int argc, char **argv)
        }
 
        TAILQ_FOREACH(iff, &interfaces, list_node)
-               fip_send_vlan_request(ps, iff);
+               fip_send_vlan_request(ps, iff->ifindex, iff->mac_addr);
 
        recv_loop(ps);
        print_results();
diff --git a/include/fip.h b/include/fip.h
index 91a017f..3ae6f27 100644
--- a/include/fip.h
+++ b/include/fip.h
@@ -123,4 +123,26 @@ struct fip_tlv_vlan {
        uint16_t vlan;  /* only lower 12 bits matter */
 };
 
+
+/* libutil / fip.c functionality */
+
+/* FIP message handler, passed into fip_recv */
+typedef int fip_handler(struct fiphdr *fh, struct sockaddr_ll *sa, void *arg);
+
+/**
+ * fip_recv - receive from a FIP packet socket
+ * @s: packet socket with data ready to be received
+ */
+int fip_recv(int s, fip_handler *fn, void *arg);
+
+/**
+ * fip_send_vlan_request - send a FIP VLAN request
+ * @s: ETH_P_FIP packet socket to send on
+ * @ifindex: network interface index to send on
+ * @mac: mac address of the netif
+ *
+ * Note: sends to FIP_ALL_FCF_MACS
+ */
+ssize_t fip_send_vlan_request(int s, int ifindex, unsigned char *mac);
+
 #endif /* FIP_H */
diff --git a/lib/Makefile.am b/lib/Makefile.am
index a70f23d..b340171 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -1,3 +1,3 @@
 AM_CPPFLAGS = -I${top_srcdir}/include
 noinst_LIBRARIES = libutil.a
-libutil_a_SOURCES = fcoe_utils.c sa_log.c sa_select.c sa_timer.c sa_other.c
+libutil_a_SOURCES = fcoe_utils.c sa_log.c sa_select.c sa_timer.c sa_other.c 
fip.c
diff --git a/lib/fip.c b/lib/fip.c
new file mode 100644
index 0000000..a5430c9
--- /dev/null
+++ b/lib/fip.c
@@ -0,0 +1,155 @@
+/*
+ * Copyright(c) 2010 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Maintained at www.Open-FCoE.org
+ */
+
+/* Routines for automatic FIP VLAN discovery and creation */
+/* Shared by fcoemon and fipvlan */
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <errno.h>
+#include <getopt.h>
+#include <poll.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/ethernet.h>
+#include <netpacket/packet.h>
+#include <arpa/inet.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include "fip.h"
+#include "fcoemon_utils.h"
+
+#define FIP_LOG(...)                   sa_log(__VA_ARGS__)
+#define FIP_LOG_ERR(error, ...)                sa_log_err(error, __func__, 
__VA_ARGS__)
+#define FIP_LOG_ERRNO(...)             sa_log_err(errno, __func__, __VA_ARGS__)
+#define FIP_LOG_DBG(...)               sa_log_debug(__VA_ARGS__)
+
+#define ARRAY_SIZE(a)  (sizeof(a) / sizeof((a)[0]))
+
+/**
+ * fip_send_vlan_request - send a FIP VLAN request
+ * @s: ETH_P_FIP packet socket to send on
+ * @ifindex: network interface index to send on
+ * @mac: mac address of the sending network interface
+ *
+ * Note: sends to FIP_ALL_FCF_MACS
+ */
+ssize_t fip_send_vlan_request(int s, int ifindex, unsigned char *mac)
+{
+       struct sockaddr_ll sa = {
+               .sll_family = AF_PACKET,
+               .sll_protocol = htons(ETH_P_FIP),
+               .sll_ifindex = ifindex,
+               .sll_hatype = ARPHRD_ETHER,
+               .sll_pkttype = PACKET_MULTICAST,
+               .sll_halen = ETHER_ADDR_LEN,
+               .sll_addr = FIP_ALL_FCF_MACS,
+       };
+       struct fiphdr fh = {
+               .fip_version = FIP_VERSION(1),
+               .fip_proto = htons(FIP_PROTO_VLAN),
+               .fip_subcode = FIP_VLAN_REQ,
+               .fip_desc_len = htons(2),
+               .fip_flags = 0,
+       };
+       struct {
+               struct fip_tlv_mac_addr mac;
+       } tlvs = {
+               .mac = {
+                       .hdr.tlv_type = FIP_TLV_MAC_ADDR,
+                       .hdr.tlv_len = 2,
+               },
+       };
+       struct iovec iov[] = {
+               { .iov_base = &fh, .iov_len = sizeof(fh), },
+               { .iov_base = &tlvs, .iov_len = sizeof(tlvs), },
+       };
+       struct msghdr msg = {
+               .msg_name = &sa,
+               .msg_namelen = sizeof(sa),
+               .msg_iov = iov,
+               .msg_iovlen = ARRAY_SIZE(iov),
+       };
+       int rc;
+
+       memcpy(tlvs.mac.mac_addr, mac, ETHER_ADDR_LEN);
+
+       FIP_LOG_DBG("sending FIP VLAN request");
+       rc = sendmsg(s, &msg, 0);
+       if (rc < 0) {
+               rc = -errno;
+               FIP_LOG_ERRNO("sendmsg error");
+       }
+       return rc;
+}
+
+/**
+ * fip_recv - receive from a FIP packet socket
+ * @s: packet socket with data ready to be received
+ * @fn: FIP receive callback to process the payload
+ * @arg: argument to pass through to @fn
+ */
+int fip_recv(int s, fip_handler *fn, void *arg)
+{
+       char buf[4096];
+       struct sockaddr_ll sa;
+       struct iovec iov[] = {
+               { .iov_base = buf, .iov_len = sizeof(buf), },
+       };
+       struct msghdr msg = {
+               .msg_name = &sa,
+               .msg_namelen = sizeof(sa),
+               .msg_iov = iov,
+               .msg_iovlen = ARRAY_SIZE(iov),
+       };
+       struct fiphdr *fh;
+       ssize_t len, desc_len;
+
+       FIP_LOG_DBG("%s", __func__);
+
+       len = recvmsg(s, &msg, 0);
+       if (len < 0) {
+               FIP_LOG_ERRNO("packet socket recv error");
+               return len;
+       }
+
+       if (len < sizeof(*fh)) {
+               FIP_LOG_ERR(EINVAL, "received packed smaller that FIP header");
+               return -1;
+       }
+
+       fh = (struct fiphdr *) buf;
+
+       desc_len = ntohs(fh->fip_desc_len);
+       if (len < (sizeof(*fh) + (desc_len << 2))) {
+               FIP_LOG_ERR(EINVAL, "received data less that FIP descriptor");
+               return -1;
+       }
+
+       if (fn)
+               return fn(fh, &sa, arg);
+       return 0;
+}

_______________________________________________
devel mailing list
[email protected]
http://www.open-fcoe.org/mailman/listinfo/devel

Reply via email to