summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLee Duncan <lduncan@suse.com>2021-09-02 12:21:00 -0700
committerGitHub <noreply@github.com>2021-09-02 12:21:00 -0700
commita42fff91d5f57447d13b6b02ec8c9db5bcb282e2 (patch)
tree275f4d84d6aa2f5fc86b656e5ed3cde008410ef9
parent0108f6800eb16f86bf512ba976ba3d1679349f5e (diff)
parent76350316de38abcd42afd3276249d577a0a66bec (diff)
downloadopen-iscsi-a42fff91d5f57447d13b6b02ec8c9db5bcb282e2.tar.gz
Merge pull request #272 from gonzoleeman/handle-ipv6-better
Handle ipv6 better
-rw-r--r--doc/iscsiadm.827
-rw-r--r--etc/iface.example11
-rw-r--r--include/iscsi_if.h7
-rw-r--r--libopeniscsiusr/idbm.c18
-rw-r--r--libopeniscsiusr/iface.c29
-rw-r--r--usr/iface.c67
-rw-r--r--usr/iface.h2
-rwxr-xr-xutils/iscsi_offload14
8 files changed, 123 insertions, 52 deletions
diff --git a/doc/iscsiadm.8 b/doc/iscsiadm.8
index 5fc6928..eea86d7 100644
--- a/doc/iscsiadm.8
+++ b/doc/iscsiadm.8
@@ -35,13 +35,12 @@ iscsiadm \- open-iscsi administration utility
.RB [ \-P
.IR printlevel ]
.RB [ \-I
-.IB iface\ \-t\ type\ \-p\ ip:port
-.RB [ \-l ]
-] | [
+.IR iface ]
+.RB [ \-t
+.IR type ]
.RB [ \-p
.IR ip:port ]
-.RB [ \-l | \-D ]
-]
+.RB [ \-l ]
.PP
.B iscsiadm
.B \-m node
@@ -473,6 +472,11 @@ Specify the \fIindex\fR of the entity to operate on.
This option is only valid for chap and flashnode submodes of host mode.
.SH DISCOVERY TYPES
iSCSI defines 3 discovery types: SendTargets, SLP, and iSNS.
+.PP
+A special discovery type called
+.I fw
+(for firmware) is also supported, for discoverying firmware interfaces,
+and populating the interface database in the process.
.TP
.B
SendTargets
@@ -494,6 +498,7 @@ optionally the port of the iSNS server to do discovery to.
.TP
.B
fw
+Firmware mode.
Several NICs and systems contain a mini iSCSI initiator which can be used
for boot. To get the values used for boot the fw option can be used.
Doing fw discovery, does not store persistent records in the node or
@@ -503,17 +508,9 @@ resource.
Performing fw discovery will print the portals, like with other discovery
methods. To see other settings like CHAP values and initiator settings,
like you would in node mode, run \fIiscsiadm \-m fw\fR.
-.IP
-fw support in open-iscsi is experimental. The settings and iscsiadm
-syntax and output format may change.
.P
-iscsiadm supports the
-.B
-iSNS (isns)
-or
-.B
-SendTargets (st)
-discovery type. An SLP implementation is under development.
+Note that the SLP implementation is under development and currently
+is not supported.
.SH EXIT STATUS
On success 0 is returned. On error one of the return codes below will
be returned.
diff --git a/etc/iface.example b/etc/iface.example
index 4b7f22c..17894cb 100644
--- a/etc/iface.example
+++ b/etc/iface.example
@@ -91,6 +91,13 @@
# example
# iface.vlan_state = enable
+#
+# The IPv6 attributes require the interface file
+# be named with the string "ipv6" in it. Otherwise,
+# parsing such a file will cause errors, since IPv4
+# is otherwise assumed.
+#
+
# OPTIONAL: iface.ipv6_linklocal
# Specify the IPV6 Link Local Address with the
# link local prefix of FE80::0/64
@@ -155,7 +162,7 @@
#
# IPV6 sample config file with neighbor discovery:
# BEGIN RECORD 2.0-872
-# iface.iscsi_ifacename = qla4xxx-3-1
+# iface.iscsi_ifacename = qla4xxx-3-1-ipv6
# iface.ipaddress =
# iface.hwaddress = 00:0e:1e:04:93:92
# iface.transport_name = qla4xxx
@@ -182,7 +189,7 @@
# Sample ipv6 config file(manual configured IPs):
# BEGIN RECORD 2.0-872
-# iface.iscsi_ifacename = iface-new-file
+# iface.iscsi_ifacename = iface-new-file-ipv6
# iface.ipaddress = fec0:ce00:7014:0041:1111:2222:1e04:9392
# iface.hwaddress = 00:0e:1e:04:93:92
# iface.transport_name = qla4xxx
diff --git a/include/iscsi_if.h b/include/iscsi_if.h
index 5a1c614..22b7c09 100644
--- a/include/iscsi_if.h
+++ b/include/iscsi_if.h
@@ -393,8 +393,11 @@ struct iscsi_path {
#define ISCSI_IPV6_ROUTER_AUTOCFG_ENABLE 0x01
#define ISCSI_IPV6_ROUTER_AUTOCFG_DISABLE 0x02
-#define ISCSI_IFACE_TYPE_IPV4 0x01
-#define ISCSI_IFACE_TYPE_IPV6 0x02
+/* Interface IP Type */
+enum iscsi_iface_type {
+ ISCSI_IFACE_TYPE_IPV4 = 1,
+ ISCSI_IFACE_TYPE_IPV6,
+};
#define ISCSI_MAX_VLAN_ID 4095
#define ISCSI_MAX_VLAN_PRIORITY 7
diff --git a/libopeniscsiusr/idbm.c b/libopeniscsiusr/idbm.c
index 0910c63..b2524ed 100644
--- a/libopeniscsiusr/idbm.c
+++ b/libopeniscsiusr/idbm.c
@@ -303,7 +303,7 @@ struct idbm_rec {
enum modify_mode can_modify;
};
-static void _idbm_node_rec_link(struct iscsi_node *node, struct idbm_rec *recs);
+static void _idbm_node_rec_link(struct iscsi_node *node, struct idbm_rec *recs, const char *iface_name);
int _idbm_lock(struct iscsi_context *ctx)
{
@@ -394,6 +394,10 @@ static int _idbm_iface_rec_link(struct iscsi_iface *iface,
struct idbm_rec *recs, int num)
{
int init_num = num;
+
+ if (strstr(iface->name, "ipv6"))
+ iface->is_ipv6 = true;
+
if (init_num == 0)
_rec_str(IFACE_ISCSINAME, recs, iface, name, IDBM_SHOW, num,
_CANNOT_MODIFY);
@@ -587,7 +591,7 @@ void _idbm_node_print(struct iscsi_node *node, FILE *f, bool show_secret)
if (recs == NULL)
return;
- _idbm_node_rec_link(node, recs);
+ _idbm_node_rec_link(node, recs, NULL);
_idbm_recs_print(recs, f, show_secret ? IDBM_SHOW : IDBM_MASKED);
_idbm_recs_free(recs);
}
@@ -977,7 +981,7 @@ static struct int_list_tbl chap_algs[] = {
{ "SHA3-256", ISCSI_AUTH_CHAP_ALG_SHA3_256 },
};
-static void _idbm_node_rec_link(struct iscsi_node *node, struct idbm_rec *recs)
+static void _idbm_node_rec_link(struct iscsi_node *node, struct idbm_rec *recs, const char *iface_name)
{
int num = 0;
@@ -990,6 +994,10 @@ static void _idbm_node_rec_link(struct iscsi_node *node, struct idbm_rec *recs)
_rec_bool(NODE_LEADING_LOGIN, recs, node, leading_login, IDBM_SHOW,
num, _CAN_MODIFY);
+ /* use the interface name passed in, if any */
+ if (iface_name)
+ strncpy((*node).iface.name, iface_name, ISCSI_MAX_IFACE_LEN);
+
/*
* Note: because we do not add the iface.iscsi_ifacename to
* sysfs iscsiadm does some weird matching. We can change the iface
@@ -1153,7 +1161,7 @@ int _idbm_node_get(struct iscsi_context *ctx, const char *target_name,
recs = _idbm_recs_alloc();
_alloc_null_check(ctx, recs, rc, out);
- _idbm_node_rec_link(*node, recs);
+ _idbm_node_rec_link(*node, recs, iface_name);
_good(_idbm_recs_read(ctx, recs, conf_path), rc, out);
@@ -1180,8 +1188,6 @@ int _idbm_node_get(struct iscsi_context *ctx, const char *target_name,
(*node)->conn.port);
}
-
-
out:
if (rc != LIBISCSI_OK) {
iscsi_node_free(*node);
diff --git a/libopeniscsiusr/iface.c b/libopeniscsiusr/iface.c
index 4d573fb..63f9c61 100644
--- a/libopeniscsiusr/iface.c
+++ b/libopeniscsiusr/iface.c
@@ -86,6 +86,29 @@ _iscsi_getter_func_gen(iscsi_iface, port_state, const char *);
_iscsi_getter_func_gen(iscsi_iface, port_speed, const char *);
_iscsi_getter_func_gen(iscsi_iface, name, const char *);
+/*
+ * ipv6 address strings will have at least two colons
+ *
+ * NOTE: does NOT validate the IP address
+ */
+static bool lib_ipaddr_is_ipv6(struct iscsi_context *ctx, char *ipaddr)
+{
+ char *first_colon, *second_colon;
+ bool res = false;
+
+ if (ipaddr) {
+ first_colon = strchr(ipaddr, ':');
+ if (first_colon) {
+ second_colon = strchr(first_colon+1, ':');
+ if (second_colon &&
+ (second_colon != first_colon))
+ res = true;
+ }
+ }
+ _debug(ctx, "ipaddr=\"%s\" -> %u", ipaddr, res);
+ return res;
+}
+
int _iscsi_iface_get_from_sysfs(struct iscsi_context *ctx, uint32_t host_id,
uint32_t sid, char *iface_kern_id,
struct iscsi_iface **iface)
@@ -203,8 +226,10 @@ int _iscsi_iface_get_from_sysfs(struct iscsi_context *ctx, uint32_t host_id,
if (bound_by_hwaddr)
snprintf((*iface)->name,
sizeof((*iface)->name)/sizeof(char),
- "%s.%s", (*iface)->transport_name,
- (*iface)->hwaddress);
+ "%s.%s.%s.%u", (*iface)->transport_name,
+ (*iface)->hwaddress,
+ lib_ipaddr_is_ipv6(ctx, (*iface)->ipaddress) ? "ipv6" : "ipv4",
+ (*iface)->iface_num);
}
if (strcmp((*iface)->name, "") == 0) {
diff --git a/usr/iface.c b/usr/iface.c
index 21d52b3..9db73c3 100644
--- a/usr/iface.c
+++ b/usr/iface.c
@@ -445,25 +445,34 @@ int iface_get_by_net_binding(struct iface_rec *pattern,
return ISCSI_ERR_NO_OBJS_FOUND;
}
-int iface_get_iptype(struct iface_rec *iface)
+/*
+ * detect IPv4 vs IPv4 IP address
+ */
+enum iscsi_iface_type iface_get_iptype(struct iface_rec *iface)
{
+ enum iscsi_iface_type res = ISCSI_IFACE_TYPE_IPV4;
+
/* address might not be set if user config with another tool */
if (!strlen(iface->ipaddress) ||
!strcmp(UNKNOWN_VALUE, iface->ipaddress)) {
- /* try to figure out by name */
- if (strstr(iface->name, "ipv4"))
- return ISCSI_IFACE_TYPE_IPV4;
- else if (strstr(iface->name, "ipv6"))
- return ISCSI_IFACE_TYPE_IPV6;
- else /* assume ipv4 by default */
- return ISCSI_IFACE_TYPE_IPV4;
+ /* unknown or empty IP address: try to figure out by name */
+ if (strstr(iface->name, "ipv6"))
+ res = ISCSI_IFACE_TYPE_IPV6;
} else {
+ /* figure out what type of IP address string we have */
if (strcmp(iface->bootproto, "dhcp") &&
- !strstr(iface->ipaddress, "."))
- return ISCSI_IFACE_TYPE_IPV6;
- else
- return ISCSI_IFACE_TYPE_IPV4;
+ !strchr(iface->ipaddress, '.')) {
+ /* bootproto is NOT "dhcp", IP addr does NOT have a dot in it */
+ res = ISCSI_IFACE_TYPE_IPV6;
+ }
}
+
+ log_debug(8, "iface: ipaddr=\"%s\" name=\"%s\" bootproto=\"%s\" -> %s",
+ iface->ipaddress, iface->name,
+ iface->bootproto,
+ res == ISCSI_IFACE_TYPE_IPV4 ? "IPv4" : "IPv6");
+
+ return res;
}
static int iface_setup_binding_from_kern_iface(void *data,
@@ -986,6 +995,30 @@ void iface_link_ifaces(struct list_head *ifaces)
iface_for_each_iface(ifaces, 1, &nr_found, iface_link);
}
+/*
+ * ipv6 address strings will have at least two colons
+ *
+ * NOTE: does NOT validate the IP address
+ */
+static bool ipaddr_is_ipv6(char *ipaddr)
+{
+ char *first_colon, *second_colon;
+ bool res = false;
+
+ if (ipaddr) {
+ first_colon = strchr(ipaddr, ':');
+ if (first_colon) {
+ second_colon = strchr(first_colon+1, ':');
+ if (second_colon &&
+ (second_colon != first_colon))
+ res = true;
+ }
+ }
+ log_debug(8, "%s(%s) -> %u",
+ __FUNCTION__, ipaddr, res);
+ return res;
+}
+
/**
* iface_setup_from_boot_context - setup iface from boot context info
* @iface: iface t setup
@@ -1059,9 +1092,6 @@ int iface_setup_from_boot_context(struct iface_rec *iface,
}
strcpy(iface->transport_name, t->name);
- memset(iface->name, 0, sizeof(iface->name));
- snprintf(iface->name, sizeof(iface->name), "%s.%s",
- iface->transport_name, context->mac);
strlcpy(iface->hwaddress, context->mac,
sizeof(iface->hwaddress));
strlcpy(iface->ipaddress, context->ipaddr,
@@ -1071,6 +1101,11 @@ int iface_setup_from_boot_context(struct iface_rec *iface,
sizeof(iface->subnet_mask));
strlcpy(iface->gateway, context->gateway,
sizeof(iface->gateway));
+ snprintf(iface->name, sizeof(iface->name), "%s.%s.%s.%u",
+ iface->transport_name, context->mac,
+ ipaddr_is_ipv6(iface->ipaddress) ? "ipv6" : "ipv4",
+ iface->iface_num);
+
log_debug(1, "iface " iface_fmt "", iface_str(iface));
return 1;
}
@@ -1211,7 +1246,7 @@ static void iface_get_common_param_count(struct iface_rec *iface, int *count)
static int __iface_get_param_count(void *data, struct iface_rec *iface)
{
struct iface_param_count *iface_params = data;
- int iptype = ISCSI_IFACE_TYPE_IPV4;
+ enum iscsi_iface_type iptype;
int count = 0;
if (strcmp(iface_params->primary->hwaddress, iface->hwaddress))
diff --git a/usr/iface.h b/usr/iface.h
index 6c06f7f..095772e 100644
--- a/usr/iface.h
+++ b/usr/iface.h
@@ -59,7 +59,7 @@ extern int iface_get_param_count(struct iface_rec *iface_primary,
int iface_all);
extern int iface_build_net_config(struct iface_rec *iface_primary,
int iface_all, struct iovec *iovs);
-extern int iface_get_iptype(struct iface_rec *iface);
+extern enum iscsi_iface_type iface_get_iptype(struct iface_rec *iface);
#define iface_fmt "[hw=%s,ip=%s,net_if=%s,iscsi_if=%s]"
#define iface_str(_iface) \
diff --git a/utils/iscsi_offload b/utils/iscsi_offload
index 833d26f..1869fe1 100755
--- a/utils/iscsi_offload
+++ b/utils/iscsi_offload
@@ -85,10 +85,11 @@ iscsi_macaddress_from_pcifn()
local h
local host
local ifmac
+ local olemacoffset=$3
ifmac=$(ip addr show dev $if | sed -n 's/ *link\/ether \(.*\) brd.*/\1/p')
m5=$(( 0x${ifmac##*:} ))
- m5=$(( $m5 + 1 ))
+ m5=$(( $m5 + $olemacoffset ))
ifmac=$(printf "%s:%02x" ${ifmac%:*} $m5)
for host in /sys/class/iscsi_host/host* ; do
if [ -L "$host" ] ; then
@@ -190,10 +191,7 @@ case "$driver" in
qla*)
mod=qla4xxx
;;
- qede)
- mod=qede
- ;;
- qedi)
+ qed*)
mod=qedi
;;
esac
@@ -221,11 +219,11 @@ if [ "$mod" = "bnx2i" ] ; then
elif [ "$mod" = "cxgb3i" ] ; then
mac=$(iscsi_macaddress_from_pcidevice $pcipath $IFNAME)
elif [ "$mod" = "be2iscsi" ] ; then
- mac=$(iscsi_macaddress_from_pcifn $pcipath $IFNAME)
+ mac=$(iscsi_macaddress_from_pcifn $pcipath $IFNAME 1)
elif [ "$mod" = "qla4xxx" ] ; then
- mac=$(iscsi_macaddress_from_pcifn $pcipath $IFNAME)
+ mac=$(iscsi_macaddress_from_pcifn $pcipath $IFNAME 1)
elif [ "$mod" = "qede" -o "$mod" = "qedi" ] ; then
- mac=$(iscsi_macaddress_from_pcifn $pcipath $IFNAME)
+ mac=$(iscsi_macaddress_from_pcifn $pcipath $IFNAME 4)
fi
if [ -z "$mac" ] ; then