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