|
Packit Service |
bca4e3 |
/*
|
|
Packit Service |
bca4e3 |
* Copyright(c) 2010 Intel Corporation. All rights reserved.
|
|
Packit Service |
bca4e3 |
*
|
|
Packit Service |
bca4e3 |
* This program is free software; you can redistribute it and/or modify it
|
|
Packit Service |
bca4e3 |
* under the terms and conditions of the GNU General Public License,
|
|
Packit Service |
bca4e3 |
* version 2, as published by the Free Software Foundation.
|
|
Packit Service |
bca4e3 |
*
|
|
Packit Service |
bca4e3 |
* This program is distributed in the hope it will be useful, but WITHOUT
|
|
Packit Service |
bca4e3 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
Packit Service |
bca4e3 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
Packit Service |
bca4e3 |
* more details.
|
|
Packit Service |
bca4e3 |
*
|
|
Packit Service |
bca4e3 |
* You should have received a copy of the GNU General Public License along with
|
|
Packit Service |
bca4e3 |
* this program; if not, write to the Free Software Foundation, Inc.,
|
|
Packit Service |
bca4e3 |
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
|
Packit Service |
bca4e3 |
*
|
|
Packit Service |
bca4e3 |
* Maintained at www.Open-FCoE.org
|
|
Packit Service |
bca4e3 |
*/
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
#include <string.h>
|
|
Packit Service |
bca4e3 |
#include <stdlib.h>
|
|
Packit Service |
bca4e3 |
#include <stdio.h>
|
|
Packit Service |
bca4e3 |
#include <stdarg.h>
|
|
Packit Service |
bca4e3 |
#include <stdint.h>
|
|
Packit Service |
bca4e3 |
#include <stdbool.h>
|
|
Packit Service |
bca4e3 |
#include <unistd.h>
|
|
Packit Service |
bca4e3 |
#include <errno.h>
|
|
Packit Service |
bca4e3 |
#include <getopt.h>
|
|
Packit Service |
bca4e3 |
#include <poll.h>
|
|
Packit Service |
bca4e3 |
#include <signal.h>
|
|
Packit Service |
bca4e3 |
#include <sys/ioctl.h>
|
|
Packit Service |
bca4e3 |
#include <sys/socket.h>
|
|
Packit Service |
bca4e3 |
#include <sys/queue.h>
|
|
Packit Service |
bca4e3 |
#include <net/if.h>
|
|
Packit Service |
bca4e3 |
#include <net/if_arp.h>
|
|
Packit Service |
bca4e3 |
#include <net/ethernet.h>
|
|
Packit Service |
bca4e3 |
#include <arpa/inet.h>
|
|
Packit Service |
bca4e3 |
#include <linux/netlink.h>
|
|
Packit Service |
bca4e3 |
#include <linux/rtnetlink.h>
|
|
Packit Service |
bca4e3 |
#include <linux/if_packet.h>
|
|
Packit Service |
bca4e3 |
#include <linux/capability.h>
|
|
Packit Service |
bca4e3 |
#include <sys/syscall.h>
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
#include <sys/stat.h>
|
|
Packit Service |
bca4e3 |
#include <fcntl.h>
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
#include "fcoe_utils_version.h"
|
|
Packit Service |
bca4e3 |
#include "fip.h"
|
|
Packit Service |
bca4e3 |
#include "fcoemon_utils.h"
|
|
Packit Service |
bca4e3 |
#include "fcoe_utils.h"
|
|
Packit Service |
bca4e3 |
#include "rtnetlink.h"
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
#define FIP_LOG(...) sa_log(__VA_ARGS__)
|
|
Packit Service |
bca4e3 |
#define FIP_LOG_ERR(error, ...) sa_log_err(error, __func__, __VA_ARGS__)
|
|
Packit Service |
bca4e3 |
#define FIP_LOG_ERRNO(...) sa_log_err(errno, __func__, __VA_ARGS__)
|
|
Packit Service |
bca4e3 |
#define FIP_LOG_DBG(...) sa_log_debug(__VA_ARGS__)
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
#define MAX_VLAN_RETRIES 50
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
/* global configuration */
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
struct {
|
|
Packit Service |
bca4e3 |
char **namev;
|
|
Packit Service |
bca4e3 |
int namec;
|
|
Packit Service |
bca4e3 |
bool automode;
|
|
Packit Service |
bca4e3 |
bool create;
|
|
Packit Service |
bca4e3 |
bool start;
|
|
Packit Service |
bca4e3 |
bool vn2vn;
|
|
Packit Service |
bca4e3 |
bool debug;
|
|
Packit Service |
bca4e3 |
bool link_up;
|
|
Packit Service |
bca4e3 |
int link_retry;
|
|
Packit Service |
bca4e3 |
char suffix[256];
|
|
Packit Service |
bca4e3 |
} config = {
|
|
Packit Service |
bca4e3 |
.namev = NULL,
|
|
Packit Service |
bca4e3 |
.namec = 0,
|
|
Packit Service |
bca4e3 |
.automode = false,
|
|
Packit Service |
bca4e3 |
.create = false,
|
|
Packit Service |
bca4e3 |
.vn2vn = false,
|
|
Packit Service |
bca4e3 |
.debug = false,
|
|
Packit Service |
bca4e3 |
.link_up = false,
|
|
Packit Service |
bca4e3 |
.link_retry = 20,
|
|
Packit Service |
bca4e3 |
.suffix = "",
|
|
Packit Service |
bca4e3 |
};
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
int (*fcoe_instance_start)(const char *ifname);
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
char *exe;
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
static struct pollfd *pfd = NULL;
|
|
Packit Service |
bca4e3 |
static int pfd_len = 0;
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
static void pfd_add(int fd)
|
|
Packit Service |
bca4e3 |
{
|
|
Packit Service |
bca4e3 |
struct pollfd *npfd;
|
|
Packit Service |
bca4e3 |
int i;
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
for (i = 0; i < pfd_len; i++)
|
|
Packit Service |
bca4e3 |
if (pfd[i].fd == fd)
|
|
Packit Service |
bca4e3 |
return;
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
npfd = realloc(pfd, (pfd_len + 1) * sizeof(struct pollfd));
|
|
Packit Service |
bca4e3 |
if (!npfd) {
|
|
Packit Service |
bca4e3 |
perror("realloc fail");
|
|
Packit Service |
bca4e3 |
return;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
pfd = npfd;
|
|
Packit Service |
bca4e3 |
pfd[pfd_len].fd = fd;
|
|
Packit Service |
bca4e3 |
pfd[pfd_len].events = POLLIN;
|
|
Packit Service |
bca4e3 |
pfd_len++;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
static void pfd_remove(int fd)
|
|
Packit Service |
bca4e3 |
{
|
|
Packit Service |
bca4e3 |
struct pollfd *npfd;
|
|
Packit Service |
bca4e3 |
int i;
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
for (i = 0; i < pfd_len; i++) {
|
|
Packit Service |
bca4e3 |
if (pfd[i].fd == fd)
|
|
Packit Service |
bca4e3 |
break;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
if (i == pfd_len)
|
|
Packit Service |
bca4e3 |
return;
|
|
Packit Service |
bca4e3 |
memmove(&pfd[i], &pfd[i+1], (--pfd_len - i) * sizeof(struct pollfd));
|
|
Packit Service |
bca4e3 |
npfd = realloc(pfd, pfd_len * sizeof(struct pollfd));
|
|
Packit Service |
bca4e3 |
if (npfd)
|
|
Packit Service |
bca4e3 |
pfd = npfd;
|
|
Packit Service |
bca4e3 |
else
|
|
Packit Service |
bca4e3 |
perror("realloc failed");
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
TAILQ_HEAD(iff_list_head, iff);
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
struct iff {
|
|
Packit Service |
bca4e3 |
int ps; /* packet socket file descriptor */
|
|
Packit Service |
bca4e3 |
int ifindex;
|
|
Packit Service |
bca4e3 |
int iflink;
|
|
Packit Service |
bca4e3 |
char ifname[IFNAMSIZ];
|
|
Packit Service |
bca4e3 |
unsigned char mac_addr[ETHER_ADDR_LEN];
|
|
Packit Service |
bca4e3 |
bool running;
|
|
Packit Service |
bca4e3 |
bool is_vlan;
|
|
Packit Service |
bca4e3 |
short int vid;
|
|
Packit Service |
bca4e3 |
bool linkup_sent;
|
|
Packit Service |
bca4e3 |
bool req_sent;
|
|
Packit Service |
bca4e3 |
bool resp_recv;
|
|
Packit Service |
bca4e3 |
bool fip_ready;
|
|
Packit Service |
bca4e3 |
bool fcoe_started;
|
|
Packit Service |
bca4e3 |
TAILQ_ENTRY(iff) list_node;
|
|
Packit Service |
bca4e3 |
struct iff_list_head vlans;
|
|
Packit Service |
bca4e3 |
};
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
struct iff_list_head interfaces = TAILQ_HEAD_INITIALIZER(interfaces);
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
TAILQ_HEAD(fcf_list_head, fcf);
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
struct fcf {
|
|
Packit Service |
bca4e3 |
int ifindex;
|
|
Packit Service |
bca4e3 |
uint16_t vlan;
|
|
Packit Service |
bca4e3 |
unsigned char mac_addr[ETHER_ADDR_LEN];
|
|
Packit Service |
bca4e3 |
TAILQ_ENTRY(fcf) list_node;
|
|
Packit Service |
bca4e3 |
};
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
struct fcf_list_head fcfs = TAILQ_HEAD_INITIALIZER(fcfs);
|
|
Packit Service |
bca4e3 |
static struct fcf_list_head vn2vns = TAILQ_HEAD_INITIALIZER(vn2vns);
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
static int create_and_start_vlan(struct fcf *fcf, bool vn2vn);
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
static struct fcf *lookup_fcf(struct fcf_list_head *head, int ifindex,
|
|
Packit Service |
bca4e3 |
uint16_t vlan, unsigned char *mac)
|
|
Packit Service |
bca4e3 |
{
|
|
Packit Service |
bca4e3 |
struct fcf *fcf;
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
TAILQ_FOREACH(fcf, head, list_node)
|
|
Packit Service |
bca4e3 |
if ((ifindex == fcf->ifindex) && (vlan == fcf->vlan)) {
|
|
Packit Service |
bca4e3 |
if ((!mac) || (memcmp(mac, fcf->mac_addr, ETHER_ADDR_LEN) == 0))
|
|
Packit Service |
bca4e3 |
return fcf;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
return NULL;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
static struct iff *lookup_iff(int ifindex, const char *ifname)
|
|
Packit Service |
bca4e3 |
{
|
|
Packit Service |
bca4e3 |
struct iff *iff;
|
|
Packit Service |
bca4e3 |
struct iff *vlan;
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
if (!ifindex && !ifname)
|
|
Packit Service |
bca4e3 |
return NULL;
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
TAILQ_FOREACH(iff, &interfaces, list_node) {
|
|
Packit Service |
bca4e3 |
if ((!ifindex || ifindex == iff->ifindex) &&
|
|
Packit Service |
bca4e3 |
(!ifname || strcmp(ifname, iff->ifname) == 0))
|
|
Packit Service |
bca4e3 |
return iff;
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
TAILQ_FOREACH(vlan, &iff->vlans, list_node)
|
|
Packit Service |
bca4e3 |
if ((!ifindex || ifindex == vlan->ifindex) &&
|
|
Packit Service |
bca4e3 |
(!ifname || strcmp(ifname, vlan->ifname) == 0))
|
|
Packit Service |
bca4e3 |
return vlan;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
return NULL;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
static struct iff *lookup_vlan(int ifindex, short int vid)
|
|
Packit Service |
bca4e3 |
{
|
|
Packit Service |
bca4e3 |
struct iff *real_dev, *vlan;
|
|
Packit Service |
bca4e3 |
TAILQ_FOREACH(real_dev, &interfaces, list_node)
|
|
Packit Service |
bca4e3 |
if (real_dev->ifindex == ifindex)
|
|
Packit Service |
bca4e3 |
TAILQ_FOREACH(vlan, &real_dev->vlans, list_node)
|
|
Packit Service |
bca4e3 |
if (vlan->vid == vid)
|
|
Packit Service |
bca4e3 |
return vlan;
|
|
Packit Service |
bca4e3 |
return NULL;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
static struct iff *find_vlan_real_dev(struct iff *vlan)
|
|
Packit Service |
bca4e3 |
{
|
|
Packit Service |
bca4e3 |
struct iff *real_dev;
|
|
Packit Service |
bca4e3 |
TAILQ_FOREACH(real_dev, &interfaces, list_node) {
|
|
Packit Service |
bca4e3 |
if (real_dev->ifindex == vlan->iflink)
|
|
Packit Service |
bca4e3 |
return real_dev;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
return NULL;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
struct fip_tlv_ptrs {
|
|
Packit Service |
bca4e3 |
struct fip_tlv_mac_addr *mac;
|
|
Packit Service |
bca4e3 |
struct fip_tlv_vlan *vlan[370];
|
|
Packit Service |
bca4e3 |
unsigned int vlanc;
|
|
Packit Service |
bca4e3 |
};
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
#define SET_BIT(b, n) ((b) |= (1 << (n)))
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
#define TLV_LEN_CHECK(t, l) ({ \
|
|
Packit Service |
bca4e3 |
int _tlc = ((t)->tlv_len != (l)) ? 1 : 0; \
|
|
Packit Service |
bca4e3 |
if (_tlc) \
|
|
Packit Service |
bca4e3 |
FIP_LOG("bad length for TLV of type %d", (t)->tlv_type); \
|
|
Packit Service |
bca4e3 |
_tlc; \
|
|
Packit Service |
bca4e3 |
})
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
/**
|
|
Packit Service |
bca4e3 |
* fip_parse_tlvs - parse type/length/value encoded FIP descriptors
|
|
Packit Service |
bca4e3 |
* @ptr: pointer to beginning of FIP TLV payload, the first descriptor
|
|
Packit Service |
bca4e3 |
* @len: total length of all TLVs, in double words
|
|
Packit Service |
bca4e3 |
* @tlv_ptrs: pointers to type specific structures to fill out
|
|
Packit Service |
bca4e3 |
*/
|
|
Packit Service |
bca4e3 |
static unsigned int
|
|
Packit Service |
bca4e3 |
fip_parse_tlvs(void *ptr, int len, struct fip_tlv_ptrs *tlv_ptrs)
|
|
Packit Service |
bca4e3 |
{
|
|
Packit Service |
bca4e3 |
struct fip_tlv_hdr *tlv = ptr;
|
|
Packit Service |
bca4e3 |
unsigned int bitmap = 0;
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
tlv_ptrs->vlanc = 0;
|
|
Packit Service |
bca4e3 |
while (len > 0) {
|
|
Packit Service |
bca4e3 |
switch (tlv->tlv_type) {
|
|
Packit Service |
bca4e3 |
case FIP_TLV_MAC_ADDR:
|
|
Packit Service |
bca4e3 |
if (TLV_LEN_CHECK(tlv, 2))
|
|
Packit Service |
bca4e3 |
break;
|
|
Packit Service |
bca4e3 |
SET_BIT(bitmap, FIP_TLV_MAC_ADDR);
|
|
Packit Service |
bca4e3 |
tlv_ptrs->mac = (struct fip_tlv_mac_addr *) tlv;
|
|
Packit Service |
bca4e3 |
break;
|
|
Packit Service |
bca4e3 |
case FIP_TLV_VLAN:
|
|
Packit Service |
bca4e3 |
if (TLV_LEN_CHECK(tlv, 1))
|
|
Packit Service |
bca4e3 |
break;
|
|
Packit Service |
bca4e3 |
SET_BIT(bitmap, FIP_TLV_VLAN);
|
|
Packit Service |
bca4e3 |
tlv_ptrs->vlan[tlv_ptrs->vlanc++] = (void *) tlv;
|
|
Packit Service |
bca4e3 |
break;
|
|
Packit Service |
bca4e3 |
default:
|
|
Packit Service |
bca4e3 |
/* unexpected or unrecognized descriptor */
|
|
Packit Service |
bca4e3 |
FIP_LOG("unrecognized TLV type %d", tlv->tlv_type);
|
|
Packit Service |
bca4e3 |
break;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
len -= tlv->tlv_len;
|
|
Packit Service |
bca4e3 |
tlv = ((void *) tlv) + (tlv->tlv_len << 2);
|
|
Packit Service |
bca4e3 |
};
|
|
Packit Service |
bca4e3 |
return bitmap;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
/**
|
|
Packit Service |
bca4e3 |
* fip_recv_vlan_note - parse a FIP VLAN Notification
|
|
Packit Service |
bca4e3 |
* @fh: FIP header, the beginning of the received FIP frame
|
|
Packit Service |
bca4e3 |
* @ifindex: index of interface this was received on
|
|
Packit Service |
bca4e3 |
* @vn2vn: true if vn2vn notification
|
|
Packit Service |
bca4e3 |
*/
|
|
Packit Service |
bca4e3 |
static int fip_recv_vlan_note(struct fiphdr *fh, int ifindex, bool vn2vn)
|
|
Packit Service |
bca4e3 |
{
|
|
Packit Service |
bca4e3 |
struct fip_tlv_ptrs tlvs;
|
|
Packit Service |
bca4e3 |
struct fcf_list_head *head;
|
|
Packit Service |
bca4e3 |
struct fcf *fcf;
|
|
Packit Service |
bca4e3 |
struct iff *iff;
|
|
Packit Service |
bca4e3 |
uint16_t vlan;
|
|
Packit Service |
bca4e3 |
unsigned int bitmap, required_tlvs;
|
|
Packit Service |
bca4e3 |
int len;
|
|
Packit Service |
bca4e3 |
unsigned int i;
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
FIP_LOG_DBG("received FIP VLAN Notification");
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
len = ntohs(fh->fip_desc_len);
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
required_tlvs = (1 << FIP_TLV_MAC_ADDR) | (1 << FIP_TLV_VLAN);
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
tlvs.mac = NULL; /* Silence incorrect GCC warning */
|
|
Packit Service |
bca4e3 |
bitmap = fip_parse_tlvs((fh + 1), len, &tlvs);
|
|
Packit Service |
bca4e3 |
if ((bitmap & required_tlvs) != required_tlvs)
|
|
Packit Service |
bca4e3 |
return -1;
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
if (vn2vn)
|
|
Packit Service |
bca4e3 |
head = &vn2vns;
|
|
Packit Service |
bca4e3 |
else
|
|
Packit Service |
bca4e3 |
head = &fcf;;
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
iff = lookup_iff(ifindex, NULL);
|
|
Packit Service |
bca4e3 |
if (iff)
|
|
Packit Service |
bca4e3 |
iff->resp_recv = true;
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
for (i = 0; i < tlvs.vlanc; i++) {
|
|
Packit Service |
bca4e3 |
vlan = ntohs(tlvs.vlan[i]->vlan);
|
|
Packit Service |
bca4e3 |
if (lookup_fcf(head, ifindex, vlan, tlvs.mac->mac_addr))
|
|
Packit Service |
bca4e3 |
continue;
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
fcf = malloc(sizeof(*fcf));
|
|
Packit Service |
bca4e3 |
if (!fcf) {
|
|
Packit Service |
bca4e3 |
FIP_LOG_ERRNO("malloc failed");
|
|
Packit Service |
bca4e3 |
break;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
memset(fcf, 0, sizeof(*fcf));
|
|
Packit Service |
bca4e3 |
fcf->ifindex = ifindex;
|
|
Packit Service |
bca4e3 |
fcf->vlan = vlan;
|
|
Packit Service |
bca4e3 |
memcpy(fcf->mac_addr, tlvs.mac->mac_addr, ETHER_ADDR_LEN);
|
|
Packit Service |
bca4e3 |
TAILQ_INSERT_TAIL(head, fcf, list_node);
|
|
Packit Service |
bca4e3 |
if (!config.create)
|
|
Packit Service |
bca4e3 |
continue;
|
|
Packit Service |
bca4e3 |
create_and_start_vlan(fcf, vn2vn);
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
return 0;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
static int fip_vlan_handler(struct fiphdr *fh, struct sockaddr_ll *sa,
|
|
Packit Service |
bca4e3 |
UNUSED void *arg)
|
|
Packit Service |
bca4e3 |
{
|
|
Packit Service |
bca4e3 |
/* We only care about VLAN Notifications */
|
|
Packit Service |
bca4e3 |
if (ntohs(fh->fip_proto) != FIP_PROTO_VLAN) {
|
|
Packit Service |
bca4e3 |
FIP_LOG_DBG("ignoring FIP packet, protocol %d",
|
|
Packit Service |
bca4e3 |
ntohs(fh->fip_proto));
|
|
Packit Service |
bca4e3 |
return -1;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
switch (fh->fip_subcode) {
|
|
Packit Service |
bca4e3 |
case FIP_VLAN_NOTE:
|
|
Packit Service |
bca4e3 |
if (config.vn2vn) {
|
|
Packit Service |
bca4e3 |
FIP_LOG_DBG("ignoring FCF response in vn2vn mode\n");
|
|
Packit Service |
bca4e3 |
return -1;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
return fip_recv_vlan_note(fh, sa->sll_ifindex, false);
|
|
Packit Service |
bca4e3 |
case FIP_VLAN_NOTE_VN2VN:
|
|
Packit Service |
bca4e3 |
if (!config.vn2vn) {
|
|
Packit Service |
bca4e3 |
FIP_LOG_DBG("ignoring VN2VN response in fabric mode\n");
|
|
Packit Service |
bca4e3 |
return -1;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
return fip_recv_vlan_note(fh, sa->sll_ifindex, true);
|
|
Packit Service |
bca4e3 |
default:
|
|
Packit Service |
bca4e3 |
FIP_LOG_DBG("ignored FIP VLAN packet with subcode %d",
|
|
Packit Service |
bca4e3 |
fh->fip_subcode);
|
|
Packit Service |
bca4e3 |
return -1;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
/**
|
|
Packit Service |
bca4e3 |
* rtnl_recv_newlink - parse response to RTM_GETLINK, or an RTM_NEWLINK event
|
|
Packit Service |
bca4e3 |
* @nh: netlink message header, beginning of received netlink frame
|
|
Packit Service |
bca4e3 |
*/
|
|
Packit Service |
bca4e3 |
static void rtnl_recv_newlink(struct nlmsghdr *nh)
|
|
Packit Service |
bca4e3 |
{
|
|
Packit Service |
bca4e3 |
struct ifinfomsg *ifm = NLMSG_DATA(nh);
|
|
Packit Service |
bca4e3 |
struct rtattr *ifla[__IFLA_MAX];
|
|
Packit Service |
bca4e3 |
struct rtattr *linkinfo[__IFLA_INFO_MAX];
|
|
Packit Service |
bca4e3 |
struct rtattr *vlan[__IFLA_VLAN_MAX];
|
|
Packit Service |
bca4e3 |
struct iff *iff, *real_dev;
|
|
Packit Service |
bca4e3 |
struct fcf_list_head *head;
|
|
Packit Service |
bca4e3 |
bool running;
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
if (config.vn2vn)
|
|
Packit Service |
bca4e3 |
head = &vn2vns;
|
|
Packit Service |
bca4e3 |
else
|
|
Packit Service |
bca4e3 |
head = &fcf;;
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
FIP_LOG_DBG("RTM_NEWLINK: ifindex %d, type %d, flags %x",
|
|
Packit Service |
bca4e3 |
ifm->ifi_index, ifm->ifi_type, ifm->ifi_flags);
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
/* We only deal with Ethernet interfaces */
|
|
Packit Service |
bca4e3 |
if (ifm->ifi_type != ARPHRD_ETHER)
|
|
Packit Service |
bca4e3 |
return;
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
/* not on bond master, but rather allow FIP on the slaves below */
|
|
Packit Service |
bca4e3 |
if (ifm->ifi_flags & IFF_MASTER)
|
|
Packit Service |
bca4e3 |
return;
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
running = !!(ifm->ifi_flags & (IFF_RUNNING | IFF_SLAVE));
|
|
Packit Service |
bca4e3 |
iff = lookup_iff(ifm->ifi_index, NULL);
|
|
Packit Service |
bca4e3 |
if (iff) {
|
|
Packit Service |
bca4e3 |
int ifindex;
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
/* already tracking, update operstate and return */
|
|
Packit Service |
bca4e3 |
iff->running = running;
|
|
Packit Service |
bca4e3 |
if (!iff->running) {
|
|
Packit Service |
bca4e3 |
pfd_remove(iff->ps);
|
|
Packit Service |
bca4e3 |
return;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
pfd_add(iff->ps);
|
|
Packit Service |
bca4e3 |
if (!config.start)
|
|
Packit Service |
bca4e3 |
return;
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
FIP_LOG_DBG("Checking for FCoE on %sif %d",
|
|
Packit Service |
bca4e3 |
iff->is_vlan ? "VLAN " : "", iff->ifindex);
|
|
Packit Service |
bca4e3 |
if (iff->is_vlan) {
|
|
Packit Service |
bca4e3 |
real_dev = find_vlan_real_dev(iff);
|
|
Packit Service |
bca4e3 |
if (!real_dev) {
|
|
Packit Service |
bca4e3 |
FIP_LOG_ERR(ENODEV, "VLAN %d without a parent",
|
|
Packit Service |
bca4e3 |
iff->ifindex);
|
|
Packit Service |
bca4e3 |
return;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
ifindex = real_dev->ifindex;
|
|
Packit Service |
bca4e3 |
} else
|
|
Packit Service |
bca4e3 |
ifindex = iff->ifindex;
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
if (!iff->fcoe_started &&
|
|
Packit Service |
bca4e3 |
lookup_fcf(head, ifindex, iff->vid, NULL)) {
|
|
Packit Service |
bca4e3 |
printf("Starting FCoE on interface %s\n",
|
|
Packit Service |
bca4e3 |
iff->ifname);
|
|
Packit Service |
bca4e3 |
fcoe_instance_start(iff->ifname);
|
|
Packit Service |
bca4e3 |
iff->fcoe_started = true;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
return;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
iff = malloc(sizeof(*iff));
|
|
Packit Service |
bca4e3 |
if (!iff) {
|
|
Packit Service |
bca4e3 |
FIP_LOG_ERRNO("malloc failed");
|
|
Packit Service |
bca4e3 |
return;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
memset(iff, 0, sizeof(*iff));
|
|
Packit Service |
bca4e3 |
TAILQ_INIT(&iff->vlans);
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
parse_ifinfo(ifla, nh);
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
iff->ifindex = ifm->ifi_index;
|
|
Packit Service |
bca4e3 |
iff->running = running;
|
|
Packit Service |
bca4e3 |
iff->fip_ready = false;
|
|
Packit Service |
bca4e3 |
if (ifla[IFLA_LINK])
|
|
Packit Service |
bca4e3 |
iff->iflink = *(int *)RTA_DATA(ifla[IFLA_LINK]);
|
|
Packit Service |
bca4e3 |
else
|
|
Packit Service |
bca4e3 |
iff->iflink = iff->ifindex;
|
|
Packit Service |
bca4e3 |
memcpy(iff->mac_addr, RTA_DATA(ifla[IFLA_ADDRESS]), ETHER_ADDR_LEN);
|
|
Packit Service |
bca4e3 |
strncpy(iff->ifname, RTA_DATA(ifla[IFLA_IFNAME]), IFNAMSIZ);
|
|
Packit Service |
bca4e3 |
iff->ifname[IFNAMSIZ - 1] = '\0';
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
if (ifla[IFLA_LINKINFO]) {
|
|
Packit Service |
bca4e3 |
parse_linkinfo(linkinfo, ifla[IFLA_LINKINFO]);
|
|
Packit Service |
bca4e3 |
/* Track VLAN devices separately */
|
|
Packit Service |
bca4e3 |
if (linkinfo[IFLA_INFO_KIND] &&
|
|
Packit Service |
bca4e3 |
!strcmp(RTA_DATA(linkinfo[IFLA_INFO_KIND]), "vlan")) {
|
|
Packit Service |
bca4e3 |
iff->is_vlan = true;
|
|
Packit Service |
bca4e3 |
parse_vlaninfo(vlan, linkinfo[IFLA_INFO_DATA]);
|
|
Packit Service |
bca4e3 |
iff->vid = *(int *)RTA_DATA(vlan[IFLA_VLAN_ID]);
|
|
Packit Service |
bca4e3 |
real_dev = find_vlan_real_dev(iff);
|
|
Packit Service |
bca4e3 |
if (!real_dev) {
|
|
Packit Service |
bca4e3 |
free(iff);
|
|
Packit Service |
bca4e3 |
return;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
TAILQ_INSERT_TAIL(&real_dev->vlans, iff, list_node);
|
|
Packit Service |
bca4e3 |
if (!iff->running) {
|
|
Packit Service |
bca4e3 |
FIP_LOG_DBG("vlan if %d not running, "
|
|
Packit Service |
bca4e3 |
"starting", iff->ifindex);
|
|
Packit Service |
bca4e3 |
rtnl_set_iff_up(iff->ifindex, NULL);
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
return;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
/* ignore bonding interfaces */
|
|
Packit Service |
bca4e3 |
if (linkinfo[IFLA_INFO_KIND] &&
|
|
Packit Service |
bca4e3 |
!strcmp(RTA_DATA(linkinfo[IFLA_INFO_KIND]), "bond")) {
|
|
Packit Service |
bca4e3 |
free(iff);
|
|
Packit Service |
bca4e3 |
return;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
TAILQ_INSERT_TAIL(&interfaces, iff, list_node);
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
/* command line arguments */
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
#define GETOPT_STR "acdf:l:m:suhv"
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
static const struct option long_options[] = {
|
|
Packit Service |
bca4e3 |
{ "auto", no_argument, NULL, 'a' },
|
|
Packit Service |
bca4e3 |
{ "create", no_argument, NULL, 'c' },
|
|
Packit Service |
bca4e3 |
{ "start", no_argument, NULL, 's' },
|
|
Packit Service |
bca4e3 |
{ "debug", no_argument, NULL, 'd' },
|
|
Packit Service |
bca4e3 |
{ "suffix", required_argument, NULL, 'f' },
|
|
Packit Service |
bca4e3 |
{ "link-retry", required_argument, NULL, 'l' },
|
|
Packit Service |
bca4e3 |
{ "mode", required_argument, NULL, 'm' },
|
|
Packit Service |
bca4e3 |
{ "link-up", required_argument, NULL, 'u' },
|
|
Packit Service |
bca4e3 |
{ "help", no_argument, NULL, 'h' },
|
|
Packit Service |
bca4e3 |
{ "version", no_argument, NULL, 'v' },
|
|
Packit Service |
bca4e3 |
{ NULL, 0, NULL, 0 }
|
|
Packit Service |
bca4e3 |
};
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
static void help(int status)
|
|
Packit Service |
bca4e3 |
{
|
|
Packit Service |
bca4e3 |
printf(
|
|
Packit Service |
bca4e3 |
"Usage: %s [ options ] [ network interfaces ]\n"
|
|
Packit Service |
bca4e3 |
"Options:\n"
|
|
Packit Service |
bca4e3 |
" -a, --auto Auto select Ethernet interfaces\n"
|
|
Packit Service |
bca4e3 |
" -c, --create Create system VLAN devices\n"
|
|
Packit Service |
bca4e3 |
" -d, --debug Enable debugging output\n"
|
|
Packit Service |
bca4e3 |
" -s, --start Start FCoE login automatically\n"
|
|
Packit Service |
bca4e3 |
" -f, --suffix Append the suffix to VLAN interface name\n"
|
|
Packit Service |
bca4e3 |
" -l, --link-retry Number of retries for link up\n"
|
|
Packit Service |
bca4e3 |
" -m, --mode Link mode, either fabric or vn2vn\n"
|
|
Packit Service |
bca4e3 |
" -u, --link-up Leave link up after FIP response\n"
|
|
Packit Service |
bca4e3 |
" -h, --help Display this help and exit\n"
|
|
Packit Service |
bca4e3 |
" -v, --version Display version information and exit\n",
|
|
Packit Service |
bca4e3 |
exe);
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
exit(status);
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
static void parse_cmdline(int argc, char **argv)
|
|
Packit Service |
bca4e3 |
{
|
|
Packit Service |
bca4e3 |
signed char c;
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
while (1) {
|
|
Packit Service |
bca4e3 |
c = getopt_long(argc, argv, GETOPT_STR, long_options, NULL);
|
|
Packit Service |
bca4e3 |
if (c < 0)
|
|
Packit Service |
bca4e3 |
break;
|
|
Packit Service |
bca4e3 |
switch (c) {
|
|
Packit Service |
bca4e3 |
case 'a':
|
|
Packit Service |
bca4e3 |
config.automode = true;
|
|
Packit Service |
bca4e3 |
break;
|
|
Packit Service |
bca4e3 |
case 'c':
|
|
Packit Service |
bca4e3 |
config.create = true;
|
|
Packit Service |
bca4e3 |
break;
|
|
Packit Service |
bca4e3 |
case 'd':
|
|
Packit Service |
bca4e3 |
config.debug = true;
|
|
Packit Service |
bca4e3 |
break;
|
|
Packit Service |
bca4e3 |
case 's':
|
|
Packit Service |
bca4e3 |
config.start = true;
|
|
Packit Service |
bca4e3 |
break;
|
|
Packit Service |
bca4e3 |
case 'f':
|
|
Packit Service |
bca4e3 |
if (optarg && strlen(optarg)) {
|
|
Packit Service |
bca4e3 |
strncpy(config.suffix, optarg, 256);
|
|
Packit Service |
bca4e3 |
config.suffix[256 - 1] = '\0';
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
break;
|
|
Packit Service |
bca4e3 |
case 'l':
|
|
Packit Service |
bca4e3 |
config.link_retry = strtoul(optarg, NULL, 10);
|
|
Packit Service |
bca4e3 |
break;
|
|
Packit Service |
bca4e3 |
case 'm':
|
|
Packit Service |
bca4e3 |
if (strcasecmp(optarg, "vn2vn") == 0)
|
|
Packit Service |
bca4e3 |
config.vn2vn = true;
|
|
Packit Service |
bca4e3 |
else if (strcasecmp(optarg, "fabric") == 0)
|
|
Packit Service |
bca4e3 |
config.vn2vn = false;
|
|
Packit Service |
bca4e3 |
else {
|
|
Packit Service |
bca4e3 |
fprintf(stderr, "%s: Unknown value for mode: %s\n",
|
|
Packit Service |
bca4e3 |
exe, optarg);
|
|
Packit Service |
bca4e3 |
exit(1);
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
break;
|
|
Packit Service |
bca4e3 |
case 'u':
|
|
Packit Service |
bca4e3 |
config.link_up = true;
|
|
Packit Service |
bca4e3 |
break;
|
|
Packit Service |
bca4e3 |
case 'h':
|
|
Packit Service |
bca4e3 |
help(0);
|
|
Packit Service |
bca4e3 |
break;
|
|
Packit Service |
bca4e3 |
case 'v':
|
|
Packit Service |
bca4e3 |
printf("%s version %s\n", exe, FCOE_UTILS_VERSION);
|
|
Packit Service |
bca4e3 |
exit(0);
|
|
Packit Service |
bca4e3 |
break;
|
|
Packit Service |
bca4e3 |
default:
|
|
Packit Service |
bca4e3 |
fprintf(stderr, "Try '%s --help' "
|
|
Packit Service |
bca4e3 |
"for more information\n", exe);
|
|
Packit Service |
bca4e3 |
exit(1);
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
if ((optind == argc) && (!config.automode))
|
|
Packit Service |
bca4e3 |
help(1);
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
config.namev = &argv[optind];
|
|
Packit Service |
bca4e3 |
config.namec = argc - optind;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
static int rtnl_listener_handler(struct nlmsghdr *nh, UNUSED void *arg)
|
|
Packit Service |
bca4e3 |
{
|
|
Packit Service |
bca4e3 |
switch (nh->nlmsg_type) {
|
|
Packit Service |
bca4e3 |
case RTM_NEWLINK:
|
|
Packit Service |
bca4e3 |
rtnl_recv_newlink(nh);
|
|
Packit Service |
bca4e3 |
return 0;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
return -1;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
static int
|
|
Packit Service |
bca4e3 |
safe_makevlan_name(char *vlan_name, size_t vsz,
|
|
Packit Service |
bca4e3 |
char *ifname, int vlan_num, char *suffix)
|
|
Packit Service |
bca4e3 |
{
|
|
Packit Service |
bca4e3 |
size_t ifsz = strlen(ifname);
|
|
Packit Service |
bca4e3 |
size_t susz = strlen(suffix); /* should never be NULL */
|
|
Packit Service |
bca4e3 |
int nusz;
|
|
Packit Service |
bca4e3 |
char numbuf[16];
|
|
Packit Service |
bca4e3 |
char *cp = vlan_name;
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
nusz = snprintf(numbuf, sizeof(numbuf), "%d", vlan_num);
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
if ((ifsz + susz + nusz + 2) > vsz) {
|
|
Packit Service |
bca4e3 |
FIP_LOG_ERR(EINVAL,
|
|
Packit Service |
bca4e3 |
"Cannot make VLAN name from ifname=\"%s\", vlan %d, and suffix=\"%s\"\n",
|
|
Packit Service |
bca4e3 |
ifname, vlan_num, suffix);
|
|
Packit Service |
bca4e3 |
return -EINVAL;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
memcpy(cp, ifname, ifsz);
|
|
Packit Service |
bca4e3 |
cp += ifsz;
|
|
Packit Service |
bca4e3 |
memcpy(cp, numbuf, nusz);
|
|
Packit Service |
bca4e3 |
cp += nusz;
|
|
Packit Service |
bca4e3 |
if (susz > 0) {
|
|
Packit Service |
bca4e3 |
memcpy(cp, suffix, susz);
|
|
Packit Service |
bca4e3 |
cp += susz;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
*cp = '\0';
|
|
Packit Service |
bca4e3 |
return 0;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
static int
|
|
Packit Service |
bca4e3 |
create_and_start_vlan(struct fcf *fcf, bool vn2vn)
|
|
Packit Service |
bca4e3 |
{
|
|
Packit Service |
bca4e3 |
struct iff *real_dev, *vlan;
|
|
Packit Service |
bca4e3 |
char vlan_name[IFNAMSIZ];
|
|
Packit Service |
bca4e3 |
int rc;
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
real_dev = lookup_iff(fcf->ifindex, NULL);
|
|
Packit Service |
bca4e3 |
if (!real_dev) {
|
|
Packit Service |
bca4e3 |
FIP_LOG_ERR(ENODEV,
|
|
Packit Service |
bca4e3 |
"lost device %d with discovered %s?\n",
|
|
Packit Service |
bca4e3 |
fcf->ifindex, vn2vn ? "VN2VN" : "FCF");
|
|
Packit Service |
bca4e3 |
return -ENXIO;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
if (!fcf->vlan) {
|
|
Packit Service |
bca4e3 |
/*
|
|
Packit Service |
bca4e3 |
* If the vlan notification has VLAN id 0,
|
|
Packit Service |
bca4e3 |
* skip creating vlan interface, and FCoE is
|
|
Packit Service |
bca4e3 |
* started on the physical interface itself.
|
|
Packit Service |
bca4e3 |
*/
|
|
Packit Service |
bca4e3 |
FIP_LOG_DBG("VLAN id is 0 for %s\n", real_dev->ifname);
|
|
Packit Service |
bca4e3 |
vlan = real_dev;
|
|
Packit Service |
bca4e3 |
} else {
|
|
Packit Service |
bca4e3 |
vlan = lookup_vlan(fcf->ifindex, fcf->vlan);
|
|
Packit Service |
bca4e3 |
if (vlan) {
|
|
Packit Service |
bca4e3 |
FIP_LOG_DBG("VLAN %s.%d already exists as %s\n",
|
|
Packit Service |
bca4e3 |
real_dev->ifname, fcf->vlan, vlan->ifname);
|
|
Packit Service |
bca4e3 |
rc = 0;
|
|
Packit Service |
bca4e3 |
} else {
|
|
Packit Service |
bca4e3 |
rc = safe_makevlan_name(vlan_name, sizeof(vlan_name),
|
|
Packit Service |
bca4e3 |
real_dev->ifname, fcf->vlan, config.suffix);
|
|
Packit Service |
bca4e3 |
if (rc < 0)
|
|
Packit Service |
bca4e3 |
return rc;
|
|
Packit Service |
bca4e3 |
rc = vlan_create(fcf->ifindex, fcf->vlan, vlan_name);
|
|
Packit Service |
bca4e3 |
if (rc < 0)
|
|
Packit Service |
bca4e3 |
printf("Failed to create VLAN device %s\n\t%s\n",
|
|
Packit Service |
bca4e3 |
vlan_name, strerror(-rc));
|
|
Packit Service |
bca4e3 |
else
|
|
Packit Service |
bca4e3 |
printf("Created VLAN device %s\n", vlan_name);
|
|
Packit Service |
bca4e3 |
return rc;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
if (!config.start)
|
|
Packit Service |
bca4e3 |
return rc;
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
if (!vlan->running) {
|
|
Packit Service |
bca4e3 |
FIP_LOG_DBG("%s if %d not running, starting",
|
|
Packit Service |
bca4e3 |
vlan == real_dev ? "real" : "vlan",
|
|
Packit Service |
bca4e3 |
vlan->ifindex);
|
|
Packit Service |
bca4e3 |
rtnl_set_iff_up(vlan->ifindex, NULL);
|
|
Packit Service |
bca4e3 |
} else if (!vlan->fcoe_started) {
|
|
Packit Service |
bca4e3 |
printf("Starting FCoE on interface %s\n",
|
|
Packit Service |
bca4e3 |
vlan->ifname);
|
|
Packit Service |
bca4e3 |
fcoe_instance_start(vlan->ifname);
|
|
Packit Service |
bca4e3 |
vlan->fcoe_started = true;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
return rc;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
static int fcoe_mod_instance_start(const char *ifname)
|
|
Packit Service |
bca4e3 |
{
|
|
Packit Service |
bca4e3 |
enum fcoe_status ret;
|
|
Packit Service |
bca4e3 |
const char *path;
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
if (config.vn2vn)
|
|
Packit Service |
bca4e3 |
path = FCOE_CREATE_VN2VN;
|
|
Packit Service |
bca4e3 |
else
|
|
Packit Service |
bca4e3 |
path = FCOE_CREATE;
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
ret = fcm_write_str_to_sysfs_file(path, ifname);
|
|
Packit Service |
bca4e3 |
if (ret) {
|
|
Packit Service |
bca4e3 |
FIP_LOG_ERRNO("Failed to open file: %s", FCOE_CREATE);
|
|
Packit Service |
bca4e3 |
FIP_LOG_ERRNO("May be fcoe stack not loaded, starting"
|
|
Packit Service |
bca4e3 |
" fcoe service will fix that");
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
return EFAIL;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
return 0;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
static int fcoe_bus_instance_start(const char *ifname)
|
|
Packit Service |
bca4e3 |
{
|
|
Packit Service |
bca4e3 |
enum fcoe_status ret;
|
|
Packit Service |
bca4e3 |
char fchost[FCHOSTBUFLEN];
|
|
Packit Service |
bca4e3 |
char ctlr[FCHOSTBUFLEN];
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
ret = fcm_write_str_to_sysfs_file(FCOE_BUS_CREATE, ifname);
|
|
Packit Service |
bca4e3 |
if (ret) {
|
|
Packit Service |
bca4e3 |
FIP_LOG_ERRNO("Failed to open file: %s", FCOE_BUS_CREATE);
|
|
Packit Service |
bca4e3 |
FIP_LOG_ERRNO("May be fcoe stack not loaded, starting"
|
|
Packit Service |
bca4e3 |
" fcoe service will fix that");
|
|
Packit Service |
bca4e3 |
return ret;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
if (fcoe_find_fchost(ifname, fchost, FCHOSTBUFLEN)) {
|
|
Packit Service |
bca4e3 |
FIP_LOG_DBG("Failed to find fc_host for %s\n", ifname);
|
|
Packit Service |
bca4e3 |
return ENOSYSFS;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
if (fcoe_find_ctlr(fchost, ctlr, FCHOSTBUFLEN)) {
|
|
Packit Service |
bca4e3 |
FIP_LOG_DBG("Failed to get ctlr for %s\n", ifname);
|
|
Packit Service |
bca4e3 |
return ENOSYSFS;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
if (config.vn2vn) {
|
|
Packit Service |
bca4e3 |
ret = fcm_write_str_to_ctlr_attr(ctlr, FCOE_CTLR_ATTR_MODE,
|
|
Packit Service |
bca4e3 |
"vn2vn");
|
|
Packit Service |
bca4e3 |
if (ret)
|
|
Packit Service |
bca4e3 |
FIP_LOG_DBG("Failed to set mode interface %s\n",
|
|
Packit Service |
bca4e3 |
ifname);
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
ret = fcm_write_str_to_ctlr_attr(ctlr, FCOE_CTLR_ATTR_ENABLED, "1");
|
|
Packit Service |
bca4e3 |
if (ret)
|
|
Packit Service |
bca4e3 |
FIP_LOG_DBG("Failed to enable interface %s\n", ifname);
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
return 0;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
static void determine_libfcoe_interface(void)
|
|
Packit Service |
bca4e3 |
{
|
|
Packit Service |
bca4e3 |
if (!access(FCOE_BUS_CREATE, F_OK)) {
|
|
Packit Service |
bca4e3 |
FIP_LOG_DBG("Using /sys/bus/fcoe interfaces\n");
|
|
Packit Service |
bca4e3 |
fcoe_instance_start = &fcoe_bus_instance_start;
|
|
Packit Service |
bca4e3 |
} else {
|
|
Packit Service |
bca4e3 |
FIP_LOG_DBG("Using libfcoe module parameter interfaces\n");
|
|
Packit Service |
bca4e3 |
fcoe_instance_start = &fcoe_mod_instance_start;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
static void print_list(struct fcf_list_head *list, const char *label)
|
|
Packit Service |
bca4e3 |
{
|
|
Packit Service |
bca4e3 |
struct iff *iff;
|
|
Packit Service |
bca4e3 |
struct fcf *fcf;
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
printf("%-16.16s| %-5.5s| %-17.17s\n", "interface", "VLAN", label);
|
|
Packit Service |
bca4e3 |
printf("------------------------------------------\n");
|
|
Packit Service |
bca4e3 |
TAILQ_FOREACH(fcf, list, list_node) {
|
|
Packit Service |
bca4e3 |
iff = lookup_iff(fcf->ifindex, NULL);
|
|
Packit Service |
bca4e3 |
printf("%-16.16s| %-5d| %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
|
|
Packit Service |
bca4e3 |
iff->ifname, fcf->vlan,
|
|
Packit Service |
bca4e3 |
fcf->mac_addr[0], fcf->mac_addr[1], fcf->mac_addr[2],
|
|
Packit Service |
bca4e3 |
fcf->mac_addr[3], fcf->mac_addr[4], fcf->mac_addr[5]);
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
printf("\n");
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
static int print_results(void)
|
|
Packit Service |
bca4e3 |
{
|
|
Packit Service |
bca4e3 |
if (TAILQ_EMPTY(&fcfs) && TAILQ_EMPTY(&vn2vns)) {
|
|
Packit Service |
bca4e3 |
printf("No Fibre Channel Forwarders or VN2VN Responders Found\n");
|
|
Packit Service |
bca4e3 |
return ENODEV;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
if (!TAILQ_EMPTY(&fcfs)) {
|
|
Packit Service |
bca4e3 |
printf("Fibre Channel Forwarders Discovered\n");
|
|
Packit Service |
bca4e3 |
print_list(&fcfs, "FCF MAC");
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
if (!TAILQ_EMPTY(&vn2vns)) {
|
|
Packit Service |
bca4e3 |
printf("VN2VN Responders Discovered\n");
|
|
Packit Service |
bca4e3 |
print_list(&vn2vns, "VN2VN MAC");
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
return 0;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
static void recv_loop(int timeout)
|
|
Packit Service |
bca4e3 |
{
|
|
Packit Service |
bca4e3 |
int i;
|
|
Packit Service |
bca4e3 |
int rc;
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
while (1) {
|
|
Packit Service |
bca4e3 |
rc = poll(pfd, pfd_len, timeout);
|
|
Packit Service |
bca4e3 |
FIP_LOG_DBG("return from poll %d", rc);
|
|
Packit Service |
bca4e3 |
if (rc == 0) /* timeout */
|
|
Packit Service |
bca4e3 |
break;
|
|
Packit Service |
bca4e3 |
if (rc == -1) {
|
|
Packit Service |
bca4e3 |
FIP_LOG_ERRNO("poll error");
|
|
Packit Service |
bca4e3 |
break;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
/* pfd[0] must be the netlink socket */
|
|
Packit Service |
bca4e3 |
if (pfd[0].revents & POLLIN)
|
|
Packit Service |
bca4e3 |
rtnl_recv(pfd[0].fd, rtnl_listener_handler, NULL);
|
|
Packit Service |
bca4e3 |
/* everything else should be FIP packet sockets */
|
|
Packit Service |
bca4e3 |
for (i = 1; i < pfd_len; i++) {
|
|
Packit Service |
bca4e3 |
if (pfd[i].revents & POLLIN) {
|
|
Packit Service |
bca4e3 |
rc = fip_recv(pfd[i].fd, fip_vlan_handler,
|
|
Packit Service |
bca4e3 |
NULL);
|
|
Packit Service |
bca4e3 |
if (rc < 0)
|
|
Packit Service |
bca4e3 |
break;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
if (i < pfd_len)
|
|
Packit Service |
bca4e3 |
break;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
static void find_interfaces(int ns)
|
|
Packit Service |
bca4e3 |
{
|
|
Packit Service |
bca4e3 |
send_getlink_dump(ns);
|
|
Packit Service |
bca4e3 |
rtnl_recv(ns, rtnl_listener_handler, NULL);
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
static int probe_fip_interface(struct iff *iff)
|
|
Packit Service |
bca4e3 |
{
|
|
Packit Service |
bca4e3 |
int origdev = 1, rc;
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
if (iff->resp_recv)
|
|
Packit Service |
bca4e3 |
return 0;
|
|
Packit Service |
bca4e3 |
if (!iff->running) {
|
|
Packit Service |
bca4e3 |
if (iff->linkup_sent) {
|
|
Packit Service |
bca4e3 |
FIP_LOG_DBG("if %d not running, waiting for link up",
|
|
Packit Service |
bca4e3 |
iff->ifindex);
|
|
Packit Service |
bca4e3 |
} else {
|
|
Packit Service |
bca4e3 |
FIP_LOG_DBG("if %d not running, starting",
|
|
Packit Service |
bca4e3 |
iff->ifindex);
|
|
Packit Service |
bca4e3 |
rtnl_set_iff_up(iff->ifindex, NULL);
|
|
Packit Service |
bca4e3 |
iff->linkup_sent = true;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
iff->req_sent = false;
|
|
Packit Service |
bca4e3 |
return 1;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
if (iff->req_sent)
|
|
Packit Service |
bca4e3 |
return 0;
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
if (!iff->fip_ready) {
|
|
Packit Service |
bca4e3 |
iff->ps = fip_socket(iff->ifindex, iff->mac_addr, FIP_NONE);
|
|
Packit Service |
bca4e3 |
if (iff->ps < 0) {
|
|
Packit Service |
bca4e3 |
FIP_LOG_DBG("if %d not ready\n", iff->ifindex);
|
|
Packit Service |
bca4e3 |
return 0;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
setsockopt(iff->ps, SOL_PACKET, PACKET_ORIGDEV,
|
|
Packit Service |
bca4e3 |
&origdev, sizeof(origdev));
|
|
Packit Service |
bca4e3 |
pfd_add(iff->ps);
|
|
Packit Service |
bca4e3 |
iff->fip_ready = true;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
if (config.vn2vn)
|
|
Packit Service |
bca4e3 |
rc = fip_send_vlan_request(iff->ps, iff->ifindex,
|
|
Packit Service |
bca4e3 |
iff->mac_addr, FIP_ALL_VN2VN);
|
|
Packit Service |
bca4e3 |
else
|
|
Packit Service |
bca4e3 |
rc = fip_send_vlan_request(iff->ps, iff->ifindex,
|
|
Packit Service |
bca4e3 |
iff->mac_addr, FIP_ALL_FCF);
|
|
Packit Service |
bca4e3 |
if (rc == 0)
|
|
Packit Service |
bca4e3 |
iff->req_sent = true;
|
|
Packit Service |
bca4e3 |
return rc == 0 ? 0 : 1;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
static int send_vlan_requests(void)
|
|
Packit Service |
bca4e3 |
{
|
|
Packit Service |
bca4e3 |
struct iff *iff;
|
|
Packit Service |
bca4e3 |
int skipped = 0;
|
|
Packit Service |
bca4e3 |
int i;
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
if (config.automode) {
|
|
Packit Service |
bca4e3 |
TAILQ_FOREACH(iff, &interfaces, list_node) {
|
|
Packit Service |
bca4e3 |
skipped += probe_fip_interface(iff);
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
} else {
|
|
Packit Service |
bca4e3 |
for (i = 0; i < config.namec; i++) {
|
|
Packit Service |
bca4e3 |
iff = lookup_iff(0, config.namev[i]);
|
|
Packit Service |
bca4e3 |
if (!iff) {
|
|
Packit Service |
bca4e3 |
skipped++;
|
|
Packit Service |
bca4e3 |
continue;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
skipped += probe_fip_interface(iff);
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
return skipped;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
static void do_vlan_discovery(void)
|
|
Packit Service |
bca4e3 |
{
|
|
Packit Service |
bca4e3 |
struct iff *iff;
|
|
Packit Service |
bca4e3 |
int retry_count = 0;
|
|
Packit Service |
bca4e3 |
int skip_retry_count = 0;
|
|
Packit Service |
bca4e3 |
int skipped = 0, retry_iff = 0;
|
|
Packit Service |
bca4e3 |
retry:
|
|
Packit Service |
bca4e3 |
skipped += send_vlan_requests();
|
|
Packit Service |
bca4e3 |
if (skipped && skip_retry_count++ < config.link_retry) {
|
|
Packit Service |
bca4e3 |
FIP_LOG_DBG("waiting for IFF_RUNNING [%d/%d]\n",
|
|
Packit Service |
bca4e3 |
skip_retry_count, config.link_retry);
|
|
Packit Service |
bca4e3 |
recv_loop(500);
|
|
Packit Service |
bca4e3 |
skipped = 0;
|
|
Packit Service |
bca4e3 |
retry_count = 0;
|
|
Packit Service |
bca4e3 |
goto retry;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
recv_loop(200);
|
|
Packit Service |
bca4e3 |
TAILQ_FOREACH(iff, &interfaces, list_node) {
|
|
Packit Service |
bca4e3 |
if (!iff->fip_ready) {
|
|
Packit Service |
bca4e3 |
FIP_LOG_DBG("if %d: skipping, FIP not ready\n",
|
|
Packit Service |
bca4e3 |
iff->ifindex);
|
|
Packit Service |
bca4e3 |
continue;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
if (!iff->running && iff->linkup_sent) {
|
|
Packit Service |
bca4e3 |
FIP_LOG_DBG("if %d: waiting for IFF_RUNNING [%d]\n",
|
|
Packit Service |
bca4e3 |
iff->ifindex, retry_count);
|
|
Packit Service |
bca4e3 |
retry_iff++;
|
|
Packit Service |
bca4e3 |
continue;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
/* if we did not receive a response, retry */
|
|
Packit Service |
bca4e3 |
if (iff->req_sent && !iff->resp_recv) {
|
|
Packit Service |
bca4e3 |
FIP_LOG_DBG("if %d: VLAN discovery RETRY [%d]",
|
|
Packit Service |
bca4e3 |
iff->ifindex, retry_count);
|
|
Packit Service |
bca4e3 |
iff->req_sent = false;
|
|
Packit Service |
bca4e3 |
retry_iff++;
|
|
Packit Service |
bca4e3 |
continue;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
if (config.create) {
|
|
Packit Service |
bca4e3 |
struct iff *vlan;
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
TAILQ_FOREACH(vlan, &iff->vlans, list_node) {
|
|
Packit Service |
bca4e3 |
if (!vlan->running) {
|
|
Packit Service |
bca4e3 |
FIP_LOG_DBG("vlan %d: waiting for "
|
|
Packit Service |
bca4e3 |
"IFF_RUNNING [%d]",
|
|
Packit Service |
bca4e3 |
vlan->ifindex, retry_count);
|
|
Packit Service |
bca4e3 |
retry_iff++;
|
|
Packit Service |
bca4e3 |
continue;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
if (retry_iff && retry_count++ < config.link_retry) {
|
|
Packit Service |
bca4e3 |
recv_loop(1000);
|
|
Packit Service |
bca4e3 |
retry_iff = 0;
|
|
Packit Service |
bca4e3 |
goto retry;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
static void cleanup_interfaces(void)
|
|
Packit Service |
bca4e3 |
{
|
|
Packit Service |
bca4e3 |
struct iff *iff;
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
TAILQ_FOREACH(iff, &interfaces, list_node) {
|
|
Packit Service |
bca4e3 |
if (iff->linkup_sent) {
|
|
Packit Service |
bca4e3 |
if (config.link_up && iff->resp_recv)
|
|
Packit Service |
bca4e3 |
continue;
|
|
Packit Service |
bca4e3 |
if (iff->fcoe_started)
|
|
Packit Service |
bca4e3 |
continue;
|
|
Packit Service |
bca4e3 |
if (TAILQ_EMPTY(&iff->vlans)) {
|
|
Packit Service |
bca4e3 |
FIP_LOG_DBG("shutdown if %d",
|
|
Packit Service |
bca4e3 |
iff->ifindex);
|
|
Packit Service |
bca4e3 |
rtnl_set_iff_down(iff->ifindex, NULL);
|
|
Packit Service |
bca4e3 |
iff->linkup_sent = false;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
/* this is to not require headers from libcap */
|
|
Packit Service |
bca4e3 |
static inline int capget(cap_user_header_t hdrp, cap_user_data_t datap)
|
|
Packit Service |
bca4e3 |
{
|
|
Packit Service |
bca4e3 |
return syscall(__NR_capget, hdrp, datap);
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
static int checkcaps(void)
|
|
Packit Service |
bca4e3 |
{
|
|
Packit Service |
bca4e3 |
struct __user_cap_header_struct caphdr = {
|
|
Packit Service |
bca4e3 |
.version = _LINUX_CAPABILITY_VERSION_3,
|
|
Packit Service |
bca4e3 |
.pid = 0,
|
|
Packit Service |
bca4e3 |
};
|
|
Packit Service |
bca4e3 |
struct __user_cap_data_struct caps[_LINUX_CAPABILITY_U32S_3];
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
capget(&caphdr, caps);
|
|
Packit Service |
bca4e3 |
return !(caps[CAP_TO_INDEX(CAP_NET_RAW)].effective &
|
|
Packit Service |
bca4e3 |
CAP_TO_MASK(CAP_NET_RAW));
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
int main(int argc, char **argv)
|
|
Packit Service |
bca4e3 |
{
|
|
Packit Service |
bca4e3 |
int ns;
|
|
Packit Service |
bca4e3 |
int rc = 0;
|
|
Packit Service |
bca4e3 |
int find_cnt = 0;
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
exe = strrchr(argv[0], '/');
|
|
Packit Service |
bca4e3 |
if (exe)
|
|
Packit Service |
bca4e3 |
exe++;
|
|
Packit Service |
bca4e3 |
else
|
|
Packit Service |
bca4e3 |
exe = argv[0];
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
parse_cmdline(argc, argv);
|
|
Packit Service |
bca4e3 |
sa_log_prefix = exe;
|
|
Packit Service |
bca4e3 |
sa_log_flags = 0;
|
|
Packit Service |
bca4e3 |
enable_debug_log(config.debug);
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
if (checkcaps()) {
|
|
Packit Service |
bca4e3 |
FIP_LOG("must run as root or with the NET_RAW capability");
|
|
Packit Service |
bca4e3 |
exit(1);
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
ns = rtnl_socket(RTMGRP_LINK);
|
|
Packit Service |
bca4e3 |
if (ns < 0) {
|
|
Packit Service |
bca4e3 |
rc = 1;
|
|
Packit Service |
bca4e3 |
goto ns_err;
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
pfd_add(ns);
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
determine_libfcoe_interface();
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
find_interfaces(ns);
|
|
Packit Service |
bca4e3 |
if (config.automode)
|
|
Packit Service |
bca4e3 |
while ((TAILQ_EMPTY(&interfaces)) && ++find_cnt < 5) {
|
|
Packit Service |
bca4e3 |
FIP_LOG_DBG("no interfaces found, trying again");
|
|
Packit Service |
bca4e3 |
find_interfaces(ns);
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
if (TAILQ_EMPTY(&interfaces)) {
|
|
Packit Service |
bca4e3 |
if (config.automode)
|
|
Packit Service |
bca4e3 |
FIP_LOG_ERR(ENODEV,
|
|
Packit Service |
bca4e3 |
"no interfaces to perform discovery on");
|
|
Packit Service |
bca4e3 |
else
|
|
Packit Service |
bca4e3 |
FIP_LOG("no interfaces to perform discovery on");
|
|
Packit Service |
bca4e3 |
exit(ENODEV);
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
do_vlan_discovery();
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
rc = print_results();
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
cleanup_interfaces();
|
|
Packit Service |
bca4e3 |
|
|
Packit Service |
bca4e3 |
close(ns);
|
|
Packit Service |
bca4e3 |
ns_err:
|
|
Packit Service |
bca4e3 |
exit(rc);
|
|
Packit Service |
bca4e3 |
}
|
|
Packit Service |
bca4e3 |
|