iscsi-initiator-utils/iscsi-initiator-utils-sync-uio-0.7.4.3.patch
2012-10-10 13:00:03 -07:00

5691 lines
183 KiB
Diff

diff --git a/iscsiuio/README b/iscsiuio/README
index 5c36dec..a716263 100644
--- a/iscsiuio/README
+++ b/iscsiuio/README
@@ -1,6 +1,6 @@
-Iscsiuio Userspace Tool
-Version 0.7.2.1
-Mar 05, 2012
+iscsiuio Userspace Tool
+Version 0.7.4.3
+Aug 16, 2012
------------------------------------------------------
This tool is to be used in conjunction with the Broadcom NetXtreme II Linux
@@ -189,10 +189,11 @@ To run the daemon in debug mode please pass the parameter '-d <debug level>'
where the following debug levels are defined:
-DEBUG 4 - Print all messages
-INFO 3 - Print messages needed to follow the uIP code (default)
-WARN 2 - Print warning messages
-ERROR 1 - Only print critical errors
+PACKET 5 - Print all messages
+DEBUG 4 - Print debug messages
+INFO 3 - Print messages needed to follow the uIP code (default)
+WARN 2 - Print warning messages
+ERROR 1 - Only print critical errors
A sample banner message:
diff --git a/iscsiuio/RELEASE.TXT b/iscsiuio/RELEASE.TXT
index d4a00b6..cb1d470 100644
--- a/iscsiuio/RELEASE.TXT
+++ b/iscsiuio/RELEASE.TXT
@@ -1,7 +1,7 @@
Release Notes
Broadcom uIP Linux Driver
- Version 0.7.2.1
- 03/05/2012
+ Version 0.7.4.3
+ 08/16/2012
Broadcom Corporation
5300 California Avenue,
@@ -10,6 +10,228 @@
Copyright (c) 2004 - 2012 Broadcom Corporation
All rights reserved
+
+uIP v0.7.4.3 (Aug 16, 2012)
+=======================================================
+ Fixes
+ -----
+ 1. Problem: Cont00049383 - No mechanism in iface file to support
+ gateway/routing
+ Change: Added support for the additional network parameters
+ as passed from the newer iscsi-util.
+ These parameters include:
+ IPv4: subnet_mask, gateway
+ IPv6: ipv6_linklocal, ipv6_router,
+ ipv6_autocfg, linklocal_autocfg, router_autocfg
+ VLAN: vlan_id, vlan_priority, vlan_state
+ Other: mtu, port
+ Impact: All
+
+ 2. Problem: Cont00060806 - Unable to connect target using DHCP over
+ tagged VLAN
+ Change: DHCP+VLAN is a new feature enhancement that was added
+ alongside all other new iface parameters.
+ Impact: All
+
+ 3. Problem: Cont00061513 - Unable to connect to target over VLAN
+ interface
+ Cause: The VLAN id was not properly passed back to the CNIC
+ driver for the offload request
+ Change: Fixed the VLAN id being passed back to the CNIC driver
+ Impact: All
+
+ 4. Problem: Cont00061529 - Unable to connect to target after an
+ initial failed login attempt until iscsi service is
+ restarted
+ Cause: Upon a failed DHCPv4 acquisition due to the wrong VLAN
+ tag in the initial iface setup, any iscsid connect request
+ from the same NIC will get dropped due to a bug.
+ Change: Fixed the bug which prevented new iscsid connect requests
+ from getting honored
+ Impact: All
+
+ 5. Problem: Cont00061978 - Load/unload stress test fails
+ Cause: The bnx2x open request was failing due to the module
+ request procedure. However, the open failure was
+ not being handled correctly.
+ Change: Fixed the device open error handling
+ Impact: 5771X/578XX
+
+ 6. Problem: Cont00062170 - IPv6 login/logout stress fails
+ Cause: The packet buffer routine for IPv6 did not take
+ network order <-> host order into consideration
+ Change: Added a htons call to compensate for the ntohs pair
+ Impact: All
+
+ 7. Problem: Cont00061869 - Unable to setup an offload iSCSI
+ connection with FLR/NPAR under ESX5.0:PDA
+ Cause: The physical function ID was previously extracted
+ from the sysfs of the VM which might not be consistent
+ to the actual physical setup due to the function
+ remapping in the hypervisor
+ Change: Read the physical function ID directly from the BAR0
+ ME register
+ Impact: All
+
+ 8. Problem: Cont00062170 - IPv6 login/logout stress fails
+ Cause: The packet interrupt was lost after running the test
+ for a much longer period of time. A bug in the
+ packet processing routine was found to exit prematurely
+ Change: Fixed the packet processing routine to process all
+ packets before exiting
+ Impact: All
+
+ 9. Problem: Cont00062660 - Unable to login with VLAN iscsiuio
+ on RHEL6.2
+ Cause: The open-iscsi util in RHEL6.2 has a bug which
+ does not pass the correct iface_num to iscsiuio
+ Change: Added workaround to fall back to do the legacy
+ VLAN support if iface_num and vlan_id = 0
+ Impact: RHEL6.2
+
+ 10. Problem: Cont00062805 - Cannot login to iSCSI targets on RHEL6.3
+ Cause: The problem was caused by a change made to the iface_rec
+ structure in the RHEL6.3 inbox open-iscsi util
+ Change: The new changes is now incorporated
+ Impact: All
+
+ 11. Problem: Cont00062993 - IPv6 DHCP with VLAN specification in
+ iface file gets wrong address
+ Cause: The DHCPv6 request was using the same DUID as always
+ so the non-VLAN DHCP server responded to our broadcast
+ instead
+ Change: Changed the DHCPv6 request DUID to link address + time
+ instead of link address alone
+ Impact: DHCPv6 operation
+
+ 12. Problem: RHEL BZ 734010/804580 - issues found by the Coverity
+ scan
+ Cause: 10 code issues were flagged for revision
+ Change: Fixed all area of concern
+ Impact: All
+
+ 13. Problem: Cont00063177 - IPv4 DHCP with VLAN specification in
+ iface file gets wrong address
+ Cause: The DHCPv4 handler was not discriminating the VLAN tag
+ associated with the DHCP offers from multiple DHCP
+ servers
+ Change: Changed the DHCPv4 handler to drop DHCP offer packets
+ that doesn't match the VLAN tag of the intended DHCP
+ discovery packet
+ Impact: DHCPv4 operation
+
+ 14. Problem: Cont00063421 - Static IPv6 cannot connect via RA/LL
+ Cause: The router advertise and the linklocal address
+ were corrupted due to the override capabilities
+ added for the newer open-iscsi util
+ Change: Fixed the address override code
+ Impact: Static IPv6
+
+ 15. Problem: Cont00063443 - Compilation error on SLES11sp1
+ Cause: The iface_num field was not defined
+ Change: Fixed all references to iface_num
+ Impact: SLES11sp1
+
+ 16. Problem: Cont00063518 - HBA fails to connect across router
+ using iface.gateway address
+ Cause: The gateway override code did not populate the
+ address into the lower level engine
+ Change: Fixed the gateway override code
+ Impact: IPv4 Static IP operation
+
+ 17. Problem: Cont00063567 - IPv6 LL and RA override does not work
+ Cause: The IPv6 LL/RA override addresses were overwritten
+ by the NDP engine
+ Change: Fixed the LL/RA override code
+ Impact: IPv6 operation
+
+ 18. Problem: Cont00063626 - Static IPv6 does not connect when
+ the prefix len is not set explicitly
+ Cause: The IPv6 prefix length was not set correctly
+ for Static IPv6 operation when CIDR notation is
+ not specified
+ Change: Fixed the default prefix length
+ Impact: Static IPv6
+
+ 19. Problem: Cont00063651 - Cannot connect to iSCSI targets
+ HP PTM/SF
+ Cause: Switch-Dependent mode + invalid Outer VLAN was
+ not supported
+ Change: Allow SD+invalid OV to fallback to SF operation mode
+ Impact: 5771X/578XX
+
+ 20. Problem: Cont00063816 - The initiator is not able to connect
+ to the iSCSI targets over VLAN
+ Cause: The process packet routine did not consider the PCP
+ of the VLAN tag to be non-zero. This created a
+ mismatch when this VLAN tag was compared against the
+ nic_iface->vlan_id which doesn't include the PCP.
+ Change: Added the consideration of non-zero PCP
+ Impact: All
+
+ 21. Problem: Cont00063863 - can't boot into offload image
+ when VLAN is enabled
+ Cause: During the iSCSI login exchange, certain iSCSI targets
+ will send an ARP request even though the TCP connection
+ has been made. The bug was in this ARP reply where
+ the local MAC was corrupted when VLAN is enabled.
+ Change: Fixed the ARP reply packet
+ Impact: All
+
+ 22. Problem: Cont00063863 - can't boot into offload image
+ when VLAN is enabled
+ Cause: During the iSCSI login exchange, certain iSCSI targets
+ will send an ARP request even though the TCP connection
+ has been made. The bug was in this ARP reply where
+ the local MAC was corrupted when VLAN is enabled.
+ Change: Fixed the ARP reply packet
+ Impact: All
+
+ 23. Problem: Cont00064604 - Fails to connect to routed IPv6 target
+ via RA
+ Cause: The default router IPv6 address was not being retrieved
+ correctly.
+ Change: Fixed the default router IPv6 address read
+ Impact: All
+
+ 24. Problem: Cont00064665 - Linux iSCSI connects via gateway address
+ on the wrong subnet
+ Cause: The gateway address used was not checked against the
+ subnet mask specified before the ARP requests. Since
+ this behavior deters from how L2 operates, therefore,
+ a change was made to correct this.
+ Change: Added check of the gateway specified against the subnet
+ specified.
+ Impact: Static IPv4 operation
+
+ 25. Problem: Cont00064722 - Linux iSCSI unable to force IPv6 LL
+ override (advanced iface parameters)
+ Cause: The override LL address was not being populated to the
+ IPv6 address database correctly
+ Change: Added this correctly to the IPv6 initialization
+ Impact: Static/DHCP IPv6 LL address override only
+
+ Enhancements
+ ------------
+ 1. Lock iscsid's connect request with path_req so connect requests
+ with DHCP/Static will no longer override each other
+
+ 2. Fixed the if_down handler from global to nic specific
+
+ 3. Fixed various synchronization issues
+
+ 4. Updated README
+
+ 5. Added support for the new iface_num field in the iscsi_uevent
+ path
+
+ 6. Fixed bug in the nic_iface search engine based on iface_num
+
+ 7. Allow VLAN tag = 1 (router management) to connect offload
+
+ 8. Added support for jumbo MTU (independent from the L2 MTU)
+
+
uIP v0.7.2.1 (Mar 05, 2012)
=======================================================
Fixes
@@ -47,7 +269,7 @@ uIP v0.7.2.1 (Mar 05, 2012)
------------
1. Change: Default iscsiuio logging to off. Use the '-d'
option to enable
- 2. Change: Disable HP SD mode
+ 2. Change: Disable HP SD mode (NOT)
3. Change: Updated README
diff --git a/iscsiuio/configure b/iscsiuio/configure
index 4879fb9..6ff2e68 100644
--- a/iscsiuio/configure
+++ b/iscsiuio/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.59 for iscsiuio 0.7.2.1.
+# Generated by GNU Autoconf 2.59 for iscsiuio 0.7.4.3.
#
# Report bugs to <eddie.wai@broadcom.com>.
#
@@ -423,8 +423,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
# Identity of this package.
PACKAGE_NAME='iscsiuio'
PACKAGE_TARNAME='iscsiuio'
-PACKAGE_VERSION='0.7.2.1'
-PACKAGE_STRING='iscsiuio 0.7.2.1'
+PACKAGE_VERSION='0.7.4.3'
+PACKAGE_STRING='iscsiuio 0.7.4.3'
PACKAGE_BUGREPORT='eddie.wai@broadcom.com'
# Factoring default headers for most tests.
@@ -954,7 +954,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures iscsiuio 0.7.2.1 to adapt to many kinds of systems.
+\`configure' configures iscsiuio 0.7.4.3 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1020,7 +1020,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of iscsiuio 0.7.2.1:";;
+ short | recursive ) echo "Configuration of iscsiuio 0.7.4.3:";;
esac
cat <<\_ACEOF
@@ -1161,7 +1161,7 @@ fi
test -n "$ac_init_help" && exit 0
if $ac_init_version; then
cat <<\_ACEOF
-iscsiuio configure 0.7.2.1
+iscsiuio configure 0.7.4.3
generated by GNU Autoconf 2.59
Copyright (C) 2003 Free Software Foundation, Inc.
@@ -1175,7 +1175,7 @@ cat >&5 <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by iscsiuio $as_me 0.7.2.1, which was
+It was created by iscsiuio $as_me 0.7.4.3, which was
generated by GNU Autoconf 2.59. Invocation command line was
$ $0 $@
@@ -21726,7 +21726,7 @@ _ASBOX
} >&5
cat >&5 <<_CSEOF
-This file was extended by iscsiuio $as_me 0.7.2.1, which was
+This file was extended by iscsiuio $as_me 0.7.4.3, which was
generated by GNU Autoconf 2.59. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -21789,7 +21789,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF
ac_cs_version="\\
-iscsiuio config.status 0.7.2.1
+iscsiuio config.status 0.7.4.3
configured by $0, generated by GNU Autoconf 2.59,
with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
diff --git a/iscsiuio/configure.ac b/iscsiuio/configure.ac
index 3b7a880..0b1e7f1 100644
--- a/iscsiuio/configure.ac
+++ b/iscsiuio/configure.ac
@@ -1,6 +1,6 @@
dnl iscsiuio uIP user space stack configure.ac file
dnl
-dnl Copyright (c) 2004-2011 Broadcom Corporation
+dnl Copyright (c) 2004-2012 Broadcom Corporation
dnl
dnl This program is free software; you can redistribute it and/or modify
dnl it under the terms of the GNU General Public License as published by
@@ -11,9 +11,9 @@ dnl Maintained by: Eddie Wai (eddie.wai@broadcom.com)
dnl
PACKAGE=iscsiuio
-VERSION=0.7.2.1
+VERSION=0.7.4.3
-AC_INIT(iscsiuio, 0.7.2.1, eddie.wai@broadcom.com)
+AC_INIT(iscsiuio, 0.7.4.3, eddie.wai@broadcom.com)
AM_INIT_AUTOMAKE($PACKAGE, $VERSION)
AC_CONFIG_HEADER(config.h)
diff --git a/iscsiuio/docs/iscsiuio.8 b/iscsiuio/docs/iscsiuio.8
index 3307b1e..4bf26df 100644
--- a/iscsiuio/docs/iscsiuio.8
+++ b/iscsiuio/docs/iscsiuio.8
@@ -3,9 +3,9 @@
.\" modify it under the terms of the GNU General Public License as
.\" published by the Free Software Foundation.
.\"
-.\" bnx2.4,v 0.7.2.1
+.\" bnx2.4,v 0.7.4.3
.\"
-.TH iscsiuio 8 "03/05/2012" "Broadcom Corporation"
+.TH iscsiuio 8 "08/16/2012" "Broadcom Corporation"
.\"
.\" NAME part
.\"
diff --git a/iscsiuio/include/iscsi_if.h b/iscsiuio/include/iscsi_if.h
index a9ac145..1944abd 100644
--- a/iscsiuio/include/iscsi_if.h
+++ b/iscsiuio/include/iscsi_if.h
@@ -207,6 +207,7 @@ struct iscsi_uevent {
} ep_connect_ret;
struct msg_req_path {
uint32_t host_no;
+ uint32_t iface_num;
} req_path;
struct msg_notify_if_down {
uint32_t host_no;
@@ -234,6 +235,8 @@ struct iscsi_path {
struct in6_addr v6_addr;
} dst;
uint16_t vlan_id;
+#define IFACE_NUM_PRESENT (1<<0)
+#define IFACE_NUM_INVALID -1
uint16_t pmtu;
} __attribute__ ((aligned (sizeof(uint64_t))));
diff --git a/iscsiuio/src/apps/dhcpc/dhcpc.c b/iscsiuio/src/apps/dhcpc/dhcpc.c
index 88d75c3..afec601 100644
--- a/iscsiuio/src/apps/dhcpc/dhcpc.c
+++ b/iscsiuio/src/apps/dhcpc/dhcpc.c
@@ -334,7 +334,7 @@ static PT_THREAD(handle_dhcp(struct uip_stack *ustack))
(uint8_t *) s->mac_addr);
/* Put the stack thread back into a long sleep */
- s->nic->state |= NIC_LONG_SLEEP;
+ s->nic->flags |= NIC_LONG_SLEEP;
/* timer_stop(&s.timer); */
@@ -343,7 +343,7 @@ static PT_THREAD(handle_dhcp(struct uip_stack *ustack))
timer_set(&s->timer, s->ticks);
PT_WAIT_UNTIL(&s->pt, timer_expired(&s->timer));
LOG_INFO("Lease expired, re-acquire IP address");
- s->nic->state &= ~NIC_LONG_SLEEP;
+ s->nic->flags &= ~NIC_LONG_SLEEP;
PT_RESTART(&s->pt);
/*
@@ -397,7 +397,7 @@ int dhcpc_init(nic_t * nic, struct uip_stack *ustack,
ustack->dhcpc = s;
/* Let the RX poll value take over */
- nic->state &= ~NIC_LONG_SLEEP;
+ nic->flags &= ~NIC_LONG_SLEEP;
PT_INIT(&s->pt);
diff --git a/iscsiuio/src/apps/dhcpc/dhcpv6.c b/iscsiuio/src/apps/dhcpc/dhcpv6.c
index b7ae631..273cce0 100644
--- a/iscsiuio/src/apps/dhcpc/dhcpv6.c
+++ b/iscsiuio/src/apps/dhcpc/dhcpv6.c
@@ -86,10 +86,6 @@ int dhcpv6_do_discovery(pDHCPV6_CONTEXT dhcpv6_context)
(pIPV6_HDR) dhcpv6_context->ipv6_context->ustack->network_layer;
dhcpv6_context->udp =
(pUDP_HDR) ((u8_t *) dhcpv6_context->ipv6 + sizeof(IPV6_HDR));
- LOG_INFO("dhcpv6: ipv6c=%p, ustack=%p eth=%p ipv6=%p udp=%p",
- dhcpv6_context->ipv6_context,
- dhcpv6_context->ipv6_context->ustack, dhcpv6_context->eth,
- dhcpv6_context->ipv6, dhcpv6_context->udp);
/* Send out DHCPv6 Solicit packet. */
dhcpv6_send_solicit_packet(dhcpv6_context);
@@ -176,8 +172,10 @@ STATIC u16_t dhcpv6_init_packet(pDHCPV6_CONTEXT dhcpv6_context, u8_t type)
opt->hdr.type = HOST_TO_NET16(DHCPV6_OPT_CLIENTID);
opt->hdr.length = HOST_TO_NET16(sizeof(DHCPV6_OPT_CLIENT_ID));
opt->type.client_id.duid_type =
- HOST_TO_NET16(DHCPV6_DUID_TYPE_LINK_LAYER);
+ HOST_TO_NET16(DHCPV6_DUID_TYPE_LINK_LAYER_AND_TIME);
opt->type.client_id.hw_type = HOST_TO_NET16(DHCPV6_HW_TYPE_ETHERNET);
+ opt->type.client_id.time = HOST_TO_NET32(clock_time()/1000 -
+ 0x3A4FC880);
memcpy((char __FAR__ *)&opt->type.client_id.link_layer_addr,
(char __FAR__ *)dhcpv6_context->our_mac_addr, sizeof(MAC_ADDR));
pkt_len += sizeof(DHCPV6_OPT_CLIENT_ID) + sizeof(DHCPV6_OPT_HDR);
diff --git a/iscsiuio/src/apps/dhcpc/dhcpv6.h b/iscsiuio/src/apps/dhcpc/dhcpv6.h
index 917cf35..d8e03e5 100644
--- a/iscsiuio/src/apps/dhcpc/dhcpv6.h
+++ b/iscsiuio/src/apps/dhcpc/dhcpv6.h
@@ -164,7 +164,7 @@ typedef struct DHCPV6_OPT_CLIENT_ID {
#define DHCPV6_DUID_TYPE_LINK_LAYER 3
u16_t hw_type;
#define DHCPV6_HW_TYPE_ETHERNET 1
-// u32_t time;
+ u32_t time;
MAC_ADDR link_layer_addr;
} DHCPV6_OPT_CLIENT_ID, *pDHCPV6_OPT_CLIENT_ID;
diff --git a/iscsiuio/src/uip/ipv6.c b/iscsiuio/src/uip/ipv6.c
index 594495a..a8eed71 100644
--- a/iscsiuio/src/uip/ipv6.c
+++ b/iscsiuio/src/uip/ipv6.c
@@ -38,6 +38,7 @@
*/
#include <stdio.h>
#include <string.h>
+#include <arpa/inet.h>
#include "logger.h"
#include "uip.h"
#include "ipv6.h"
@@ -78,7 +79,7 @@ STATIC void ipv6_udp_rx(pIPV6_CONTEXT ipv6_context);
int iscsiL2Send(pIPV6_CONTEXT ipv6_context, int pkt_len)
{
- LOG_DEBUG("IPV6: iscsiL2Send");
+ LOG_DEBUG("IPv6: iscsiL2Send");
uip_send(ipv6_context->ustack,
(void *)ipv6_context->ustack->data_link_layer, pkt_len);
@@ -103,7 +104,8 @@ int iscsiL2AddMcAddr(pIPV6_CONTEXT ipv6_context, MAC_ADDR * new_mc_addr)
(char __FAR__ *)&all_zeroes_mc, sizeof(MAC_ADDR))) {
memcpy((char __FAR__ *)mc_addr,
(char __FAR__ *)new_mc_addr, sizeof(MAC_ADDR));
- LOG_DEBUG("IPV6: mc_addr added %x:%x:%x:%x:%x:%x",
+ LOG_DEBUG("IPv6: mc_addr added "
+ "%02x:%02x:%02x:%02x:%02x:%02x",
*(u8_t *) new_mc_addr,
*((u8_t *) new_mc_addr + 1),
*((u8_t *) new_mc_addr + 2),
@@ -150,10 +152,11 @@ void ipv6_init(struct ndpc_state *ndp, int cfg)
ipv6_arp_table = &ipv6_context->ipv6_arp_table[0];
ipv6_prefix_table = &ipv6_context->ipv6_prefix_table[0];
- memset((char __FAR__ *)ipv6_arp_table, 0, sizeof(ipv6_arp_table));
- memset((char __FAR__ *)ipv6_prefix_table, 0, sizeof(ipv6_prefix_table));
- memcpy((char __FAR__ *)&ipv6_context->mac_addr,
- (char __FAR__ *)mac_addr, sizeof(MAC_ADDR));
+ memset((char __FAR__*)ipv6_arp_table, 0, sizeof(*ipv6_arp_table));
+ memset((char __FAR__*)ipv6_prefix_table, 0,
+ sizeof(*ipv6_prefix_table));
+ memcpy((char __FAR__*)&ipv6_context->mac_addr,
+ (char __FAR__*)mac_addr, sizeof(MAC_ADDR));
/*
* Per RFC 2373.
* There are two types of local-use unicast addresses defined. These
@@ -167,33 +170,34 @@ void ipv6_init(struct ndpc_state *ndp, int cfg)
* |1111111010| 0 | interface ID |
* +----------+-------------------------+----------------------------+
*/
- ipv6_context->link_local_addr.addr8[0] = 0xfe;
- ipv6_context->link_local_addr.addr8[1] = 0x80;
- /* Bit 1 is 1 to indicate universal scope. */
- ipv6_context->link_local_addr.addr8[8] = mac_addr[0] | 0x2;
- ipv6_context->link_local_addr.addr8[9] = mac_addr[1];
- ipv6_context->link_local_addr.addr8[10] = mac_addr[2];
- ipv6_context->link_local_addr.addr8[11] = 0xff;
- ipv6_context->link_local_addr.addr8[12] = 0xfe;
- ipv6_context->link_local_addr.addr8[13] = mac_addr[3];
- ipv6_context->link_local_addr.addr8[14] = mac_addr[4];
- ipv6_context->link_local_addr.addr8[15] = mac_addr[5];
-
- ipv6_context->link_local_multi.addr8[0] = 0xff;
- ipv6_context->link_local_multi.addr8[1] = 0x02;
- ipv6_context->link_local_multi.addr8[11] = 0x01;
- ipv6_context->link_local_multi.addr8[12] = 0xff;
- ipv6_context->link_local_multi.addr8[13] |=
- ipv6_context->link_local_addr.addr8[13];
- ipv6_context->link_local_multi.addr16[7] =
- ipv6_context->link_local_addr.addr16[7];
-
- /* Default Prefix length is 64 */
- /* Add Link local address to the head of the ipv6 address
- list */
- ipv6_add_prefix_entry(ipv6_context,
- &ipv6_context->link_local_addr, 64);
-
+ if (ipv6_context->ustack->linklocal_autocfg != IPV6_LL_AUTOCFG_OFF) {
+ ipv6_context->link_local_addr.addr8[0] = 0xfe;
+ ipv6_context->link_local_addr.addr8[1] = 0x80;
+ /* Bit 1 is 1 to indicate universal scope. */
+ ipv6_context->link_local_addr.addr8[8] = mac_addr[0] | 0x2;
+ ipv6_context->link_local_addr.addr8[9] = mac_addr[1];
+ ipv6_context->link_local_addr.addr8[10] = mac_addr[2];
+ ipv6_context->link_local_addr.addr8[11] = 0xff;
+ ipv6_context->link_local_addr.addr8[12] = 0xfe;
+ ipv6_context->link_local_addr.addr8[13] = mac_addr[3];
+ ipv6_context->link_local_addr.addr8[14] = mac_addr[4];
+ ipv6_context->link_local_addr.addr8[15] = mac_addr[5];
+
+ ipv6_context->link_local_multi.addr8[0] = 0xff;
+ ipv6_context->link_local_multi.addr8[1] = 0x02;
+ ipv6_context->link_local_multi.addr8[11] = 0x01;
+ ipv6_context->link_local_multi.addr8[12] = 0xff;
+ ipv6_context->link_local_multi.addr8[13] |=
+ ipv6_context->link_local_addr.addr8[13];
+ ipv6_context->link_local_multi.addr16[7] =
+ ipv6_context->link_local_addr.addr16[7];
+
+ /* Default Prefix length is 64 */
+ /* Add Link local address to the head of the ipv6 address
+ list */
+ ipv6_add_prefix_entry(ipv6_context,
+ &ipv6_context->link_local_addr, 64);
+ }
/*
* Convert Multicast IP address to Multicast MAC adress per
* RFC 2464: Transmission of IPv6 Packets over Ethernet Networks
@@ -257,6 +261,7 @@ int ipv6_add_prefix_entry(pIPV6_CONTEXT ipv6_context,
int i;
pIPV6_PREFIX_ENTRY prefix_entry;
pIPV6_PREFIX_ENTRY ipv6_prefix_table = ipv6_context->ipv6_prefix_table;
+ char addr_str[INET6_ADDRSTRLEN];
/* Check if there is an valid entry already. */
for (i = 0; i < IPV6_NUM_OF_ADDRESS_ENTRY; i++) {
@@ -287,21 +292,13 @@ int ipv6_add_prefix_entry(pIPV6_CONTEXT ipv6_context,
prefix_entry->prefix_len = prefix_len / 8;
- memcpy((char __FAR__ *)&prefix_entry->address,
- (char __FAR__ *)ipv6_addr, sizeof(IPV6_ADDR));
-
-
- LOG_DEBUG("IPV6: add prefix ip addr "
- "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x "
- "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
- prefix_entry->address.addr8[0], prefix_entry->address.addr8[1],
- prefix_entry->address.addr8[2], prefix_entry->address.addr8[3],
- prefix_entry->address.addr8[4], prefix_entry->address.addr8[5],
- prefix_entry->address.addr8[6], prefix_entry->address.addr8[7],
- prefix_entry->address.addr8[8], prefix_entry->address.addr8[9],
- prefix_entry->address.addr8[10], prefix_entry->address.addr8[11],
- prefix_entry->address.addr8[12], prefix_entry->address.addr8[13],
- prefix_entry->address.addr8[14], prefix_entry->address.addr8[15]);
+ memcpy((char __FAR__*)&prefix_entry->address,
+ (char __FAR__*)ipv6_addr, sizeof(IPV6_ADDR));
+
+ inet_ntop(AF_INET6, &prefix_entry->address.addr8, addr_str,
+ sizeof(addr_str));
+
+ LOG_DEBUG("IPv6: add prefix IP addr %s", addr_str);
/* Put it on the list on head of the list. */
if (ipv6_context->addr_list != NULL) {
@@ -419,7 +416,7 @@ int ipv6_discover_address(pIPV6_CONTEXT ipv6_context)
sizeof(IPV6_ADDR));
icmp->icmpv6_cksum = 0;
- LOG_DEBUG("IPV6: Send rtr sol");
+ LOG_DEBUG("IPv6: Send rtr sol");
ipv6_send(ipv6_context, (u8_t *) icmp - (u8_t *) eth +
sizeof(ICMPV6_HDR) + sizeof(ICMPV6_OPT_LINK_ADDR));
return rc;
@@ -650,7 +647,7 @@ STATIC void ipv6_update_arp_table(pIPV6_CONTEXT ipv6_context,
int i;
pIPV6_ARP_ENTRY ipv6_arp_table = ipv6_context->ipv6_arp_table;
- LOG_DEBUG("IPV6: ARP update");
+ LOG_DEBUG("IPv6: Neighbor update");
/*
* Walk through the ARP mapping table and try to find an entry to
* update. If none is found, the IP -> MAC address mapping is
@@ -710,6 +707,7 @@ int ipv6_send_nd_solicited_packet(pIPV6_CONTEXT ipv6_context, pETH_HDR eth,
pICMPV6_HDR icmp;
int pkt_len = 0;
pIPV6_ADDR longest_match_addr;
+ char addr_str[INET6_ADDRSTRLEN];
ipv6->ipv6_nxt_hdr = IPPROTO_ICMPV6;
@@ -719,7 +717,7 @@ int ipv6_send_nd_solicited_packet(pIPV6_CONTEXT ipv6_context, pETH_HDR eth,
/* Use Link-local as source address */
if (ipv6_is_it_our_link_local_address(ipv6_context, &ipv6->ipv6_dst) ==
TRUE) {
- LOG_DEBUG("IPV6: NS using link local");
+ LOG_DEBUG("IPv6: NS using link local");
memcpy((char __FAR__ *)&ipv6->ipv6_src,
(char __FAR__ *)&ipv6_context->link_local_addr,
sizeof(IPV6_ADDR));
@@ -727,12 +725,12 @@ int ipv6_send_nd_solicited_packet(pIPV6_CONTEXT ipv6_context, pETH_HDR eth,
longest_match_addr =
ipv6_find_longest_match(ipv6_context, &ipv6->ipv6_dst);
if (longest_match_addr) {
- LOG_DEBUG("IPV6: NS using longest match addr");
+ LOG_DEBUG("IPv6: NS using longest match addr");
memcpy((char __FAR__ *)&ipv6->ipv6_src,
(char __FAR__ *)longest_match_addr,
sizeof(IPV6_ADDR));
} else {
- LOG_DEBUG("IPV6: NS using link local instead");
+ LOG_DEBUG("IPv6: NS using link local instead");
memcpy((char __FAR__ *)&ipv6->ipv6_src,
(char __FAR__ *)&ipv6_context->link_local_addr,
sizeof(IPV6_ADDR));
@@ -740,17 +738,8 @@ int ipv6_send_nd_solicited_packet(pIPV6_CONTEXT ipv6_context, pETH_HDR eth,
}
icmp = (pICMPV6_HDR) ((u8_t *) ipv6 + sizeof(IPV6_HDR));
- LOG_DEBUG
- ("IPV6: NS host ip addr %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x"
- " %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
- ipv6->ipv6_src.addr8[0], ipv6->ipv6_src.addr8[1],
- ipv6->ipv6_src.addr8[2], ipv6->ipv6_src.addr8[3],
- ipv6->ipv6_src.addr8[4], ipv6->ipv6_src.addr8[5],
- ipv6->ipv6_src.addr8[6], ipv6->ipv6_src.addr8[7],
- ipv6->ipv6_src.addr8[8], ipv6->ipv6_src.addr8[9],
- ipv6->ipv6_src.addr8[10], ipv6->ipv6_src.addr8[11],
- ipv6->ipv6_src.addr8[12], ipv6->ipv6_src.addr8[13],
- ipv6->ipv6_src.addr8[14], ipv6->ipv6_src.addr8[15]);
+ inet_ntop(AF_INET6, &ipv6->ipv6_src.addr8, addr_str, sizeof(addr_str));
+ LOG_DEBUG("IPv6: NS host IP addr: %s", addr_str);
/*
* Destination IP address to be resolved is after the ICMPv6
* header.
@@ -839,6 +828,7 @@ STATIC void ipv6_icmp_handle_router_adv(pIPV6_CONTEXT ipv6_context)
pICMPV6_OPT_HDR icmp_opt;
u16_t opt_len;
u16_t len;
+ char addr_str[INET6_ADDRSTRLEN];
if (ipv6_context->flags & IPV6_FLAGS_ROUTER_ADV_RECEIVED)
return;
@@ -868,7 +858,7 @@ STATIC void ipv6_icmp_handle_router_adv(pIPV6_CONTEXT ipv6_context)
}
if (ipv6_context->flags & IPV6_FLAGS_ROUTER_ADV_RECEIVED) {
- LOG_DEBUG("IPV6: RTR ADV nd_ra_flags=0x%x",
+ LOG_DEBUG("IPv6: RTR ADV nd_ra_flags = 0x%x",
icmp->nd_ra_flags_reserved);
if (icmp->nd_ra_curhoplimit > 0)
ipv6_context->hop_limit = icmp->nd_ra_curhoplimit;
@@ -880,21 +870,17 @@ STATIC void ipv6_icmp_handle_router_adv(pIPV6_CONTEXT ipv6_context)
ipv6_context->flags |= IPV6_FLAGS_OTHER_STATEFUL_CONFIG;
if (icmp->nd_ra_router_lifetime != 0) {
- /* This is a default router. */
- memcpy((char __FAR__ *)&ipv6_context->default_router,
- (char __FAR__ *)&ipv6->ipv6_src,
- sizeof(IPV6_ADDR));
- LOG_DEBUG("IPV6: def router "
- "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x "
- "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
- ipv6->ipv6_src.addr8[0], ipv6->ipv6_src.addr8[1],
- ipv6->ipv6_src.addr8[2], ipv6->ipv6_src.addr8[3],
- ipv6->ipv6_src.addr8[4], ipv6->ipv6_src.addr8[5],
- ipv6->ipv6_src.addr8[6], ipv6->ipv6_src.addr8[7],
- ipv6->ipv6_src.addr8[8], ipv6->ipv6_src.addr8[9],
- ipv6->ipv6_src.addr8[10], ipv6->ipv6_src.addr8[11],
- ipv6->ipv6_src.addr8[12], ipv6->ipv6_src.addr8[13],
- ipv6->ipv6_src.addr8[14], ipv6->ipv6_src.addr8[15]);
+ /* There is a default router. */
+ if (ipv6_context->ustack->router_autocfg !=
+ IPV6_RTR_AUTOCFG_OFF)
+ memcpy(
+ (char __FAR__*)&ipv6_context->default_router,
+ (char __FAR__*)&ipv6->ipv6_src,
+ sizeof(IPV6_ADDR));
+ inet_ntop(AF_INET6, &ipv6_context->default_router,
+ addr_str, sizeof(addr_str));
+ LOG_DEBUG("IPV6: Got default router IP addr: %s",
+ addr_str);
}
}
}
@@ -903,6 +889,7 @@ STATIC void ipv6_icmp_process_prefix(pIPV6_CONTEXT ipv6_context,
pICMPV6_OPT_PREFIX icmp_prefix)
{
IPV6_ADDR addr;
+ char addr_str[INET6_ADDRSTRLEN];
/* we only process on-link address info */
if (!(icmp_prefix->flags & ICMPV6_OPT_PREFIX_FLAG_ON_LINK))
@@ -917,6 +904,8 @@ STATIC void ipv6_icmp_process_prefix(pIPV6_CONTEXT ipv6_context,
(char __FAR__ *)&icmp_prefix->prefix, 8);
memcpy((char __FAR__ *)&addr.addr8[8],
&ipv6_context->link_local_addr.addr8[8], 8);
+ inet_ntop(AF_INET6, &addr, addr_str, sizeof(addr_str));
+ LOG_DEBUG("IPv6: Got RA ICMP option IP addr: %s", addr_str);
ipv6_add_prefix_entry(ipv6_context, &addr, 64);
}
}
@@ -929,11 +918,12 @@ STATIC void ipv6_icmp_handle_nd_adv(pIPV6_CONTEXT ipv6_context)
pICMPV6_OPT_LINK_ADDR link_opt = (pICMPV6_OPT_LINK_ADDR)((u8_t *)icmp +
sizeof(ICMPV6_HDR) + sizeof(IPV6_ADDR));
pIPV6_ADDR tar_addr6;
+ char addr_str[INET6_ADDRSTRLEN];
/* Added the multicast check for ARP table update */
/* Should we qualify for only our host's multicast and our
link_local_multicast?? */
- LOG_DEBUG("IPV6: Handle nd adv");
+ LOG_DEBUG("IPv6: Handle nd adv");
if ((ipv6_is_it_our_address(ipv6_context, &ipv6->ipv6_dst) == TRUE) ||
(memcmp((char __FAR__ *)&ipv6_context->link_local_multi,
(char __FAR__ *)&ipv6->ipv6_dst, sizeof(IPV6_ADDR)) == 0) ||
@@ -951,21 +941,14 @@ STATIC void ipv6_icmp_handle_nd_adv(pIPV6_CONTEXT ipv6_context)
if (link_opt->hdr.type == IPV6_ICMP_OPTION_TAR_ADDR) {
tar_addr6 = (pIPV6_ADDR)((u8_t *)icmp +
sizeof(ICMPV6_HDR));
- LOG_DEBUG("IPV6: tar mac %x:%x:%x:%x:%x:%x",
+ LOG_DEBUG("IPV6: Target MAC "
+ "%02x:%02x:%02x:%02x:%02x:%02x",
link_opt->link_addr[0], link_opt->link_addr[1],
link_opt->link_addr[2], link_opt->link_addr[3],
link_opt->link_addr[4], link_opt->link_addr[5]);
- LOG_DEBUG("IPV6: tar addr "
- "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x "
- "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
- tar_addr6->addr8[0], tar_addr6->addr8[1],
- tar_addr6->addr8[2], tar_addr6->addr8[3],
- tar_addr6->addr8[4], tar_addr6->addr8[5],
- tar_addr6->addr8[6], tar_addr6->addr8[7],
- tar_addr6->addr8[8], tar_addr6->addr8[9],
- tar_addr6->addr8[10], tar_addr6->addr8[11],
- tar_addr6->addr8[12], tar_addr6->addr8[13],
- tar_addr6->addr8[14], tar_addr6->addr8[15]);
+ inet_ntop(AF_INET6, &tar_addr6->addr8, addr_str,
+ sizeof(addr_str));
+ LOG_DEBUG("IPv6: Target IP addr %s", addr_str);
ipv6_update_arp_table(ipv6_context, tar_addr6,
(MAC_ADDR *)link_opt->link_addr);
}
@@ -985,14 +968,15 @@ STATIC void ipv6_icmp_handle_nd_sol(pIPV6_CONTEXT ipv6_context)
pIPV6_ADDR longest_match_addr;
pIPV6_ADDR tar_addr6;
- LOG_DEBUG("IPV6: Handle nd sol");
+ LOG_DEBUG("IPv6: Handle nd sol");
if ((memcmp((char __FAR__ *)&ipv6_context->mac_addr,
(char __FAR__ *)eth->dest_mac, sizeof(MAC_ADDR)) != 0) &&
(iscsiL2IsOurMcAddr(ipv6_context, (pMAC_ADDRESS) & eth->dest_mac) ==
FALSE)) {
/* This packet is not for us to handle */
- LOG_DEBUG("IPV6: MAC not addressed to us %x:%x:%x:%x:%x:%x",
+ LOG_DEBUG("IPv6: MAC not addressed to us "
+ "%02x:%02x:%02x:%02x:%02x:%02x",
eth->dest_mac[0], eth->dest_mac[1],
eth->dest_mac[2], eth->dest_mac[3],
eth->dest_mac[4], eth->dest_mac[5]);
@@ -1005,7 +989,7 @@ STATIC void ipv6_icmp_handle_nd_sol(pIPV6_CONTEXT ipv6_context)
sizeof(ICMPV6_HDR)))
== FALSE) {
/* This packet is not for us to handle */
- LOG_DEBUG("IPV6: IP not addressed to us");
+ LOG_DEBUG("IPv6: IP not addressed to us");
return;
}
@@ -1026,7 +1010,7 @@ STATIC void ipv6_icmp_handle_nd_sol(pIPV6_CONTEXT ipv6_context)
tar_addr6 = (pIPV6_ADDR)((u8_t *)icmp + sizeof(ICMPV6_HDR));
if (ipv6_is_it_our_link_local_address(ipv6_context, tar_addr6)
== TRUE) {
- LOG_DEBUG("IPV6: NA using link local");
+ LOG_DEBUG("IPv6: NA using link local");
memcpy((char __FAR__ *)&ipv6->ipv6_src,
(char __FAR__ *)&ipv6_context->link_local_addr,
sizeof(IPV6_ADDR));
@@ -1034,12 +1018,12 @@ STATIC void ipv6_icmp_handle_nd_sol(pIPV6_CONTEXT ipv6_context)
longest_match_addr =
ipv6_find_longest_match(ipv6_context, tar_addr6);
if (longest_match_addr) {
- LOG_DEBUG("IPV6: NA using longest match addr");
+ LOG_DEBUG("IPv6: NA using longest match addr");
memcpy((char __FAR__ *)&ipv6->ipv6_src,
(char __FAR__ *)longest_match_addr,
sizeof(IPV6_ADDR));
} else {
- LOG_DEBUG("IPV6: NA using link local instead");
+ LOG_DEBUG("IPv6: NA using link local instead");
memcpy((char __FAR__ *)&ipv6->ipv6_src,
(char __FAR__ *)&ipv6_context->link_local_addr,
sizeof(IPV6_ADDR));
@@ -1047,7 +1031,7 @@ STATIC void ipv6_icmp_handle_nd_sol(pIPV6_CONTEXT ipv6_context)
}
} else {
/* No target link address, just use whatever it sent to us */
- LOG_DEBUG("IPV6: NA use dst addr");
+ LOG_DEBUG("IPv6: NA use dst addr");
memcpy((char __FAR__ *)&ipv6->ipv6_src,
(char __FAR__ *)&tmp,
sizeof(IPV6_ADDR));
@@ -1085,7 +1069,7 @@ STATIC void ipv6_icmp_handle_nd_sol(pIPV6_CONTEXT ipv6_context)
*/
ipv6->ipv6_plen = HOST_TO_NET16((sizeof(ICMPV6_HDR) +
icmpv6_opt_len + sizeof(IPV6_ADDR)));
- LOG_DEBUG("IPV6: Send nd adv");
+ LOG_DEBUG("IPv6: Send nd adv");
ipv6_send(ipv6_context,
(u8_t *) icmp - (u8_t *) eth +
sizeof(ICMPV6_HDR) +
@@ -1118,7 +1102,7 @@ STATIC void ipv6_icmp_handle_echo_request(pIPV6_CONTEXT ipv6_context)
icmp->icmpv6_type = ICMPV6_ECHO_REPLY;
icmp->icmpv6_code = 0;
icmp->icmpv6_cksum = 0;
- LOG_DEBUG("IPV6: Send echo reply");
+ LOG_DEBUG("IPv6: Send echo reply");
ipv6_send(ipv6_context, (u8_t *) icmp - (u8_t *) eth +
sizeof(IPV6_HDR) + HOST_TO_NET16(ipv6->ipv6_plen));
return;
@@ -1126,7 +1110,8 @@ STATIC void ipv6_icmp_handle_echo_request(pIPV6_CONTEXT ipv6_context)
void ipv6_set_ip_params(pIPV6_CONTEXT ipv6_context,
pIPV6_ADDR src_ip, u8_t prefix_len,
- pIPV6_ADDR default_gateway)
+ pIPV6_ADDR default_gateway,
+ pIPV6_ADDR linklocal)
{
if (!(IPV6_IS_ADDR_UNSPECIFIED(src_ip))) {
ipv6_add_prefix_entry(ipv6_context, src_ip, prefix_len);
@@ -1146,9 +1131,30 @@ void ipv6_set_ip_params(pIPV6_CONTEXT ipv6_context,
}
if (!(IPV6_IS_ADDR_UNSPECIFIED(default_gateway))) {
- /* This is a default router. */
- memcpy((char __FAR__ *)&ipv6_context->default_router,
- (char __FAR__ *)default_gateway, sizeof(IPV6_ADDR));
+ /* Override the default gateway addr */
+ memcpy((char __FAR__*)&ipv6_context->default_router,
+ (char __FAR__*)default_gateway, sizeof(IPV6_ADDR));
+ ipv6_add_prefix_entry(ipv6_context, default_gateway,
+ prefix_len);
+ }
+ if (!(IPV6_IS_ADDR_UNSPECIFIED(linklocal))) {
+ /* Override the linklocal addr */
+ memcpy((char __FAR__*)&ipv6_context->link_local_addr,
+ (char __FAR__*)linklocal, sizeof(IPV6_ADDR));
+ ipv6_context->link_local_multi.addr8[0] = 0xff;
+ ipv6_context->link_local_multi.addr8[1] = 0x02;
+ ipv6_context->link_local_multi.addr8[11] = 0x01;
+ ipv6_context->link_local_multi.addr8[12] = 0xff;
+ ipv6_context->link_local_multi.addr8[13] |=
+ ipv6_context->link_local_addr.addr8[13];
+ ipv6_context->link_local_multi.addr16[7] =
+ ipv6_context->link_local_addr.addr16[7];
+
+ /* Default Prefix length is 64 */
+ /* Add Link local address to the head of the ipv6 address
+ list */
+ ipv6_add_prefix_entry(ipv6_context,
+ &ipv6_context->link_local_addr, 64);
}
}
@@ -1220,7 +1226,7 @@ u16_t ipv6_do_stateful_dhcpv6(pIPV6_CONTEXT ipv6_context, u32_t flags)
(IPV6_FLAGS_MANAGED_ADDR_CONFIG | IPV6_FLAGS_OTHER_STATEFUL_CONFIG);
if (!(ipv6_context->flags & IPV6_FLAGS_ROUTER_ADV_RECEIVED)) {
- LOG_DEBUG("IPV6: There is no IPv6 router on the network");
+ LOG_DEBUG("IPv6: There is no IPv6 router on the network");
ra_flags |=
(IPV6_FLAGS_MANAGED_ADDR_CONFIG |
IPV6_FLAGS_OTHER_STATEFUL_CONFIG);
@@ -1234,7 +1240,7 @@ u16_t ipv6_do_stateful_dhcpv6(pIPV6_CONTEXT ipv6_context, u32_t flags)
(ra_flags & IPV6_FLAGS_OTHER_STATEFUL_CONFIG))
task |= DHCPV6_TASK_GET_OTHER_PARAMS;
- LOG_DEBUG("IPV6: Stateful flags=0x%x, ra_flags=0x%x, task=0x%x", flags,
+ LOG_DEBUG("IPv6: Stateful flags=0x%x, ra_flags=0x%x, task=0x%x", flags,
ra_flags, task);
return task;
diff --git a/iscsiuio/src/uip/ipv6.h b/iscsiuio/src/uip/ipv6.h
index 167f5f6..ed2f3a4 100644
--- a/iscsiuio/src/uip/ipv6.h
+++ b/iscsiuio/src/uip/ipv6.h
@@ -343,7 +343,8 @@ int ipv6_add_prefix_entry(pIPV6_CONTEXT ipv6_context,
IPV6_ADDR * ipv6_addr, u8_t prefix_len);
void ipv6_set_ip_params(pIPV6_CONTEXT ipv6_context,
pIPV6_ADDR src_ip, u8_t prefix_len,
- pIPV6_ADDR default_gateway);
+ pIPV6_ADDR default_gateway,
+ pIPV6_ADDR linklocal);
void ipv6_set_host_addr(pIPV6_CONTEXT ipv6_context, pIPV6_ADDR src_ip);
int ipv6_get_default_router_ip_addrs(pIPV6_CONTEXT ipv6_context,
pIPV6_ADDR ip_addr);
diff --git a/iscsiuio/src/uip/ipv6_ndpc.c b/iscsiuio/src/uip/ipv6_ndpc.c
index 6d101ce..89dbd5e 100644
--- a/iscsiuio/src/uip/ipv6_ndpc.c
+++ b/iscsiuio/src/uip/ipv6_ndpc.c
@@ -65,6 +65,7 @@ static PT_THREAD(handle_ndp(struct uip_stack *ustack, int force))
pIPV6_CONTEXT ipv6c;
pDHCPV6_CONTEXT dhcpv6c = NULL;
u16_t task = 0;
+ char buf[INET6_ADDRSTRLEN];
s = ustack->ndpc;
if (s == NULL) {
@@ -86,6 +87,9 @@ static PT_THREAD(handle_ndp(struct uip_stack *ustack, int force))
if (s->state == NDPC_STATE_RTR_ADV)
goto rtr_adv;
+ /* For AUTOCFG == DHCPv6, do all
+ For == ND, skip DHCP only and do RTR
+ For == UNUSED/UNSPEC, do all as according to DHCP or not */
s->state = NDPC_STATE_RTR_SOL;
/* try_again: */
s->ticks = CLOCK_SECOND * IPV6_MAX_ROUTER_SOL_DELAY;
@@ -97,7 +101,7 @@ static PT_THREAD(handle_ndp(struct uip_stack *ustack, int force))
ipv6_autoconfig(s->ipv6_context);
timer_set(&s->timer, s->ticks);
- wait_rtr:
+wait_rtr:
s->ustack->uip_flags &= ~UIP_NEWDATA;
LOG_DEBUG("%s: ndpc_handle wait for rtr adv flags=0x%x",
s->nic->log_name, ipv6c->flags);
@@ -134,10 +138,12 @@ no_rtr_adv:
s->state = NDPC_STATE_RTR_ADV;
rtr_adv:
- /* Both Static IPv6 and DHCPv6 comes here */
+ if (!(ustack->ip_config & IPV6_CONFIG_DHCP))
+ goto staticv6;
+ /* Only DHCPv6 comes here */
task = ipv6_do_stateful_dhcpv6(ipv6c, ISCSI_FLAGS_DHCP_TCPIP_CONFIG);
- if (task && (ustack->ip_config == IPV6_CONFIG_DHCP)) {
+ if (task) {
/* Run the DHCPv6 engine */
if (!dhcpv6c)
@@ -187,6 +193,7 @@ wait_dhcp:
}
} while (dhcpv6c->dhcpv6_done == FALSE);
s->state = NDPC_STATE_DHCPV6_DONE;
+
LOG_DEBUG("%s: ndpc_handle got dhcpv6", s->nic->log_name);
/* End of DHCPv6 engine */
@@ -197,28 +204,25 @@ wait_dhcp:
s->nic->log_name);
PT_RESTART(&s->pt);
}
- IPV6_ADDR tmp, tmp2;
- char buf[INET6_ADDRSTRLEN];
-
+staticv6:
ipv6_disable_dhcpv6(ipv6c);
- memcpy(&tmp.addr8, &ustack->hostaddr6, sizeof(IPV6_ADDR));
- LOG_DEBUG("%s: host ip addr %02x:%02x:%02x:%02x:%02x:%02x:"
- "%02x:%02x", s->nic->log_name,
- ustack->hostaddr6[0], ustack->hostaddr6[1],
- ustack->hostaddr6[2], ustack->hostaddr6[3],
- ustack->hostaddr6[4], ustack->hostaddr6[5],
- ustack->hostaddr6[6], ustack->hostaddr6[7]);
- memset(&tmp2, 0, sizeof(tmp2));
- ipv6_set_ip_params(ipv6c, &tmp,
- ustack->prefix_len, &tmp2);
-
- ipv6_add_solit_node_address(ipv6c, &tmp);
-
- inet_ntop(AF_INET6, &tmp.addr8, buf, sizeof(buf));
- LOG_INFO("%s: Static hostaddr IP: %s", s->nic->log_name,
- buf);
-
}
+ /* Copy out the default_router_addr6 and ll */
+ if (ustack->router_autocfg != IPV6_RTR_AUTOCFG_OFF)
+ memcpy(&ustack->default_route_addr6,
+ &ipv6c->default_router, sizeof(IPV6_ADDR));
+ inet_ntop(AF_INET6, &ustack->default_route_addr6,
+ buf, sizeof(buf));
+ LOG_INFO("%s: Default router IP: %s", s->nic->log_name,
+ buf);
+
+ if (ustack->linklocal_autocfg != IPV6_LL_AUTOCFG_OFF)
+ memcpy(&ustack->linklocal6, &ipv6c->link_local_addr,
+ sizeof(IPV6_ADDR));
+ inet_ntop(AF_INET6, &ustack->linklocal6,
+ buf, sizeof(buf));
+ LOG_INFO("%s: Linklocal IP: %s", s->nic->log_name,
+ buf);
ipv6_loop:
s->state = NDPC_STATE_BACKGROUND_LOOP;
@@ -249,6 +253,8 @@ int ndpc_init(nic_t * nic, struct uip_stack *ustack,
pIPV6_CONTEXT ipv6c;
pDHCPV6_CONTEXT dhcpv6c;
struct ndpc_state *s = ustack->ndpc;
+ IPV6_ADDR src, gw, ll;
+ char buf[INET6_ADDRSTRLEN];
if (s) {
LOG_DEBUG("NDP: NDP context already allocated");
@@ -315,9 +321,30 @@ init2:
if (ustack->ip_config == IPV6_CONFIG_DHCP) {
/* DHCPv6 specific */
+ memset(&src, 0, sizeof(src));
} else {
/* Static v6 specific */
+ memcpy(&src.addr8, &ustack->hostaddr6, sizeof(IPV6_ADDR));
+ ipv6_add_solit_node_address(ipv6c, &src);
+
+ inet_ntop(AF_INET6, &src.addr8, buf, sizeof(buf));
+ LOG_INFO("%s: Static hostaddr IP: %s", s->nic->log_name,
+ buf);
}
+ /* Copy out the default_router_addr6 and ll */
+ if (ustack->router_autocfg == IPV6_RTR_AUTOCFG_OFF)
+ memcpy(&gw.addr8, &ustack->default_route_addr6,
+ sizeof(IPV6_ADDR));
+ else
+ memset(&gw, 0, sizeof(gw));
+
+ if (ustack->linklocal_autocfg == IPV6_LL_AUTOCFG_OFF)
+ memcpy(&ll.addr8, &ustack->linklocal6,
+ sizeof(IPV6_ADDR));
+ else
+ memset(&ll, 0, sizeof(ll));
+ ipv6_set_ip_params(ipv6c, &src,
+ ustack->prefix_len, &gw, &ll);
return 0;
error2:
@@ -367,16 +394,14 @@ int ndpc_request(struct uip_stack *ustack, void *in, void *out, int request)
//LOG_DEBUG("%s: NDP - Request %d", s->nic->log_name, request);
while (s->state != NDPC_STATE_BACKGROUND_LOOP) {
- LOG_DEBUG("%s: ndpc state not in background loop, run handler",
- s->nic->log_name);
+ LOG_DEBUG("%s: ndpc state not in background loop, run handler ",
+ "request = %d", s->nic->log_name, request);
handle_ndp(ustack, 1);
}
ipv6c = s->ipv6_context;
switch (request) {
case NEIGHBOR_SOLICIT:
- LOG_DEBUG("nd sol: in=%p in->eth=%p in->ipv6=%p", in, in,
- (u8_t *) in + 4);
*(int *)out = ipv6_send_nd_solicited_packet(ipv6c,
(pETH_HDR) ((pNDPC_REQPTR)in)->eth,
(pIPV6_HDR) ((pNDPC_REQPTR)in)->ipv6);
@@ -385,12 +410,6 @@ int ndpc_request(struct uip_stack *ustack, void *in, void *out, int request)
*(int *)out = ipv6_is_it_our_link_local_address(ipv6c,
(pIPV6_ADDR)in);
break;
- case GET_LINK_LOCAL_ADDR:
- *(pIPV6_ADDR *) out = &ipv6c->link_local_addr;
- break;
- case GET_DEFAULT_ROUTER_ADDR:
- *(pIPV6_ADDR *)out = &ipv6c->default_router;
- break;
case CHECK_ARP_TABLE:
*(int *)out = ipv6_ip_in_arp_table(ipv6c,
(pIPV6_ADDR) ((pNDPC_REQPTR)in)->ipv6,
@@ -399,7 +418,9 @@ int ndpc_request(struct uip_stack *ustack, void *in, void *out, int request)
case GET_HOST_ADDR:
*(pIPV6_ADDR *)out = ipv6_find_longest_match(ipv6c,
(pIPV6_ADDR)in);
+ break;
default:
+ ret = -EINVAL;
break;
}
return ret;
diff --git a/iscsiuio/src/uip/uip.c b/iscsiuio/src/uip/uip.c
index 9c79e07..d03b92e 100644
--- a/iscsiuio/src/uip/uip.c
+++ b/iscsiuio/src/uip/uip.c
@@ -1403,8 +1403,6 @@ void uip_process(struct uip_stack *ustack, u8_t flag)
#endif /* UIP_UDP */
/* This is IPv6 ICMPv6 processing code. */
- LOG_DEBUG(PFX "icmp6_input: length %d", ustack->uip_len);
-
if (ipv6_hdr->ip6_nxt != UIP_PROTO_ICMP6) {
/* We only allow ICMPv6 packets from here. */
++ustack->stats.ip.drop;
@@ -2344,7 +2342,7 @@ tcp_send:
uip_ip6addr_copy(IPv6_BUF(ustack)->srcipaddr,
ustack->hostaddr6);
uip_ip6addr_copy(IPv6_BUF(ustack)->destipaddr,
- uip_connr->ripaddr);
+ uip_connr->ripaddr6);
} else {
tcp_ipv4_hdr->proto = UIP_PROTO_TCP;
uip_ip4addr_copy(tcp_ipv4_hdr->srcipaddr, ustack->hostaddr);
diff --git a/iscsiuio/src/uip/uip.h b/iscsiuio/src/uip/uip.h
index 2b5f88c..ccac680 100644
--- a/iscsiuio/src/uip/uip.h
+++ b/iscsiuio/src/uip/uip.h
@@ -1031,6 +1031,7 @@ extern u16_t uip_urglen, uip_surglen;
*/
struct __attribute__ ((__packed__)) uip_conn {
uip_ip4addr_t ripaddr;
+ uip_ip6addr_t ripaddr6;
/**< The IP address of the remote host. */
u16_t lport; /**< The local TCP port, in network byte order. */
@@ -1564,6 +1565,7 @@ struct uip_stack {
a new connection. */
#endif /* UIP_ACTIVE_OPEN */
+#define IP_CONFIG_OFF 0x00
#define IPV4_CONFIG_OFF 0x01
#define IPV4_CONFIG_STATIC 0x02
#define IPV4_CONFIG_DHCP 0x04
@@ -1573,8 +1575,24 @@ struct uip_stack {
u8_t ip_config;
uip_ip4addr_t hostaddr, netmask, default_route_addr;
- uip_ip6addr_t hostaddr6, netmask6, default_route_addr6;
+ uip_ip6addr_t hostaddr6, netmask6, default_route_addr6,
+ linklocal6;
int prefix_len;
+ u8_t ipv6_autocfg;
+#define IPV6_AUTOCFG_DHCPV6 (1<<0)
+#define IPV6_AUTOCFG_ND (1<<1)
+#define IPV6_AUTOCFG_NOTSPEC (1<<6)
+#define IPV6_AUTOCFG_NOTUSED (1<<7)
+ u8_t linklocal_autocfg;
+#define IPV6_LL_AUTOCFG_ON (1<<0)
+#define IPV6_LL_AUTOCFG_OFF (1<<1)
+#define IPV6_LL_AUTOCFG_NOTSPEC (1<<6)
+#define IPV6_LL_AUTOCFG_NOTUSED (1<<7)
+ u8_t router_autocfg;
+#define IPV6_RTR_AUTOCFG_ON (1<<0)
+#define IPV6_RTR_AUTOCFG_OFF (1<<1)
+#define IPV6_RTR_AUTOCFG_NOTSPEC (1<<6)
+#define IPV6_RTR_AUTOCFG_NOTUSED (1<<7)
#define UIP_NEIGHBOR_ENTRIES 8
struct neighbor_entry neighbor_entries[UIP_NEIGHBOR_ENTRIES];
@@ -1586,7 +1604,6 @@ struct uip_stack {
pthread_mutex_t lock;
/* IPv6 support */
-
#define UIP_SUPPORT_IPv6_ENABLED 0x01
#define UIP_SUPPORT_IPv6_DISABLED 0x02
u8_t enable_IPv6;
diff --git a/iscsiuio/src/uip/uip_arp.c b/iscsiuio/src/uip/uip_arp.c
index 321281c..3ef3b07 100644
--- a/iscsiuio/src/uip/uip_arp.c
+++ b/iscsiuio/src/uip/uip_arp.c
@@ -265,10 +265,14 @@ uip_arp_arpin(nic_interface_t * nic_iface,
arp->sipaddr[0] = ustack->hostaddr[0];
arp->sipaddr[1] = ustack->hostaddr[1];
- if (nic_iface->vlan_id == 0)
+ if (nic_iface->vlan_id == 0) {
eth->type = htons(UIP_ETHTYPE_ARP);
- else
+ pkt->buf_size = sizeof(*arp) + sizeof(*eth);
+ } else {
eth->type = htons(UIP_ETHTYPE_8021Q);
+ pkt->buf_size = sizeof(*arp) +
+ sizeof(struct uip_vlan_eth_hdr);
+ }
pkt->buf_size = sizeof(*arp) + sizeof(*eth);
}
break;
diff --git a/iscsiuio/src/unix/iscsid_ipc.c b/iscsiuio/src/unix/iscsid_ipc.c
index 6bc5c11..d7372fc 100644
--- a/iscsiuio/src/unix/iscsid_ipc.c
+++ b/iscsiuio/src/unix/iscsid_ipc.c
@@ -70,20 +70,34 @@ struct iscsid_options {
pthread_t thread;
};
-struct ip_addr_mask {
- int ip_type;
- union {
- struct in_addr addr4;
- struct in6_addr addr6;
- } addr;
- union {
- struct in_addr nm4;
- struct in6_addr nm6;
- } netmask;
-#define addr4 addr.addr4
-#define addr6 addr.addr6
-#define nm4 netmask.nm4
-#define nm6 netmask.nm6
+struct iface_rec_decode {
+ /* General */
+ int32_t iface_num;
+ uint32_t ip_type;
+
+ /* IPv4 */
+ struct in_addr ipv4_addr;
+ struct in_addr ipv4_subnet_mask;
+ struct in_addr ipv4_gateway;
+
+ /* IPv6 */
+ struct in6_addr ipv6_addr;
+ struct in6_addr ipv6_subnet_mask;
+ uint32_t prefix_len;
+ struct in6_addr ipv6_linklocal;
+ struct in6_addr ipv6_router;
+
+ uint8_t ipv6_autocfg;
+ uint8_t linklocal_autocfg;
+ uint8_t router_autocfg;
+
+ uint8_t vlan_state;
+ uint8_t vlan_priority;
+ uint16_t vlan_id;
+
+#define MIN_MTU_SUPPORT 46
+#define MAX_MTU_SUPPORT 9000
+ uint16_t mtu;
};
/******************************************************************************
@@ -119,8 +133,7 @@ static void *enable_nic_thread(void *data)
pthread_exit(NULL);
}
-static int decode_cidr(char *in_ipaddr_str, struct ip_addr_mask *ipam,
- int *prefix_len)
+static int decode_cidr(char *in_ipaddr_str, struct iface_rec_decode *ird)
{
int rc = 0, i;
char *tmp, *tok;
@@ -130,7 +143,6 @@ static int decode_cidr(char *in_ipaddr_str, struct ip_addr_mask *ipam,
struct in_addr ia;
struct in6_addr ia6;
- memset(ipam, 0, sizeof(struct ip_addr_mask));
if (strlen(in_ipaddr_str) > NI_MAXHOST)
strncpy(ipaddr_str, in_ipaddr_str, NI_MAXHOST);
else
@@ -149,16 +161,16 @@ static int decode_cidr(char *in_ipaddr_str, struct ip_addr_mask *ipam,
/* Determine if the IP address passed from the iface file is
* an IPv4 or IPv6 address */
- rc = inet_pton(AF_INET, ipaddr_str, &ipam->addr6);
+ rc = inet_pton(AF_INET, ipaddr_str, &ird->ipv6_addr);
if (rc == 0) {
/* Test to determine if the addres is an IPv6 address */
- rc = inet_pton(AF_INET6, ipaddr_str, &ipam->addr6);
+ rc = inet_pton(AF_INET6, ipaddr_str, &ird->ipv6_addr);
if (rc == 0) {
LOG_ERR(PFX "Could not parse IP address: '%s'",
ipaddr_str);
goto out;
}
- ipam->ip_type = AF_INET6;
+ ird->ip_type = AF_INET6;
if (keepbits > 128) {
LOG_ERR(PFX "CIDR netmask > 128 for IPv6: %d(%s)",
keepbits, tmp);
@@ -166,15 +178,15 @@ static int decode_cidr(char *in_ipaddr_str, struct ip_addr_mask *ipam,
}
if (!keepbits) {
/* Default prefix mask to 64 */
- memcpy(&ipam->nm6.s6_addr, all_zeroes_addr6,
+ memcpy(&ird->ipv6_subnet_mask.s6_addr, all_zeroes_addr6,
sizeof(struct in6_addr));
+ ird->prefix_len = 64;
for (i = 0; i < 2; i++)
- ipam->nm6.s6_addr32[i] = 0xffffffff;
+ ird->ipv6_subnet_mask.s6_addr32[i] = 0xffffffff;
goto out;
}
- *prefix_len = keepbits;
- memcpy(&ia6.s6_addr, all_zeroes_addr6,
- sizeof(struct in6_addr));
+ ird->prefix_len = keepbits;
+ memcpy(&ia6.s6_addr, all_zeroes_addr6, sizeof(struct in6_addr));
for (i = 0; i < 4; i++) {
if (keepbits < 32) {
ia6.s6_addr32[i] = keepbits > 0 ?
@@ -184,12 +196,12 @@ static int decode_cidr(char *in_ipaddr_str, struct ip_addr_mask *ipam,
ia6.s6_addr32[i] = 0xFFFFFFFF;
keepbits -= 32;
}
- ipam->nm6 = ia6;
+ ird->ipv6_subnet_mask = ia6;
if (inet_ntop(AF_INET6, &ia6, str, sizeof(str)))
LOG_INFO(PFX "Using netmask: %s", str);
} else {
- ipam->ip_type = AF_INET;
- rc = inet_pton(AF_INET, ipaddr_str, &ipam->addr4);
+ ird->ip_type = AF_INET;
+ rc = inet_pton(AF_INET, ipaddr_str, &ird->ipv4_addr);
if (keepbits > 32) {
LOG_ERR(PFX "CIDR netmask > 32 for IPv4: %d(%s)",
@@ -197,54 +209,153 @@ static int decode_cidr(char *in_ipaddr_str, struct ip_addr_mask *ipam,
goto out;
}
ia.s_addr = keepbits > 0 ? 0x00 - (1 << (32 - keepbits)) : 0;
- ipam->nm4.s_addr = htonl(ia.s_addr);
- LOG_INFO(PFX "Using netmask: %s", inet_ntoa(ipam->nm4));
+ ird->ipv4_subnet_mask.s_addr = htonl(ia.s_addr);
+ LOG_INFO(PFX "Using netmask: %s",
+ inet_ntoa(ird->ipv4_subnet_mask));
}
out:
return rc;
}
+static int decode_iface(struct iface_rec_decode *ird, struct iface_rec *rec)
+{
+ int rc = 0;
+ char ipaddr_str[NI_MAXHOST];
+
+ /* Decodes the rec contents */
+ memset(ird, 0, sizeof(struct iface_rec_decode));
+
+ /* Detect for CIDR notation and strip off the netmask if present */
+ rc = decode_cidr(rec->ipaddress, ird);
+ if (rc && !ird->ip_type) {
+ LOG_ERR(PFX "cidr decode err: rc=%d, ip_type=%d",
+ rc, ird->ip_type);
+ /* Can't decode address, just exit */
+ return rc;
+ }
+ rc = 0;
+
+ ird->iface_num = rec->iface_num;
+ ird->vlan_id = rec->vlan_id;
+ if (rec->iface_num != IFACE_NUM_INVALID) {
+ ird->mtu = rec->mtu;
+ if (rec->vlan_id && strcmp(rec->vlan_state, "disable")) {
+ ird->vlan_state = 1;
+ ird->vlan_priority = rec->vlan_priority;
+ ird->vlan_id = rec->vlan_id;
+ }
+ if (ird->ip_type == AF_INET6) {
+ if (!strcmp(rec->ipv6_autocfg, "dhcpv6"))
+ ird->ipv6_autocfg = IPV6_AUTOCFG_DHCPV6;
+ else if (!strcmp(rec->ipv6_autocfg, "nd"))
+ ird->ipv6_autocfg = IPV6_AUTOCFG_ND;
+ else
+ ird->ipv6_autocfg = IPV6_AUTOCFG_NOTSPEC;
+
+ if (!strcmp(rec->linklocal_autocfg, "auto"))
+ ird->linklocal_autocfg = IPV6_LL_AUTOCFG_ON;
+ else if (!strcmp(rec->linklocal_autocfg, "off"))
+ ird->linklocal_autocfg = IPV6_LL_AUTOCFG_OFF;
+ else /* default */
+ ird->linklocal_autocfg = IPV6_LL_AUTOCFG_ON;
+
+ if (!strcmp(rec->router_autocfg, "auto"))
+ ird->router_autocfg = IPV6_RTR_AUTOCFG_ON;
+ else if (!strcmp(rec->router_autocfg, "off"))
+ ird->router_autocfg = IPV6_RTR_AUTOCFG_OFF;
+ else /* default */
+ ird->router_autocfg = IPV6_RTR_AUTOCFG_ON;
+
+ /* Decode the addresses based on the control flags */
+ /* For DHCP, ignore the IPv6 addr in the iface */
+ if (ird->ipv6_autocfg == IPV6_AUTOCFG_DHCPV6)
+ memcpy(&ird->ipv6_addr, all_zeroes_addr6,
+ sizeof(struct in6_addr));
+ /* Subnet mask priority: CIDR, then rec */
+ if (!ird->ipv6_subnet_mask.s6_addr)
+ inet_pton(AF_INET, rec->subnet_mask,
+ &ird->ipv6_subnet_mask);
+
+ /* For LL on, ignore the IPv6 addr in the iface */
+ if (ird->linklocal_autocfg == IPV6_LL_AUTOCFG_OFF) {
+ if (strlen(rec->ipv6_linklocal) > NI_MAXHOST)
+ strncpy(ipaddr_str, rec->ipv6_linklocal,
+ NI_MAXHOST);
+ else
+ strcpy(ipaddr_str, rec->ipv6_linklocal);
+ inet_pton(AF_INET6, ipaddr_str,
+ &ird->ipv6_linklocal);
+ }
+
+ /* For RTR on, ignore the IPv6 addr in the iface */
+ if (ird->router_autocfg == IPV6_RTR_AUTOCFG_OFF) {
+ if (strlen(rec->ipv6_router) > NI_MAXHOST)
+ strncpy(ipaddr_str, rec->ipv6_router,
+ NI_MAXHOST);
+ else
+ strcpy(ipaddr_str, rec->ipv6_router);
+ inet_pton(AF_INET6, ipaddr_str,
+ &ird->ipv6_router);
+ }
+ } else {
+ /* Subnet mask priority: CIDR, rec, default */
+ if (!ird->ipv4_subnet_mask.s_addr)
+ inet_pton(AF_INET, rec->subnet_mask,
+ &ird->ipv4_subnet_mask);
+ if (!ird->ipv4_subnet_mask.s_addr)
+ ird->ipv4_subnet_mask.s_addr =
+ calculate_default_netmask(
+ ird->ipv4_addr.s_addr);
+
+ if (strlen(rec->gateway) > NI_MAXHOST)
+ strncpy(ipaddr_str, rec->gateway, NI_MAXHOST);
+ else
+ strcpy(ipaddr_str, rec->gateway);
+ inet_pton(AF_INET, ipaddr_str, &ird->ipv4_gateway);
+ }
+ } else {
+ ird->ipv6_autocfg = IPV6_AUTOCFG_NOTUSED;
+ ird->linklocal_autocfg = IPV6_LL_AUTOCFG_NOTUSED;
+ ird->router_autocfg = IPV6_RTR_AUTOCFG_NOTUSED;
+ }
+ return rc;
+}
+
static int parse_iface(void *arg)
{
- int rc;
+ int rc, i;
nic_t *nic = NULL;
- nic_interface_t *nic_iface, *vlan_iface, *base_nic_iface;
+ nic_interface_t *nic_iface;
char *transport_name;
size_t transport_name_size;
nic_lib_handle_t *handle;
iscsid_uip_broadcast_t *data;
- short int vlan;
char ipv6_buf_str[INET6_ADDRSTRLEN];
int request_type = 0;
- struct in_addr netmask;
- int i, prefix_len = 64;
- struct ip_addr_mask ipam;
struct iface_rec *rec;
void *res;
+ struct iface_rec_decode ird;
+ struct in_addr src_match, dst_match;
data = (iscsid_uip_broadcast_t *) arg;
rec = &data->u.iface_rec.rec;
LOG_INFO(PFX "Received request for '%s' to set IP address: '%s' "
- "VLAN: '%d'", rec->netdev, rec->ipaddress, rec->vlan_id);
-
- vlan = rec->vlan_id;
- if (vlan && valid_vlan(vlan) == 0) {
- LOG_ERR(PFX "Invalid VLAN tag: %d", rec->vlan_id);
+ "VLAN: '%d'",
+ rec->netdev,
+ rec->ipaddress,
+ rec->vlan_id);
+
+ rc = decode_iface(&ird, rec);
+ if (ird.vlan_id && valid_vlan(ird.vlan_id) == 0) {
+ LOG_ERR(PFX "Invalid VLAN tag: %d", ird.vlan_id);
rc = -EIO;
goto early_exit;
}
-
- /* Detect for CIDR notation and strip off the netmask if present */
- rc = decode_cidr(rec->ipaddress, &ipam, &prefix_len);
- if (rc && !ipam.ip_type) {
- LOG_ERR(PFX "decode_cidr: rc=%d, ipam.ip_type=%d",
- rc, ipam.ip_type)
- goto early_exit;
- }
- if (ipam.ip_type == AF_INET6)
- inet_ntop(AF_INET6, &ipam.addr6, ipv6_buf_str,
- sizeof(ipv6_buf_str));
+ if (rc && !ird.ip_type) {
+ LOG_ERR(PFX "iface err: rc=%d, ip_type=%d", rc, ird.ip_type);
+ goto early_exit;
+ }
for (i = 0; i < 10; i++) {
struct timespec sleep_req, sleep_rem;
@@ -258,11 +369,13 @@ static int parse_iface(void *arg)
}
if (i >= 10) {
- LOG_WARN(PFX "Could not aquire nic_list_mutex lock");
+ LOG_WARN(PFX "Could not acquire nic_list_mutex lock");
rc = -EIO;
goto early_exit;
}
+ /* nic_list_mutex locked */
+
/* Check if we can find the NIC device using the netdev
* name */
rc = from_netdev_name_find_nic(rec->netdev, &nic);
@@ -298,21 +411,22 @@ static int parse_iface(void *arg)
rec->netdev);
}
+ pthread_mutex_lock(&nic->nic_mutex);
if (nic->flags & NIC_GOING_DOWN) {
+ pthread_mutex_unlock(&nic->nic_mutex);
rc = -EIO;
LOG_INFO(PFX "nic->flags GOING DOWN");
goto done;
}
- /* If we retry too many times allow iscsid to to timeout */
+ /* If we retry too many times allow iscsid to timeout */
if (nic->pending_count > 1000) {
- LOG_WARN(PFX "%s: pending count excceded 1000", nic->log_name);
-
- pthread_mutex_lock(&nic->nic_mutex);
nic->pending_count = 0;
nic->flags &= ~NIC_ENABLED_PENDING;
pthread_mutex_unlock(&nic->nic_mutex);
+ LOG_WARN(PFX "%s: pending count exceeded 1000", nic->log_name);
+
rc = 0;
goto done;
}
@@ -320,18 +434,19 @@ static int parse_iface(void *arg)
if (nic->flags & NIC_ENABLED_PENDING) {
struct timespec sleep_req, sleep_rem;
+ nic->pending_count++;
+ pthread_mutex_unlock(&nic->nic_mutex);
+
sleep_req.tv_sec = 0;
sleep_req.tv_nsec = 100000;
nanosleep(&sleep_req, &sleep_rem);
- pthread_mutex_lock(&nic->nic_mutex);
- nic->pending_count++;
- pthread_mutex_unlock(&nic->nic_mutex);
-
LOG_INFO(PFX "%s: enabled pending", nic->log_name);
+
rc = -EAGAIN;
goto done;
}
+ pthread_mutex_unlock(&nic->nic_mutex);
prepare_library(nic);
@@ -359,66 +474,9 @@ static int parse_iface(void *arg)
LOG_INFO(PFX "%s library set using transport_name %s",
nic->log_name, transport_name);
- /* Create the base network interface if it doesn't exist */
- nic_iface = nic_find_nic_iface_protocol(nic, 0, ipam.ip_type);
- if (nic_iface == NULL) {
- LOG_INFO(PFX "%s couldn't find interface with "
- "ip_type: 0x%x creating it",
- nic->log_name, ipam.ip_type);
-
- /* Create the nic interface */
- nic_iface = nic_iface_init();
-
- if (nic_iface == NULL) {
- LOG_ERR(PFX "Couldn't allocate nic_iface", nic_iface);
- goto done;
- }
-
- nic_iface->protocol = ipam.ip_type;
- nic_add_nic_iface(nic, nic_iface);
-
- persist_all_nic_iface(nic);
-
- LOG_INFO(PFX "%s: created network interface", nic->log_name);
- } else {
- LOG_INFO(PFX "%s: using existing network interface",
- nic->log_name);
- }
-
- set_nic_iface(nic, nic_iface);
-
- /* Find the vlan nic_interface */
- if (vlan) {
- vlan_iface = nic_find_vlan_iface_protocol(nic, nic_iface, vlan,
- ipam.ip_type);
- if (vlan_iface == NULL) {
- LOG_INFO(PFX "%s couldn't find interface with VLAN = %d"
- "ip_type: 0x%x creating it",
- nic->log_name, vlan, ipam.ip_type);
-
- /* Create the nic interface */
- vlan_iface = nic_iface_init();
-
- if (vlan_iface == NULL) {
- LOG_ERR(PFX "Couldn't allocate nic_iface for "
- "VLAN: %d", vlan_iface, vlan);
- goto done;
- }
-
- vlan_iface->protocol = ipam.ip_type;
- vlan_iface->vlan_id = vlan;
- nic_add_vlan_iface(nic, nic_iface, vlan_iface);
- } else {
- LOG_INFO(PFX "%s: using existing vlan interface",
- nic->log_name);
- }
- base_nic_iface = nic_iface;
- nic_iface = vlan_iface;
- }
-
/* Determine how to configure the IP address */
- if (ipam.ip_type == AF_INET) {
- if (memcmp(&ipam.addr4,
+ if (ird.ip_type == AF_INET) {
+ if (memcmp(&ird.ipv4_addr,
all_zeroes_addr4, sizeof(uip_ip4addr_t)) == 0) {
LOG_INFO(PFX "%s: requesting configuration using DHCP",
nic->log_name);
@@ -428,51 +486,161 @@ static int parse_iface(void *arg)
"static IP address", nic->log_name);
request_type = IPV4_CONFIG_STATIC;
}
- } else if (ipam.ip_type == AF_INET6) {
- if (memcmp(&ipam.addr6,
- all_zeroes_addr6, sizeof(uip_ip6addr_t)) == 0) {
- LOG_INFO(PFX
- "%s: requesting configuration using DHCPv6",
- nic->log_name);
+ } else if (ird.ip_type == AF_INET6) {
+ /* For the new 872_22, check ipv6_autocfg for DHCPv6 instead */
+ switch (ird.ipv6_autocfg) {
+ case IPV6_AUTOCFG_DHCPV6:
request_type = IPV6_CONFIG_DHCP;
- } else {
- LOG_INFO(PFX "%s: request configuration using static "
- "IPv6 address: '%s'",
- nic->log_name, ipv6_buf_str);
+ break;
+ case IPV6_AUTOCFG_ND:
request_type = IPV6_CONFIG_STATIC;
+ break;
+ case IPV6_AUTOCFG_NOTSPEC:
+ /* Treat NOTSPEC the same as NOTUSED for now */
+ case IPV6_AUTOCFG_NOTUSED:
+ /* For 871 */
+ default:
+ /* Just the IP address to determine */
+ if (memcmp(&ird.ipv6_addr,
+ all_zeroes_addr6,
+ sizeof(struct in6_addr)) == 0)
+ request_type = IPV6_CONFIG_DHCP;
+ else
+ request_type = IPV6_CONFIG_STATIC;
}
} else {
LOG_ERR(PFX "%s: unknown ip_type to configure: 0x%x",
- nic->log_name, ipam.ip_type);
+ nic->log_name, ird.ip_type);
rc = -EIO;
goto done;
}
+ pthread_mutex_lock(&nic->nic_mutex);
+
+ nic_iface = nic_find_nic_iface(nic, ird.ip_type, ird.vlan_id,
+ ird.iface_num, request_type);
+
+ if (nic->flags & NIC_PATHREQ_WAIT) {
+ if (!nic_iface ||
+ !(nic_iface->flags & NIC_IFACE_PATHREQ_WAIT)) {
+ int pathreq_wait;
+
+ if (nic_iface &&
+ (nic_iface->flags & NIC_IFACE_PATHREQ_WAIT2))
+ pathreq_wait = 12;
+ else
+ pathreq_wait = 10;
+
+ if (nic->pathreq_pending_count < pathreq_wait) {
+ struct timespec sleep_req, sleep_rem;
+
+ pthread_mutex_unlock(&nic->nic_mutex);
+
+ nic->pathreq_pending_count++;
+ sleep_req.tv_sec = 0;
+ sleep_req.tv_nsec = 100000;
+ nanosleep(&sleep_req, &sleep_rem);
+ /* Somebody else is waiting for PATH_REQ */
+ LOG_INFO(PFX "%s: path req pending cnt=%d",
+ nic->log_name,
+ nic->pathreq_pending_count);
+ rc = -EAGAIN;
+ goto done;
+ } else {
+ nic->pathreq_pending_count = 0;
+ LOG_DEBUG(PFX "%s: path req pending cnt "
+ "exceeded!", nic->log_name);
+ /* Allow to fall thru */
+ }
+ }
+ }
+
+ nic->flags |= NIC_PATHREQ_WAIT;
+
+ /* Create the network interface if it doesn't exist */
+ if (nic_iface == NULL) {
+ LOG_DEBUG(PFX "%s couldn't find interface with "
+ "ip_type: 0x%x creating it",
+ nic->log_name, ird.ip_type);
+ nic_iface = nic_iface_init();
+
+ if (nic_iface == NULL) {
+ pthread_mutex_unlock(&nic->nic_mutex);
+ LOG_ERR(PFX "%s Couldn't allocate "
+ "interface with ip_type: 0x%x",
+ nic->log_name, ird.ip_type);
+ goto done;
+ }
+ nic_iface->protocol = ird.ip_type;
+ nic_iface->vlan_id = ird.vlan_id;
+ nic_iface->vlan_priority = ird.vlan_priority;
+ if (ird.mtu >= MIN_MTU_SUPPORT && ird.mtu <= MAX_MTU_SUPPORT)
+ nic_iface->mtu = ird.mtu;
+ nic_iface->iface_num = ird.iface_num;
+ nic_iface->request_type = request_type;
+ nic_add_nic_iface(nic, nic_iface);
+
+ persist_all_nic_iface(nic);
+
+ LOG_INFO(PFX "%s: created network interface",
+ nic->log_name);
+ } else {
+ /* Move the nic_iface to the front */
+ set_nic_iface(nic, nic_iface);
+ LOG_INFO(PFX "%s: using existing network interface",
+ nic->log_name);
+ }
+
+ nic_iface->flags |= NIC_IFACE_PATHREQ_WAIT1;
+ if (nic->nl_process_thread == INVALID_THREAD) {
+ rc = pthread_create(&nic->nl_process_thread, NULL,
+ nl_process_handle_thread, nic);
+ if (rc != 0) {
+ LOG_ERR(PFX "%s: Could not create NIC NL "
+ "processing thread [%s]", nic->log_name,
+ strerror(rc));
+ nic->nl_process_thread = INVALID_THREAD;
+ /* Reset both WAIT flags */
+ nic_iface->flags &= ~NIC_IFACE_PATHREQ_WAIT;
+ nic->flags &= ~NIC_PATHREQ_WAIT;
+ }
+ }
+
+ pthread_mutex_unlock(&nic->nic_mutex);
+
if (nic_iface->ustack.ip_config == request_type) {
+ /* Same request_type, check for STATIC address change */
if (request_type == IPV4_CONFIG_STATIC) {
- if (memcmp(nic_iface->ustack.hostaddr, &ipam.addr4,
+ if (memcmp(nic_iface->ustack.hostaddr, &ird.ipv4_addr,
sizeof(struct in_addr)))
- goto diff;
+ goto reacquire;
} else if (request_type == IPV6_CONFIG_STATIC) {
- if (memcmp(nic_iface->ustack.hostaddr6, &ipam.addr6,
+ if (memcmp(nic_iface->ustack.hostaddr6, &ird.ipv6_addr,
sizeof(struct in6_addr)))
- goto diff;
+ goto reacquire;
+ else
+ inet_ntop(AF_INET6, &ird.ipv6_addr,
+ ipv6_buf_str,
+ sizeof(ipv6_buf_str));
}
LOG_INFO(PFX "%s: IP configuration didn't change using 0x%x",
nic->log_name, nic_iface->ustack.ip_config);
- goto enable_nic;
-diff:
- /* Disable the NIC */
- nic_disable(nic, 0);
- } else {
- if (request_type == IPV4_CONFIG_DHCP
- || request_type == IPV6_CONFIG_DHCP)
- nic->flags |= NIC_RESET_UIP;
+ /* No need to acquire the IP address */
+ inet_ntop(AF_INET6, &ird.ipv6_addr, ipv6_buf_str,
+ sizeof(ipv6_buf_str));
- /* Disable the NIC */
- nic_disable(nic, 0);
+ goto enable_nic;
}
+reacquire:
+ /* Config needs to re-acquire for this nic_iface */
+ pthread_mutex_lock(&nic->nic_mutex);
+ nic_iface->flags |= NIC_IFACE_ACQUIRE;
+ pthread_mutex_unlock(&nic->nic_mutex);
+
+ /* Disable the nic loop from further processing, upon returned,
+ the nic_iface should be cleared */
+ nic_disable(nic, 0);
/* Check to see if this is using DHCP or if this is
* a static IPv4 address. This is done by checking
@@ -485,97 +653,96 @@ diff:
memset(nic_iface->ustack.hostaddr, 0, sizeof(struct in_addr));
LOG_INFO(PFX "%s: configuring using DHCP", nic->log_name);
nic_iface->ustack.ip_config = IPV4_CONFIG_DHCP;
-
break;
+
case IPV4_CONFIG_STATIC:
- memcpy(nic_iface->ustack.hostaddr, &ipam.addr4,
+ memcpy(nic_iface->ustack.hostaddr, &ird.ipv4_addr,
sizeof(struct in_addr));
LOG_INFO(PFX "%s: configuring using static IP "
"IPv4 address :%s ",
- nic->log_name, inet_ntoa(ipam.addr4));
- netmask.s_addr = ipam.nm4.s_addr;
- if (!netmask.s_addr)
- netmask.s_addr =
- calculate_default_netmask(ipam.addr4.s_addr);
- memcpy(nic_iface->ustack.netmask,
- &netmask, sizeof(netmask.s_addr));
- LOG_INFO(PFX " netmask :%s", inet_ntoa(netmask));
-
+ nic->log_name, inet_ntoa(ird.ipv4_addr));
+
+ if (ird.ipv4_subnet_mask.s_addr)
+ memcpy(nic_iface->ustack.netmask,
+ &ird.ipv4_subnet_mask, sizeof(struct in_addr));
+ LOG_INFO(PFX " netmask: %s", inet_ntoa(ird.ipv4_subnet_mask));
+
+ /* Default route */
+ if (ird.ipv4_gateway.s_addr) {
+ /* Check for validity */
+ src_match.s_addr = ird.ipv4_addr.s_addr &
+ ird.ipv4_subnet_mask.s_addr;
+ dst_match.s_addr = ird.ipv4_gateway.s_addr &
+ ird.ipv4_subnet_mask.s_addr;
+ if (src_match.s_addr == dst_match.s_addr)
+ memcpy(nic_iface->ustack.default_route_addr,
+ &ird.ipv4_gateway,
+ sizeof(struct in_addr));
+ }
nic_iface->ustack.ip_config = IPV4_CONFIG_STATIC;
break;
+
case IPV6_CONFIG_DHCP:
memset(nic_iface->ustack.hostaddr6, 0,
sizeof(struct in6_addr));
- nic_iface->ustack.prefix_len = prefix_len;
- if (ipam.nm6.s6_addr[0] | ipam.nm6.s6_addr[1] |
- ipam.nm6.s6_addr[2] | ipam.nm6.s6_addr[3] |
- ipam.nm6.s6_addr[4] | ipam.nm6.s6_addr[5] |
- ipam.nm6.s6_addr[6] | ipam.nm6.s6_addr[7])
+ nic_iface->ustack.prefix_len = ird.prefix_len;
+ nic_iface->ustack.ipv6_autocfg = ird.ipv6_autocfg;
+ nic_iface->ustack.linklocal_autocfg = ird.linklocal_autocfg;
+ nic_iface->ustack.router_autocfg = ird.router_autocfg;
+
+ if (memcmp(&ird.ipv6_subnet_mask, all_zeroes_addr6,
+ sizeof(struct in6_addr)))
memcpy(nic_iface->ustack.netmask6,
- &ipam.nm6, sizeof(struct in6_addr));
+ &ird.ipv6_subnet_mask, sizeof(struct in6_addr));
+ if (ird.linklocal_autocfg == IPV6_LL_AUTOCFG_OFF)
+ memcpy(nic_iface->ustack.linklocal6,
+ &ird.ipv6_linklocal, sizeof(struct in6_addr));
+ if (ird.router_autocfg == IPV6_RTR_AUTOCFG_OFF)
+ memcpy(nic_iface->ustack.default_route_addr6,
+ &ird.ipv6_router, sizeof(struct in6_addr));
+ inet_ntop(AF_INET6, &ird.ipv6_addr, ipv6_buf_str,
+ sizeof(ipv6_buf_str));
LOG_INFO(PFX "%s: configuring using DHCPv6",
nic->log_name);
nic_iface->ustack.ip_config = IPV6_CONFIG_DHCP;
break;
+
case IPV6_CONFIG_STATIC:
- memcpy(nic_iface->ustack.hostaddr6, &ipam.addr6,
+ memcpy(nic_iface->ustack.hostaddr6, &ird.ipv6_addr,
sizeof(struct in6_addr));
+ nic_iface->ustack.prefix_len = ird.prefix_len;
+ nic_iface->ustack.ipv6_autocfg = ird.ipv6_autocfg;
+ nic_iface->ustack.linklocal_autocfg = ird.linklocal_autocfg;
+ nic_iface->ustack.router_autocfg = ird.router_autocfg;
- nic_iface->ustack.prefix_len = prefix_len;
- if (ipam.nm6.s6_addr[0] | ipam.nm6.s6_addr[1] |
- ipam.nm6.s6_addr[2] | ipam.nm6.s6_addr[3] |
- ipam.nm6.s6_addr[4] | ipam.nm6.s6_addr[5] |
- ipam.nm6.s6_addr[6] | ipam.nm6.s6_addr[7])
+ if (memcmp(&ird.ipv6_subnet_mask, all_zeroes_addr6,
+ sizeof(struct in6_addr)))
memcpy(nic_iface->ustack.netmask6,
- &ipam.nm6, sizeof(struct in6_addr));
-
+ &ird.ipv6_subnet_mask, sizeof(struct in6_addr));
+ if (ird.linklocal_autocfg == IPV6_LL_AUTOCFG_OFF)
+ memcpy(nic_iface->ustack.linklocal6,
+ &ird.ipv6_linklocal, sizeof(struct in6_addr));
+ if (ird.router_autocfg == IPV6_RTR_AUTOCFG_OFF)
+ memcpy(nic_iface->ustack.default_route_addr6,
+ &ird.ipv6_router, sizeof(struct in6_addr));
+
+ inet_ntop(AF_INET6, &ird.ipv6_addr, ipv6_buf_str,
+ sizeof(ipv6_buf_str));
LOG_INFO(PFX "%s: configuring using static IP "
"IPv6 address: '%s'", nic->log_name, ipv6_buf_str);
nic_iface->ustack.ip_config = IPV6_CONFIG_STATIC;
break;
+
default:
LOG_INFO(PFX "%s: Unknown request type: 0x%x",
nic->log_name, request_type);
}
- /* Configuration changed, do VLAN WA */
- vlan_iface = nic_iface->vlan_next;
- while (vlan_iface) {
- /* TODO: When VLAN support is placed in the iface file
- * revisit this code */
- if (vlan_iface->ustack.ip_config) {
- vlan_iface->ustack.ip_config =
- nic_iface->ustack.ip_config;
- memcpy(vlan_iface->ustack.hostaddr,
- nic_iface->ustack.hostaddr,
- sizeof(nic_iface->ustack.hostaddr));
- memcpy(vlan_iface->ustack.netmask,
- nic_iface->ustack.netmask,
- sizeof(nic_iface->ustack.netmask));
- memcpy(vlan_iface->ustack.hostaddr6,
- nic_iface->ustack.hostaddr6,
- sizeof(nic_iface->ustack.hostaddr6));
- memcpy(vlan_iface->ustack.netmask6,
- nic_iface->ustack.netmask6,
- sizeof(nic_iface->ustack.netmask6));
- }
- vlan_iface = vlan_iface->vlan_next;
- }
-
enable_nic:
- if (nic->state & NIC_STOPPED) {
- pthread_mutex_lock(&nic->nic_mutex);
- if (nic->flags & NIC_ENABLED_PENDING) {
- /* Still waiting */
- pthread_mutex_unlock(&nic->nic_mutex);
- rc = 0;
- goto enable_out;
- }
- nic->flags |= NIC_ENABLED_PENDING;
- pthread_mutex_unlock(&nic->nic_mutex);
-
+ switch (nic->state) {
+ case NIC_STOPPED:
/* This thread will be thrown away when completed */
if (nic->enable_thread != INVALID_THREAD) {
rc = pthread_join(nic->enable_thread, &res);
@@ -592,19 +759,27 @@ enable_nic:
nic->log_name);
eagain:
rc = -EAGAIN;
- } else {
+ break;
+
+ case NIC_RUNNING:
LOG_INFO(PFX "%s: NIC already enabled "
"flags: 0x%x state: 0x%x\n",
nic->log_name, nic->flags, nic->state);
rc = 0;
+ break;
+ default:
+ LOG_INFO(PFX "%s: NIC enable still in progress "
+ "flags: 0x%x state: 0x%x\n",
+ nic->log_name, nic->flags, nic->state);
+ rc = -EAGAIN;
}
-enable_out:
+
LOG_INFO(PFX "ISCSID_UIP_IPC_GET_IFACE: command: %x "
"name: %s, netdev: %s ipaddr: %s vlan: %d transport_name:%s",
data->header.command, rec->name, rec->netdev,
- (ipam.ip_type == AF_INET) ? inet_ntoa(ipam.addr4) :
+ (ird.ip_type == AF_INET) ? inet_ntoa(ird.ipv4_addr) :
ipv6_buf_str,
- vlan, rec->transport_name);
+ ird.vlan_id, rec->transport_name);
done:
pthread_mutex_unlock(&nic_list_mutex);
@@ -638,12 +813,13 @@ int process_iscsid_broadcast(int s2)
data = (iscsid_uip_broadcast_t *) calloc(1, sizeof(*data));
if (data == NULL) {
LOG_ERR(PFX "Couldn't allocate memory for iface data");
- return -ENOMEM;
+ rc = -ENOMEM;
+ goto error;
}
memset(data, 0, sizeof(*data));
size = fread(data, sizeof(iscsid_uip_broadcast_header_t), 1, fd);
- if (size == -1) {
+ if (!size) {
LOG_ERR(PFX "Could not read request: %d(%s)",
errno, strerror(errno));
rc = ferror(fd);
@@ -657,7 +833,7 @@ int process_iscsid_broadcast(int s2)
cmd, payload_len);
size = fread(&data->u.iface_rec, payload_len, 1, fd);
- if (size == -1) {
+ if (!size) {
LOG_ERR(PFX "Could not read data: %d(%s)",
errno, strerror(errno));
goto error;
diff --git a/iscsiuio/src/unix/libs/bnx2.c b/iscsiuio/src/unix/libs/bnx2.c
index 112d570..a8300c2 100644
--- a/iscsiuio/src/unix/libs/bnx2.c
+++ b/iscsiuio/src/unix/libs/bnx2.c
@@ -295,7 +295,7 @@ static int bnx2_uio_verify(nic_t * nic)
LOG_INFO(PFX "%s: Verified is a cnic_uio device", nic->log_name);
- error:
+error:
return rc;
}
@@ -395,7 +395,7 @@ static void bnx2_free(nic_t *nic)
/**
* bnx2_alloc() - Used to allocate a bnx2 structure
*/
-static bnx2_t *bnx2_alloc(nic_t * nic)
+static bnx2_t *bnx2_alloc(nic_t *nic)
{
bnx2_t *bp = malloc(sizeof(*bp));
if (bp == NULL) {
@@ -468,12 +468,14 @@ static int bnx2_open(nic_t * nic)
manually_trigger_uio_event(nic, nic->uio_minor);
/* udev might not have created the file yet */
+ pthread_mutex_unlock(&nic->nic_mutex);
sleep(1);
+ pthread_mutex_lock(&nic->nic_mutex);
}
}
if (fstat(nic->fd, &uio_stat) < 0) {
LOG_ERR(PFX "%s: Could not fstat device", nic->log_name);
- rc = -ENODEV;
+ errno = -ENODEV;
goto error_alloc_rx_ring;
}
nic->uio_minor = minor(uio_stat.st_rdev);
@@ -483,7 +485,7 @@ static int bnx2_open(nic_t * nic)
if (bp->bar0_fd < 0) {
LOG_ERR(PFX "%s: Could not open %s", nic->log_name,
sysfs_resc_path);
- rc = -ENODEV;
+ errno = -ENODEV;
goto error_alloc_rx_ring;
}
@@ -506,6 +508,7 @@ static int bnx2_open(nic_t * nic)
if (bp->rx_ring == NULL) {
LOG_ERR(PFX "%s: Could not allocate space for rx_ring",
nic->log_name);
+ errno = -ENOMEM;
goto error_alloc_rx_ring;
}
mlock(bp->rx_ring, sizeof(struct l2_fhdr *) * bp->rx_ring_size);
@@ -515,6 +518,7 @@ static int bnx2_open(nic_t * nic)
if (bp->rx_pkt_ring == NULL) {
LOG_ERR(PFX "%s: Could not allocate space for rx_pkt_ring",
nic->log_name);
+ errno = -ENOMEM;
goto error_alloc_rx_pkt_ring;
}
mlock(bp->rx_pkt_ring, sizeof(void *) * bp->rx_ring_size);
@@ -677,9 +681,10 @@ static int bnx2_open(nic_t * nic)
bnx2_wr32(bp, BNX2_RPM_SORT_USER2, val | BNX2_RPM_SORT_USER2_ENA);
rc = enable_multicast(nic);
- if (rc != 0)
+ if (rc != 0) {
+ errno = rc;
goto error_bufs;
-
+ }
msync(bp->reg, 0x12800, MS_SYNC);
LOG_INFO("%s: bnx2 uio initialized", nic->log_name);
@@ -707,6 +712,10 @@ error_alloc_rx_pkt_ring:
bp->rx_ring = NULL;
error_alloc_rx_ring:
+ if (nic->fd != INVALID_FD) {
+ close(nic->fd);
+ nic->fd = INVALID_FD;
+ }
bnx2_free(nic);
return errno;
@@ -878,8 +887,8 @@ void bnx2_start_xmit(nic_t * nic, size_t len, u16_t vlan_id)
rxbd = (struct rx_bd *)(((__u8 *) bp->tx_ring) + getpagesize());
if ((rxbd->rx_bd_haddr_hi == 0) && (rxbd->rx_bd_haddr_lo == 0)) {
- LOG_DEBUG(PFX "%s: trying to transmit when device is closed",
- nic->log_name);
+ LOG_PACKET(PFX "%s: trying to transmit when device is closed",
+ nic->log_name);
pthread_mutex_unlock(&nic->xmit_mutex);
return;
}
@@ -905,8 +914,8 @@ void bnx2_start_xmit(nic_t * nic, size_t len, u16_t vlan_id)
bnx2_reg_sync(bp, bp->tx_bidx_io, sizeof(__u16));
bnx2_reg_sync(bp, bp->tx_bseq_io, sizeof(__u32));
- LOG_DEBUG(PFX "%s: sent %d bytes using dev->tx_prod: %d",
- nic->log_name, len, bp->tx_prod);
+ LOG_PACKET(PFX "%s: sent %d bytes using dev->tx_prod: %d",
+ nic->log_name, len, bp->tx_prod);
}
/**
@@ -917,8 +926,8 @@ void bnx2_start_xmit(nic_t * nic, size_t len, u16_t vlan_id)
*/
int bnx2_write(nic_t * nic, nic_interface_t * nic_iface, packet_t * pkt)
{
- bnx2_t *bp = (bnx2_t *) nic->priv;
- struct uip_stack *uip = &nic_iface->ustack;
+ bnx2_t *bp;
+ struct uip_stack *uip;
/* Sanity Check: validate the parameters */
if (nic == NULL || nic_iface == NULL || pkt == NULL) {
@@ -927,6 +936,8 @@ int bnx2_write(nic_t * nic, nic_interface_t * nic_iface, packet_t * pkt)
" pkt == 0x%x", nic, nic_iface, pkt);
return -EINVAL;
}
+ bp = (bnx2_t *)nic->priv;
+ uip = &nic_iface->ustack;
if (pkt->buf_size == 0) {
LOG_ERR(PFX "%s: Trying to transmitted 0 sized packet",
@@ -935,22 +946,24 @@ int bnx2_write(nic_t * nic, nic_interface_t * nic_iface, packet_t * pkt)
}
if (pthread_mutex_trylock(&nic->xmit_mutex) != 0) {
- LOG_DEBUG(PFX "%s: Dropped previous transmitted packet",
- nic->log_name);
+ LOG_PACKET(PFX "%s: Dropped previous transmitted packet",
+ nic->log_name);
return -EINVAL;
}
bnx2_prepare_xmit_packet(nic, nic_iface, pkt);
- bnx2_start_xmit(nic, pkt->buf_size, nic_iface->vlan_id);
+ bnx2_start_xmit(nic, pkt->buf_size,
+ (nic_iface->vlan_priority << 12) |
+ nic_iface->vlan_id);
/* bump the bnx2 dev send statistics */
nic->stats.tx.packets++;
nic->stats.tx.bytes += uip->uip_len;
- LOG_DEBUG(PFX "%s: transmitted %d bytes "
- "dev->tx_cons: %d, dev->tx_prod: %d, dev->tx_bseq:%d",
- nic->log_name, pkt->buf_size,
- bp->tx_cons, bp->tx_prod, bp->tx_bseq);
+ LOG_PACKET(PFX "%s: transmitted %d bytes "
+ "dev->tx_cons: %d, dev->tx_prod: %d, dev->tx_bseq:%d",
+ nic->log_name, pkt->buf_size,
+ bp->tx_cons, bp->tx_prod, bp->tx_bseq);
return 0;
}
@@ -963,7 +976,7 @@ int bnx2_write(nic_t * nic, nic_interface_t * nic_iface, packet_t * pkt)
*/
static int bnx2_read(nic_t * nic, packet_t * pkt)
{
- bnx2_t *bp = (bnx2_t *) nic->priv;
+ bnx2_t *bp;
int rc = 0;
uint16_t hw_cons, sw_cons;
@@ -973,6 +986,7 @@ static int bnx2_read(nic_t * nic, packet_t * pkt)
" pkt == 0x%x", nic, pkt);
return -EINVAL;
}
+ bp = (bnx2_t *)nic->priv;
hw_cons = bp->get_rx_cons(bp);
sw_cons = bp->rx_cons;
@@ -984,8 +998,8 @@ static int bnx2_read(nic_t * nic, packet_t * pkt)
int len;
uint16_t errors;
- LOG_DEBUG(PFX "%s: clearing rx interrupt: %d %d %d",
- nic->log_name, sw_cons, hw_cons, rx_index);
+ LOG_PACKET(PFX "%s: clearing rx interrupt: %d %d %d",
+ nic->log_name, sw_cons, hw_cons, rx_index);
msync(rx_hdr, sizeof(struct l2_fhdr), MS_SYNC);
errors = ((rx_hdr->l2_fhdr_status & 0xffff0000) >> 16);
@@ -1033,8 +1047,8 @@ static int bnx2_read(nic_t * nic, packet_t * pkt)
rc = 1;
- LOG_DEBUG(PFX "%s: processing packet "
- "length: %d", nic->log_name, len);
+ LOG_PACKET(PFX "%s: processing packet "
+ "length: %d", nic->log_name, len);
} else {
/* If the NIC passes up a packet bigger
* then the RX buffer, flag it */
@@ -1073,21 +1087,23 @@ static int bnx2_read(nic_t * nic, packet_t * pkt)
*/
static int bnx2_clear_tx_intr(nic_t * nic)
{
- bnx2_t *bp = (bnx2_t *) nic->priv;
- uint16_t hw_cons = bp->get_tx_cons(bp);
+ bnx2_t *bp;
+ uint16_t hw_cons;
/* Sanity check: ensure the parameters passed in are valid */
if (unlikely(nic == NULL)) {
LOG_ERR(PFX "bnx2_read() nic == NULL");
return -EINVAL;
}
+ bp = (bnx2_t *) nic->priv;
+ hw_cons = bp->get_tx_cons(bp);
if (bp->flags & BNX2_UIO_TX_HAS_SENT) {
bp->flags &= ~BNX2_UIO_TX_HAS_SENT;
}
- LOG_DEBUG(PFX "%s: clearing tx interrupt [%d %d]",
- nic->log_name, bp->tx_cons, hw_cons);
+ LOG_PACKET(PFX "%s: clearing tx interrupt [%d %d]",
+ nic->log_name, bp->tx_cons, hw_cons);
bp->tx_cons = hw_cons;
@@ -1097,7 +1113,7 @@ static int bnx2_clear_tx_intr(nic_t * nic)
if (nic->tx_packet_queue != NULL) {
packet_t *pkt;
- LOG_DEBUG(PFX "%s: sending queued tx packet", nic->log_name);
+ LOG_PACKET(PFX "%s: sending queued tx packet", nic->log_name);
pkt = nic_dequeue_tx_packet(nic);
/* Got a TX packet buffer of the TX queue and put it onto
@@ -1106,13 +1122,14 @@ static int bnx2_clear_tx_intr(nic_t * nic)
bnx2_prepare_xmit_packet(nic, pkt->nic_iface, pkt);
bnx2_start_xmit(nic, pkt->buf_size,
+ (pkt->nic_iface->vlan_priority << 12) |
pkt->nic_iface->vlan_id);
- LOG_DEBUG(PFX "%s: transmitted queued packet %d bytes "
- "dev->tx_cons: %d, dev->tx_prod: %d, "
- "dev->tx_bseq:%d",
- nic->log_name, pkt->buf_size,
- bp->tx_cons, bp->tx_prod, bp->tx_bseq);
+ LOG_PACKET(PFX "%s: transmitted queued packet %d bytes "
+ "dev->tx_cons: %d, dev->tx_prod: %d, "
+ "dev->tx_bseq:%d",
+ nic->log_name, pkt->buf_size,
+ bp->tx_cons, bp->tx_prod, bp->tx_bseq);
return -EAGAIN;
}
diff --git a/iscsiuio/src/unix/libs/bnx2x.c b/iscsiuio/src/unix/libs/bnx2x.c
index fa32fbc..5e33420 100644
--- a/iscsiuio/src/unix/libs/bnx2x.c
+++ b/iscsiuio/src/unix/libs/bnx2x.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009-2011, Broadcom Corporation
+ * Copyright (c) 2009-2012, Broadcom Corporation
*
* Written by: Benjamin Li (benli@broadcom.com)
*
@@ -288,11 +288,12 @@ static void bnx2x_set_drv_version_unknown(bnx2x_t * bp)
bp->version.sub_minor = BNX2X_UNKNOWN_SUB_MINOR_VERSION;
}
+/* Return: 1 = Unknown, 0 = Known */
static int bnx2x_is_drv_version_unknown(struct bnx2x_driver_version *version)
{
- if ((version->major == BNX2X_UNKNOWN_MAJOR_VERSION) &&
- (version->minor == BNX2X_UNKNOWN_MINOR_VERSION) &&
- (version->sub_minor == BNX2X_UNKNOWN_SUB_MINOR_VERSION)) {
+ if ((version->major == (uint16_t)BNX2X_UNKNOWN_MAJOR_VERSION) &&
+ (version->minor == (uint16_t)BNX2X_UNKNOWN_MINOR_VERSION) &&
+ (version->sub_minor == (uint16_t)BNX2X_UNKNOWN_SUB_MINOR_VERSION)) {
return 1;
}
@@ -595,7 +596,7 @@ static void bnx2x_free(nic_t *nic)
/**
* bnx2x_alloc() - Used to allocate a bnx2x structure
*/
-static bnx2x_t *bnx2x_alloc(nic_t * nic)
+static bnx2x_t *bnx2x_alloc(nic_t *nic)
{
bnx2x_t *bp = malloc(sizeof(*bp));
@@ -652,9 +653,13 @@ static int bnx2x_open(nic_t * nic)
if (bp == NULL)
return -ENOMEM;
- if (!bnx2x_is_drv_version_unknown(&bnx2x_version))
- bnx2x_get_drv_version(bp);
- else {
+ if (bnx2x_is_drv_version_unknown(&bnx2x_version)) {
+ /* If version is unknown, go read from ethtool */
+ rc = bnx2x_get_drv_version(bp);
+ if (rc)
+ goto open_error;
+ } else {
+ /* Version is not unknown, jsut use it */
bnx2x_version.major = bp->version.major;
bnx2x_version.minor = bp->version.minor;
bnx2x_version.sub_minor = bp->version.sub_minor;
@@ -663,7 +668,9 @@ static int bnx2x_open(nic_t * nic)
count = 0;
while ((nic->fd < 0) && count < 15) {
/* udev might not have created the file yet */
+ pthread_mutex_unlock(&nic->nic_mutex);
sleep(1);
+ pthread_mutex_lock(&nic->nic_mutex);
nic->fd = open(nic->uio_device_name, O_RDWR | O_NONBLOCK);
if (nic->fd != INVALID_FD) {
@@ -684,7 +691,9 @@ static int bnx2x_open(nic_t * nic)
manually_trigger_uio_event(nic, nic->uio_minor);
/* udev might not have created the file yet */
+ pthread_mutex_unlock(&nic->nic_mutex);
sleep(1);
+ pthread_mutex_lock(&nic->nic_mutex);
count++;
}
@@ -820,7 +829,15 @@ static int bnx2x_open(nic_t * nic)
nic->log_name);
goto open_error;
}
-
+ /* In E1/E1H use pci device function as read from sysfs.
+ * In E2/E3 read physical function from ME register since these chips
+ * support Physical Device Assignment where kernel BDF maybe arbitrary
+ * (depending on hypervisor).
+ */
+ if (CHIP_IS_E2_PLUS(bp)) {
+ func = (bnx2x_rd32(bp, BAR_ME_REGISTER) & ME_REG_ABS_PF_NUM) >>
+ ME_REG_ABS_PF_NUM_SHIFT;
+ }
bp->func = func;
bp->port = bp->func % PORT_MAX;
@@ -976,9 +993,12 @@ static int bnx2x_open(nic_t * nic)
val = bnx2x_rd32(bp, mf_cfg_addr + ovtag_offset);
val &= 0xffff;
/* SD mode, check for valid outer VLAN */
- if (val == 0xffff)
- goto open_error;
-
+ if (val == 0xffff) {
+ LOG_ERR(PFX "%s: Invalid OV detected for SD, "
+ " fallback to SF mode!\n",
+ nic->log_name);
+ goto SF;
+ }
/* Check for iSCSI protocol */
val = bnx2x_rd32(bp, mf_cfg_addr + proto_offset);
if ((val & 6) != 6)
@@ -995,10 +1015,9 @@ static int bnx2x_open(nic_t * nic)
mac[4] = (__u8) (val >> 8);
mac[5] = (__u8) val;
memcpy(nic->mac_addr, mac, 6);
-
}
}
-
+SF:
LOG_INFO(PFX "%s: Using mac address: %02x:%02x:%02x:%02x:%02x:%02x",
nic->log_name,
nic->mac_addr[0], nic->mac_addr[1], nic->mac_addr[2],
@@ -1053,6 +1072,10 @@ open_error:
close(bp->bar0_fd);
bp->bar0_fd = INVALID_FD;
}
+ if (nic->fd != INVALID_FD) {
+ close(nic->fd);
+ nic->fd = INVALID_FD;
+ }
bnx2x_free(nic);
return rc;
@@ -1165,9 +1188,12 @@ static int bnx2x_uio_close_resources(nic_t * nic, NIC_SHUTDOWN_T graceful)
static int bnx2x_close(nic_t * nic, NIC_SHUTDOWN_T graceful)
{
/* Sanity Check: validate the parameters */
- if (nic == NULL || nic->priv == NULL) {
- LOG_ERR(PFX "bnx2x_close(): nic == %p, bp == %p", nic,
- nic->priv);
+ if (nic == NULL) {
+ LOG_ERR(PFX "bnx2x_close(): nic == NULL");
+ return -EINVAL;
+ }
+ if (nic->priv == NULL) {
+ LOG_ERR(PFX "bnx2x_close(): nic->priv == NULL");
return -EINVAL;
}
@@ -1227,8 +1253,8 @@ void bnx2x_start_xmit(nic_t * nic, size_t len, u16_t vlan_id)
rx_bd = (struct eth_rx_bd *)(((__u8 *) bp->tx_ring) + getpagesize());
if ((rx_bd->addr_hi == 0) && (rx_bd->addr_lo == 0)) {
- LOG_DEBUG(PFX "%s: trying to transmit when device is closed",
- nic->log_name);
+ LOG_PACKET(PFX "%s: trying to transmit when device is closed",
+ nic->log_name);
pthread_mutex_unlock(&nic->xmit_mutex);
return;
}
@@ -1251,7 +1277,7 @@ void bnx2x_start_xmit(nic_t * nic, size_t len, u16_t vlan_id)
bp->tx_bd_prod = BNX2X_NEXT_TX_BD(bp->tx_bd_prod);
barrier();
- if (nl_process_if_down == 0) {
+ if (nic->nl_process_if_down == 0) {
bnx2x_doorbell(bp, bp->tx_doorbell, 0x02 |
(bp->tx_bd_prod << 16));
bnx2x_flush_doorbell(bp, bp->tx_doorbell);
@@ -1262,8 +1288,8 @@ void bnx2x_start_xmit(nic_t * nic, size_t len, u16_t vlan_id)
*/
pthread_mutex_unlock(&nic->xmit_mutex);
}
- LOG_DEBUG(PFX "%s: sent %d bytes using bp->tx_prod: %d",
- nic->log_name, len, bp->tx_prod);
+ LOG_PACKET(PFX "%s: sent %d bytes using bp->tx_prod: %d",
+ nic->log_name, len, bp->tx_prod);
}
/**
@@ -1274,8 +1300,8 @@ void bnx2x_start_xmit(nic_t * nic, size_t len, u16_t vlan_id)
*/
int bnx2x_write(nic_t * nic, nic_interface_t * nic_iface, packet_t * pkt)
{
- bnx2x_t *bp = (bnx2x_t *) nic->priv;
- struct uip_stack *uip = &nic_iface->ustack;
+ bnx2x_t *bp;
+ struct uip_stack *uip;
int i = 0;
/* Sanity Check: validate the parameters */
@@ -1285,6 +1311,8 @@ int bnx2x_write(nic_t * nic, nic_interface_t * nic_iface, packet_t * pkt)
" pkt == 0x%x", nic, nic_iface, pkt);
return -EINVAL;
}
+ bp = (bnx2x_t *) nic->priv;
+ uip = &nic_iface->ustack;
if (pkt->buf_size == 0) {
LOG_ERR(PFX "%s: Trying to transmitted 0 sized packet",
@@ -1304,22 +1332,24 @@ int bnx2x_write(nic_t * nic, nic_interface_t * nic_iface, packet_t * pkt)
}
if (pthread_mutex_trylock(&nic->xmit_mutex) != 0) {
- LOG_DEBUG(PFX "%s: Dropped previous transmitted packet",
- nic->log_name);
+ LOG_PACKET(PFX "%s: Dropped previous transmitted packet",
+ nic->log_name);
return -EINVAL;
}
bnx2x_prepare_xmit_packet(nic, nic_iface, pkt);
- bnx2x_start_xmit(nic, pkt->buf_size, nic_iface->vlan_id);
+ bnx2x_start_xmit(nic, pkt->buf_size,
+ (nic_iface->vlan_priority << 12) |
+ nic_iface->vlan_id);
/* bump the cnic dev send statistics */
nic->stats.tx.packets++;
nic->stats.tx.bytes += uip->uip_len;
- LOG_DEBUG(PFX "%s: transmitted %d bytes "
- "dev->tx_cons: %d, dev->tx_prod: %d, dev->tx_bd_prod:%d",
- nic->log_name, pkt->buf_size,
- bp->tx_cons, bp->tx_prod, bp->tx_bd_prod);
+ LOG_PACKET(PFX "%s: transmitted %d bytes "
+ "dev->tx_cons: %d, dev->tx_prod: %d, dev->tx_bd_prod:%d",
+ nic->log_name, pkt->buf_size,
+ bp->tx_cons, bp->tx_prod, bp->tx_bd_prod);
return 0;
}
@@ -1348,7 +1378,7 @@ static inline int bnx2x_get_rx_pad(bnx2x_t * bp, union eth_rx_cqe *cqe)
*/
static int bnx2x_read(nic_t * nic, packet_t * pkt)
{
- bnx2x_t *bp = (bnx2x_t *) nic->priv;
+ bnx2x_t *bp;
int rc = 0;
uint16_t hw_cons, sw_cons, bd_cons, bd_prod;
@@ -1358,6 +1388,7 @@ static int bnx2x_read(nic_t * nic, packet_t * pkt)
" pkt == 0x%x", nic, pkt);
return -EINVAL;
}
+ bp = (bnx2x_t *) nic->priv;
hw_cons = bp->get_rx_cons(bp);
sw_cons = bp->rx_cons;
@@ -1383,8 +1414,8 @@ static int bnx2x_read(nic_t * nic, packet_t * pkt)
}
cqe_fp_flags = cqe->fast_path_cqe.type_error_flags;
- LOG_DEBUG(PFX "%s: clearing rx interrupt: %d %d",
- nic->log_name, sw_cons, hw_cons);
+ LOG_PACKET(PFX "%s: clearing rx interrupt: %d %d",
+ nic->log_name, sw_cons, hw_cons);
msync(cqe, cqe_size, MS_SYNC);
@@ -1416,9 +1447,9 @@ static int bnx2x_read(nic_t * nic, packet_t * pkt)
pkt->vlan_tag = 0;
}
- LOG_DEBUG(PFX
- "%s: processing packet length: %d",
- nic->log_name, len);
+ LOG_PACKET(PFX
+ "%s: processing packet length: %d",
+ nic->log_name, len);
/* bump the cnic dev recv statistics */
nic->stats.rx.packets++;
@@ -1453,14 +1484,16 @@ static int bnx2x_read(nic_t * nic, packet_t * pkt)
*/
static int bnx2x_clear_tx_intr(nic_t * nic)
{
- bnx2x_t *bp = (bnx2x_t *) nic->priv;
- uint16_t hw_cons = bp->get_tx_cons(bp);
+ bnx2x_t *bp;
+ uint16_t hw_cons;
/* Sanity check: ensure the parameters passed in are valid */
if (unlikely(nic == NULL)) {
LOG_ERR(PFX "bnx2x_read() nic == NULL");
return -EINVAL;
}
+ bp = (bnx2x_t *) nic->priv;
+ hw_cons = bp->get_tx_cons(bp);
if (bp->tx_cons == hw_cons) {
if (bp->tx_cons == bp->tx_prod) {
@@ -1473,8 +1506,8 @@ static int bnx2x_clear_tx_intr(nic_t * nic)
return -EAGAIN;
}
- LOG_DEBUG(PFX "%s: clearing tx interrupt [%d %d]",
- nic->log_name, bp->tx_cons, hw_cons);
+ LOG_PACKET(PFX "%s: clearing tx interrupt [%d %d]",
+ nic->log_name, bp->tx_cons, hw_cons);
bp->tx_cons = hw_cons;
/* There is a queued TX packet that needs to be sent out. The usual
@@ -1484,7 +1517,7 @@ static int bnx2x_clear_tx_intr(nic_t * nic)
packet_t *pkt;
int i;
- LOG_DEBUG(PFX "%s: sending queued tx packet", nic->log_name);
+ LOG_PACKET(PFX "%s: sending queued tx packet", nic->log_name);
pkt = nic_dequeue_tx_packet(nic);
/* Got a TX packet buffer of the TX queue and put it onto
@@ -1493,13 +1526,14 @@ static int bnx2x_clear_tx_intr(nic_t * nic)
bnx2x_prepare_xmit_packet(nic, pkt->nic_iface, pkt);
bnx2x_start_xmit(nic, pkt->buf_size,
+ (pkt->nic_iface->vlan_priority << 12) |
pkt->nic_iface->vlan_id);
- LOG_DEBUG(PFX "%s: transmitted queued packet %d bytes "
- "dev->tx_cons: %d, dev->tx_prod: %d, "
- "dev->tx_bd_prod:%d",
- nic->log_name, pkt->buf_size,
- bp->tx_cons, bp->tx_prod, bp->tx_bd_prod);
+ LOG_PACKET(PFX "%s: transmitted queued packet %d bytes "
+ "dev->tx_cons: %d, dev->tx_prod: %d, "
+ "dev->tx_bd_prod:%d",
+ nic->log_name, pkt->buf_size,
+ bp->tx_cons, bp->tx_prod, bp->tx_bd_prod);
return 0;
}
@@ -1512,9 +1546,9 @@ static int bnx2x_clear_tx_intr(nic_t * nic)
hw_cons = bp->get_tx_cons(bp);
if (bp->tx_cons != hw_cons) {
- LOG_DEBUG(PFX
- "%s: clearing tx interrupt [%d %d]",
- nic->log_name, bp->tx_cons, hw_cons);
+ LOG_PACKET(PFX
+ "%s: clearing tx interrupt [%d %d]",
+ nic->log_name, bp->tx_cons, hw_cons);
bp->tx_cons = hw_cons;
break;
diff --git a/iscsiuio/src/unix/libs/bnx2x.h b/iscsiuio/src/unix/libs/bnx2x.h
index 8e923b9..b758179 100644
--- a/iscsiuio/src/unix/libs/bnx2x.h
+++ b/iscsiuio/src/unix/libs/bnx2x.h
@@ -467,6 +467,18 @@ struct client_init_general_data {
#define BAR_XSTRORM_INTMEM 0x420000
#define BAR_TSTRORM_INTMEM 0x430000
+#define BAR_ME_REGISTER 0x450000
+#define ME_REG_PF_NUM_SHIFT 0
+#define ME_REG_PF_NUM\
+ (7L<<ME_REG_PF_NUM_SHIFT) /* Relative PF Num */
+#define ME_REG_VF_VALID (1<<8)
+#define ME_REG_VF_NUM_SHIFT 9
+#define ME_REG_VF_NUM_MASK (0x3f<<ME_REG_VF_NUM_SHIFT)
+#define ME_REG_VF_ERR (0x1<<3)
+#define ME_REG_ABS_PF_NUM_SHIFT 16
+#define ME_REG_ABS_PF_NUM\
+ (7L<<ME_REG_ABS_PF_NUM_SHIFT) /* Absolute PF Num */
+
#define USTORM_RX_PRODS_OFFSET(port, client_id) \
(IS_E1H_OFFSET ? (0x1000 + (port * 0x680) + (client_id * 0x40)) \
: (0x4000 + (port * 0x360) + (client_id * 0x30)))
diff --git a/iscsiuio/src/unix/libs/cnic.c b/iscsiuio/src/unix/libs/cnic.c
index 841c1ac..a81d47b 100644
--- a/iscsiuio/src/unix/libs/cnic.c
+++ b/iscsiuio/src/unix/libs/cnic.c
@@ -125,6 +125,7 @@ static int cnic_arp_send(nic_t * nic, nic_interface_t * nic_iface, int fd,
memcpy(arp->arp_tpa, &dst_ip, 4);
(*nic->nic_library->ops->start_xmit) (nic, pkt_size,
+ (nic_iface->vlan_priority << 12) |
nic_iface->vlan_id);
memcpy(&addr.s_addr, &dst_ip, sizeof(addr.s_addr));
@@ -166,15 +167,6 @@ static int cnic_neigh_soliciation_send(nic_t * nic,
memcpy(ipv6_hdr->ip6_dst.s6_addr, addr6_dst->s6_addr,
sizeof(struct in6_addr));
- LOG_DEBUG(PFX "dst ip addr %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
- ipv6_hdr->ip6_dst.s6_addr16[0],
- ipv6_hdr->ip6_dst.s6_addr16[1],
- ipv6_hdr->ip6_dst.s6_addr16[2],
- ipv6_hdr->ip6_dst.s6_addr16[3],
- ipv6_hdr->ip6_dst.s6_addr16[4],
- ipv6_hdr->ip6_dst.s6_addr16[5],
- ipv6_hdr->ip6_dst.s6_addr16[6],
- ipv6_hdr->ip6_dst.s6_addr16[7]);
nic_fill_ethernet_header(nic_iface, eth, nic->mac_addr, nic->mac_addr,
&pkt_size, (void *)&ipv6_hdr, ETHERTYPE_IPV6);
req_ptr.eth = (void *)eth;
@@ -196,6 +188,7 @@ static int cnic_neigh_soliciation_send(nic_t * nic,
eth->ether_shost[2], eth->ether_shost[3],
eth->ether_shost[4], eth->ether_shost[5]);
(*nic->nic_library->ops->start_xmit) (nic, pkt_size,
+ (nic_iface->vlan_priority << 12) |
nic_iface->vlan_id);
LOG_DEBUG(PFX "%s: Sent cnic ICMPv6 neighbor request %s",
@@ -261,12 +254,7 @@ static int cnic_nl_neigh_rsp(nic_t * nic, int fd,
}
if (ret) {
/* Get link local IPv6 address */
- if (ndpc_request(&nic_iface->ustack, NULL,
- &src_ipv6, GET_LINK_LOCAL_ADDR)) {
- src_ipv6 = (u8_t *)all_zeroes_addr6;
- LOG_DEBUG(PFX "RSP Get LL failed");
- goto src_done;
- }
+ src_ipv6 = (u8_t *)&nic_iface->ustack.linklocal6;
} else {
if (ndpc_request(&nic_iface->ustack,
&path_req->dst.v6_addr,
@@ -288,16 +276,18 @@ src_done:
addr_dst_str, sizeof(addr_dst_str));
}
memcpy(path_rsp->mac_addr, mac_addr, 6);
- path_rsp->vlan_id = path_req->vlan_id;
- path_rsp->pmtu = path_req->pmtu;
+ path_rsp->vlan_id = (nic_iface->vlan_priority << 12) |
+ nic_iface->vlan_id;
+ path_rsp->pmtu = nic_iface->mtu ? nic_iface->mtu : path_req->pmtu;
rc = __kipc_call(fd, ret_ev, sizeof(*ret_ev) + sizeof(*path_rsp));
if (rc > 0) {
LOG_DEBUG(PFX "neighbor reply sent back to kernel "
- "%s at %02x:%02x:%02x:%02x:%02x:%02x",
+ "%s at %02x:%02x:%02x:%02x:%02x:%02x with vlan %d",
addr_dst_str,
mac_addr[0], mac_addr[1],
- mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
+ mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5],
+ nic_iface->vlan_id);
} else {
LOG_ERR(PFX "send neighbor reply failed: %d", rc);
@@ -323,67 +313,18 @@ const static struct timeval tp_wait = {
*/
int cnic_handle_ipv4_iscsi_path_req(nic_t * nic, int fd,
struct iscsi_uevent *ev,
- struct iscsi_path *path)
+ struct iscsi_path *path,
+ nic_interface_t *nic_iface)
{
- nic_interface_t *nic_iface, *vlan_iface;
struct in_addr src_addr, dst_addr,
src_matching_addr, dst_matching_addr, netmask;
__u8 mac_addr[6];
int rc;
uint16_t arp_retry;
int status = 0;
-
- memset(mac_addr, 0, sizeof(mac_addr));
-
- pthread_mutex_lock(&nic_list_mutex);
-
- /* Find the proper interface via VLAN id */
- nic_iface = nic_find_nic_iface_protocol(nic, 0, AF_INET);
- if (nic_iface == NULL) {
- pthread_mutex_unlock(&nic_list_mutex);
- LOG_ERR(PFX "%s: Couldn't find net_iface vlan_id: %d",
- nic->log_name, path->vlan_id);
- return -EINVAL;
- }
- if (path->vlan_id) {
- vlan_iface = nic_find_vlan_iface_protocol(nic, nic_iface,
- path->vlan_id,
- AF_INET);
- if (vlan_iface == NULL) {
- LOG_INFO(PFX "%s couldn't find interface with VLAN = %d"
- "ip_type: 0x%x creating it",
- nic->log_name, path->vlan_id, AF_INET);
-
- /* Create the nic interface */
- vlan_iface = nic_iface_init();
-
- if (vlan_iface == NULL) {
- LOG_ERR(PFX "Couldn't allocate nic_iface for "
- "VLAN: %d", vlan_iface,
- path->vlan_id);
- return -EINVAL;
- }
-
- vlan_iface->protocol = nic_iface->protocol;
- vlan_iface->vlan_id = path->vlan_id;
- vlan_iface->ustack.ip_config =
- nic_iface->ustack.ip_config;
- memcpy(vlan_iface->ustack.hostaddr,
- nic_iface->ustack.hostaddr,
- sizeof(nic_iface->ustack.hostaddr));
- memcpy(vlan_iface->ustack.netmask,
- nic_iface->ustack.netmask,
- sizeof(nic_iface->ustack.netmask));
- nic_add_vlan_iface(nic, nic_iface, vlan_iface);
- } else {
- LOG_INFO(PFX "%s: using existing vlan interface",
- nic->log_name);
- }
- nic_iface = vlan_iface;
- }
-
#define MAX_ARP_RETRY 4
+ memset(mac_addr, 0, sizeof(mac_addr));
memcpy(&dst_addr, &path->dst.v4_addr, sizeof(dst_addr));
memcpy(&src_addr, nic_iface->ustack.hostaddr, sizeof(src_addr));
@@ -445,20 +386,15 @@ int cnic_handle_ipv4_iscsi_path_req(nic_t * nic, int fd,
ts.tv_sec = tp_abs.tv_sec;
ts.tv_nsec = tp_abs.tv_usec * 1000;
- pthread_mutex_unlock(&nic_list_mutex);
+ /* Wait 1s for if_down */
+ pthread_mutex_lock(&nic->nl_process_mutex);
rc = pthread_cond_timedwait
- (&nl_process_if_down_cond,
- &nl_process_mutex, &ts);
+ (&nic->nl_process_if_down_cond,
+ &nic->nl_process_mutex, &ts);
if (rc == ETIMEDOUT) {
- pthread_mutex_unlock(&nl_process_mutex);
-
- if (pthread_mutex_trylock
- (&nic_list_mutex) != 0) {
- arp_retry = MAX_ARP_RETRY;
- goto done;
-
- }
+ pthread_mutex_unlock
+ (&nic->nl_process_mutex);
rc = uip_lookup_arp_entry(dst_addr.
s_addr,
@@ -466,8 +402,9 @@ int cnic_handle_ipv4_iscsi_path_req(nic_t * nic, int fd,
if (rc == 0)
goto done;
} else {
- nl_process_if_down = 0;
- pthread_mutex_unlock(&nl_process_mutex);
+ nic->nl_process_if_down = 0;
+ pthread_mutex_unlock
+ (&nic->nl_process_mutex);
arp_retry = MAX_ARP_RETRY;
goto done;
@@ -491,9 +428,6 @@ done:
cnic_nl_neigh_rsp(nic, fd, ev, path, mac_addr,
nic_iface, status, AF_INET);
-
- pthread_mutex_unlock(&nic_list_mutex);
-
return rc;
}
@@ -507,9 +441,9 @@ done:
*/
int cnic_handle_ipv6_iscsi_path_req(nic_t * nic, int fd,
struct iscsi_uevent *ev,
- struct iscsi_path *path)
+ struct iscsi_path *path,
+ nic_interface_t *nic_iface)
{
- nic_interface_t *nic_iface, *vlan_iface;
__u8 mac_addr[6];
int rc, i;
uint16_t neighbor_retry;
@@ -525,52 +459,6 @@ int cnic_handle_ipv6_iscsi_path_req(nic_t * nic, int fd,
inet_ntop(AF_INET6, &path->dst.v6_addr,
addr_dst_str, sizeof(addr_dst_str));
- pthread_mutex_lock(&nic_list_mutex);
-
- /* Find the proper interface via VLAN id */
- nic_iface = nic_find_nic_iface_protocol(nic, 0, AF_INET6);
- if (nic_iface == NULL) {
- pthread_mutex_unlock(&nic_list_mutex);
- LOG_ERR(PFX "%s: Couldn't find net_iface vlan_id: %d",
- nic->log_name, path->vlan_id);
- return -EINVAL;
- }
- if (path->vlan_id) {
- vlan_iface = nic_find_vlan_iface_protocol(nic, nic_iface,
- path->vlan_id,
- AF_INET6);
- if (vlan_iface == NULL) {
- LOG_INFO(PFX "%s couldn't find interface with VLAN = %d"
- "ip_type: 0x%x creating it",
- nic->log_name, path->vlan_id, AF_INET6);
-
- /* Create the nic interface */
- vlan_iface = nic_iface_init();
-
- if (vlan_iface == NULL) {
- LOG_ERR(PFX "Couldn't allocate nic_iface for "
- "VLAN: %d", vlan_iface,
- path->vlan_id);
- return -EINVAL;
- }
- vlan_iface->protocol = nic_iface->protocol;
- vlan_iface->vlan_id = path->vlan_id;
- vlan_iface->ustack.ip_config =
- nic_iface->ustack.ip_config;
- memcpy(vlan_iface->ustack.hostaddr6,
- nic_iface->ustack.hostaddr6,
- sizeof(nic_iface->ustack.hostaddr6));
- memcpy(vlan_iface->ustack.netmask6,
- nic_iface->ustack.netmask6,
- sizeof(nic_iface->ustack.netmask6));
- nic_add_vlan_iface(nic, nic_iface, vlan_iface);
- } else {
- LOG_INFO(PFX "%s: using existing vlan interface",
- nic->log_name);
- }
- nic_iface = vlan_iface;
- }
-
/* Depending on the IPv6 address of the target we will need to
* determine whether we use the assigned IPv6 address or the
* link local IPv6 address */
@@ -584,12 +472,7 @@ int cnic_handle_ipv6_iscsi_path_req(nic_t * nic, int fd,
if (rc) {
LOG_DEBUG(PFX "Use LL");
/* Get link local IPv6 address */
- if (ndpc_request(&nic_iface->ustack, NULL,
- &addr, GET_LINK_LOCAL_ADDR)) {
- neighbor_retry = MAX_ARP_RETRY;
- LOG_DEBUG(PFX "Use LL failed");
- goto done;
- }
+ addr = (struct in6_addr *)&nic_iface->ustack.linklocal6;
} else {
LOG_DEBUG(PFX "Use Best matched");
if (ndpc_request(&nic_iface->ustack,
@@ -618,21 +501,15 @@ int cnic_handle_ipv6_iscsi_path_req(nic_t * nic, int fd,
memcpy(&netmask.s6_addr, all_zeroes_addr6,
sizeof(struct in6_addr));
- LOG_DEBUG(PFX "src addr %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
- src_addr.s6_addr16[0], src_addr.s6_addr16[1],
- src_addr.s6_addr16[2], src_addr.s6_addr16[3],
- src_addr.s6_addr16[4], src_addr.s6_addr16[5],
- src_addr.s6_addr16[6], src_addr.s6_addr16[7]);
- LOG_DEBUG(PFX "dst addr %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
- dst_addr.s6_addr16[0], dst_addr.s6_addr16[1],
- dst_addr.s6_addr16[2], dst_addr.s6_addr16[3],
- dst_addr.s6_addr16[4], dst_addr.s6_addr16[5],
- dst_addr.s6_addr16[6], dst_addr.s6_addr16[7]);
- LOG_DEBUG(PFX "nm addr %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
- netmask.s6_addr16[0], netmask.s6_addr16[1],
- netmask.s6_addr16[2], netmask.s6_addr16[3],
- netmask.s6_addr16[4], netmask.s6_addr16[5],
- netmask.s6_addr16[6], netmask.s6_addr16[7]);
+ inet_ntop(AF_INET6, &src_addr.s6_addr16, addr_dst_str,
+ sizeof(addr_dst_str));
+ LOG_DEBUG(PFX "src IP addr %s", addr_dst_str);
+ inet_ntop(AF_INET6, &dst_addr.s6_addr16, addr_dst_str,
+ sizeof(addr_dst_str));
+ LOG_DEBUG(PFX "dst IP addr %s", addr_dst_str);
+ inet_ntop(AF_INET6, &netmask.s6_addr16, addr_dst_str,
+ sizeof(addr_dst_str));
+ LOG_DEBUG(PFX "prefix mask %s", addr_dst_str);
for (i = 0; i < 4; i++) {
src_matching_addr.s6_addr32[i] = src_addr.s6_addr32[i] &
@@ -642,24 +519,22 @@ int cnic_handle_ipv6_iscsi_path_req(nic_t * nic, int fd,
if (src_matching_addr.s6_addr32[i] !=
dst_matching_addr.s6_addr32[i]) {
/* No match with the prefix mask, use default route */
- if (ndpc_request(&nic_iface->ustack, NULL, &addr,
- GET_DEFAULT_ROUTER_ADDR)) {
- neighbor_retry = MAX_ARP_RETRY;
- goto done;
- }
- if (memcmp(addr, all_zeroes_addr6, sizeof(*addr)))
- memcpy(&dst_addr, addr, sizeof(dst_addr));
- else {
+ if (memcmp(nic_iface->ustack.default_route_addr6,
+ all_zeroes_addr6, sizeof(*addr))) {
+ memcpy(&dst_addr,
+ nic_iface->ustack.default_route_addr6,
+ sizeof(dst_addr));
+ inet_ntop(AF_INET6, &dst_addr.s6_addr16,
+ addr_dst_str, sizeof(addr_dst_str));
+ LOG_DEBUG(PFX "Use default router IP addr %s",
+ addr_dst_str);
+ break;
+ } else {
neighbor_retry = MAX_ARP_RETRY;
goto done;
}
}
}
- LOG_DEBUG(PFX "dst addr %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
- dst_addr.s6_addr16[0], dst_addr.s6_addr16[1],
- dst_addr.s6_addr16[2], dst_addr.s6_addr16[3],
- dst_addr.s6_addr16[4], dst_addr.s6_addr16[5],
- dst_addr.s6_addr16[6], dst_addr.s6_addr16[7]);
#define MAX_ARP_RETRY 4
neighbor_retry = 0;
@@ -672,6 +547,8 @@ int cnic_handle_ipv6_iscsi_path_req(nic_t * nic, int fd,
goto done;
}
if (!rc) {
+ inet_ntop(AF_INET6, &dst_addr.s6_addr16,
+ addr_dst_str, sizeof(addr_dst_str));
LOG_DEBUG(PFX
"%s: Preparing to send IPv6 neighbor solicitation "
"to dst: '%s'", nic->log_name, addr_dst_str);
@@ -703,20 +580,14 @@ int cnic_handle_ipv6_iscsi_path_req(nic_t * nic, int fd,
ts.tv_sec = tp_abs.tv_sec;
ts.tv_nsec = tp_abs.tv_usec * 1000;
- pthread_mutex_unlock(&nic_list_mutex);
+ pthread_mutex_lock(&nic->nl_process_mutex);
rc = pthread_cond_timedwait
- (&nl_process_if_down_cond,
- &nl_process_mutex, &ts);
+ (&nic->nl_process_if_down_cond,
+ &nic->nl_process_mutex, &ts);
if (rc == ETIMEDOUT) {
- pthread_mutex_unlock(&nl_process_mutex);
-
- if (pthread_mutex_trylock
- (&nic_list_mutex) != 0) {
- neighbor_retry = MAX_ARP_RETRY;
- goto done;
-
- }
+ pthread_mutex_unlock
+ (&nic->nl_process_mutex);
req_ptr.eth = (void *)mac_addr;
req_ptr.ipv6 = (void *)&dst_addr;
@@ -730,8 +601,9 @@ int cnic_handle_ipv6_iscsi_path_req(nic_t * nic, int fd,
if (rc)
goto done;
} else {
- nl_process_if_down = 0;
- pthread_mutex_unlock(&nl_process_mutex);
+ nic->nl_process_if_down = 0;
+ pthread_mutex_unlock
+ (&nic->nl_process_mutex);
neighbor_retry = MAX_ARP_RETRY;
goto done;
@@ -752,9 +624,6 @@ done:
cnic_nl_neigh_rsp(nic, fd, ev, path, mac_addr,
nic_iface, status, AF_INET6);
-
- pthread_mutex_unlock(&nic_list_mutex);
-
return rc;
}
@@ -764,11 +633,12 @@ done:
* @param nic - The nic the message is directed towards
* @param fd - The file descriptor to be used to extract the private data
* @param ev - The iscsi_uevent
- * @param buf - The private message buffer
- * @param buf_len - The private message buffer length
+ * @param path - The private message buffer
+ * @param nic_iface - The nic_iface to use for this connection request
*/
int cnic_handle_iscsi_path_req(nic_t * nic, int fd, struct iscsi_uevent *ev,
- struct iscsi_path *path)
+ struct iscsi_path *path,
+ nic_interface_t *nic_iface)
{
LOG_DEBUG(PFX "%s: Netlink message with VLAN ID: %d, path MTU: %d "
@@ -777,9 +647,11 @@ int cnic_handle_iscsi_path_req(nic_t * nic, int fd, struct iscsi_uevent *ev,
path->ip_addr_len);
if (path->ip_addr_len == 4)
- return cnic_handle_ipv4_iscsi_path_req(nic, fd, ev, path);
+ return cnic_handle_ipv4_iscsi_path_req(nic, fd, ev, path,
+ nic_iface);
else if (path->ip_addr_len == 16)
- return cnic_handle_ipv6_iscsi_path_req(nic, fd, ev, path);
+ return cnic_handle_ipv6_iscsi_path_req(nic, fd, ev, path,
+ nic_iface);
else {
LOG_DEBUG(PFX "%s: unknown ip_addr_len: %d size dropping ",
nic->log_name, path->ip_addr_len);
diff --git a/iscsiuio/src/unix/libs/cnic.h b/iscsiuio/src/unix/libs/cnic.h
index 738deb8..679dab8 100644
--- a/iscsiuio/src/unix/libs/cnic.h
+++ b/iscsiuio/src/unix/libs/cnic.h
@@ -48,6 +48,7 @@ int cnic_nl_open();
void cnic_nl_close();
int cnic_handle_iscsi_path_req(nic_t * nic, int, struct iscsi_uevent *,
- struct iscsi_path *path);
+ struct iscsi_path *path,
+ nic_interface_t *nic_iface);
#endif /* __CNIC_NL_H__ */
diff --git a/iscsiuio/src/unix/main.c b/iscsiuio/src/unix/main.c
index 4f548e9..2008913 100644
--- a/iscsiuio/src/unix/main.c
+++ b/iscsiuio/src/unix/main.c
@@ -141,7 +141,6 @@ signal_wait:
break;
case SIGUSR1:
LOG_INFO("Caught SIGUSR1 signal, rotate log");
-retry:
fini_logger(SHUTDOWN_LOGGER);
rc = init_logger(main_log.log_file);
if (rc != 0)
diff --git a/iscsiuio/src/unix/nic.c b/iscsiuio/src/unix/nic.c
index 0934b56..0b3c538 100644
--- a/iscsiuio/src/unix/nic.c
+++ b/iscsiuio/src/unix/nic.c
@@ -64,6 +64,7 @@
#include "bnx2.h"
#include "bnx2x.h"
+#include "ipv6.h"
/******************************************************************************
* Constants
@@ -118,7 +119,7 @@ static void free_nic_library_handle(nic_lib_handle_t * handle)
* @param handle - This is the library handle to load
* @return 0 = Success; <0 = failure
*/
-static int load_nic_library(nic_lib_handle_t * handle)
+static int load_nic_library(nic_lib_handle_t *handle)
{
int rc;
char *library_name;
@@ -172,7 +173,7 @@ static int load_nic_library(nic_lib_handle_t * handle)
return 0;
- error:
+error:
pthread_mutex_unlock(&handle->mutex);
return rc;
@@ -197,9 +198,10 @@ int load_all_nic_libraries()
handle->ops = (*nic_get_ops[i]) ();
rc = load_nic_library(handle);
- if (rc != 0)
+ if (rc != 0) {
+ free_nic_library_handle(handle);
return rc;
-
+ }
/* Add the CNIC library to the list of library handles */
pthread_mutex_lock(&nic_lib_list_mutex);
@@ -270,7 +272,7 @@ NIC_LIBRARY_EXIST_T does_nic_uio_name_exist(char *name)
rc = NIC_LIBRARY_DOESNT_EXIST;
- done:
+done:
pthread_mutex_unlock(&nic_lib_list_mutex);
return rc;
}
@@ -300,7 +302,7 @@ NIC_LIBRARY_EXIST_T does_nic_library_exist(char *name)
rc = NIC_LIBRARY_DOESNT_EXIST;
- done:
+done:
pthread_mutex_unlock(&nic_lib_list_mutex);
return rc;
}
@@ -366,7 +368,7 @@ int find_nic_lib_using_pci_id(uint32_t vendor, uint32_t device,
}
rc = -EINVAL;
- done:
+done:
pthread_mutex_unlock(&nic_lib_list_mutex);
return rc;
@@ -393,13 +395,14 @@ nic_t *nic_init()
nic->next = NULL;
nic->thread = INVALID_THREAD;
nic->enable_thread = INVALID_THREAD;
- nic->flags |= NIC_UNITIALIZED | NIC_DISABLED;
- nic->state |= NIC_STOPPED;
+ nic->flags |= NIC_DISABLED;
+ nic->state = NIC_STOPPED;
nic->free_packet_queue = NULL;
nic->tx_packet_queue = NULL;
nic->nic_library = NULL;
nic->pci_id = NULL;
+ /* nic_mutex is used to protect nic_ops */
pthread_mutex_init(&nic->nic_mutex, NULL);
pthread_mutex_init(&nic->xmit_mutex, NULL);
pthread_mutex_init(&nic->free_packet_queue_mutex, NULL);
@@ -411,6 +414,15 @@ nic_t *nic_init()
nic->rx_poll_usec = DEFAULT_RX_POLL_USEC;
+ pthread_mutex_init(&nic->nl_process_mutex, NULL);
+ pthread_cond_init(&nic->nl_process_if_down_cond, NULL);
+ pthread_cond_init(&nic->nl_process_cond, NULL);
+ nic->nl_process_thread = INVALID_THREAD;
+ nic->nl_process_if_down = 0;
+ nic->nl_process_head = 0;
+ nic->nl_process_tail = 0;
+ memset(&nic->nl_process_ring, 0, sizeof(nic->nl_process_ring));
+
return nic;
}
@@ -432,7 +444,6 @@ void nic_add(nic_t * nic)
/**
* nic_remove() - Used to remove the NIC for the nic list
- nic_list_mutex must be taken
* @param nic - the nic to remove
*/
int nic_remove(nic_t * nic)
@@ -451,41 +462,66 @@ int nic_remove(nic_t * nic)
nic->ops->close(nic, 0);
nic->state = NIC_EXIT;
- pthread_mutex_unlock(&nic->nic_mutex);
if (nic->enable_thread != INVALID_THREAD) {
- LOG_ERR(PFX "%s: Canceling nic enable thread", nic->log_name);
+ LOG_DEBUG(PFX "%s: Canceling nic enable thread", nic->log_name);
rc = pthread_cancel(nic->enable_thread);
if (rc != 0)
- LOG_ERR(PFX "%s: Couldn't send cancel to nic enable "
- "thread", nic->log_name);
+ LOG_DEBUG(PFX "%s: Couldn't send cancel to nic enable "
+ "thread", nic->log_name);
- LOG_ERR(PFX "%s: Waiting to join nic enable thread",
- nic->log_name);
+ LOG_DEBUG(PFX "%s: Waiting to join nic enable thread",
+ nic->log_name);
rc = pthread_join(nic->enable_thread, &res);
if (rc != 0)
- LOG_ERR(PFX "%s: Couldn't join to canceled enable nic "
- "thread", nic->log_name);
+ LOG_DEBUG(PFX "%s: Couldn't join to canceled enable "
+ "nic thread", nic->log_name);
nic->enable_thread = INVALID_THREAD;
+ LOG_DEBUG(PFX "%s: nic enable thread cleaned", nic->log_name);
+ } else {
+ LOG_DEBUG(PFX "%s: NIC enable thread already canceled",
+ nic->log_name);
}
+
if (nic->thread != INVALID_THREAD) {
- LOG_ERR(PFX "%s: Canceling nic thread", nic->log_name);
+ LOG_DEBUG(PFX "%s: Canceling nic thread", nic->log_name);
rc = pthread_cancel(nic->thread);
if (rc != 0)
- LOG_ERR(PFX "%s: Couldn't send cancel to nic",
- nic->log_name);
+ LOG_DEBUG(PFX "%s: Couldn't send cancel to nic",
+ nic->log_name);
- LOG_ERR(PFX "%s: Waiting to join nic thread", nic->log_name);
+ LOG_DEBUG(PFX "%s: Waiting to join nic thread", nic->log_name);
rc = pthread_join(nic->thread, &res);
if (rc != 0)
- LOG_ERR(PFX "%s: Couldn't join to canceled nic thread",
- nic->log_name);
-
+ LOG_DEBUG(PFX "%s: Couldn't join to canceled nic "
+ "thread", nic->log_name);
nic->thread = INVALID_THREAD;
+ LOG_DEBUG(PFX "%s: nic thread cleaned", nic->log_name);
+ } else {
+ LOG_DEBUG(PFX "%s: NIC thread already canceled", nic->log_name);
+ }
+
+ if (nic->nl_process_thread != INVALID_THREAD) {
+ LOG_DEBUG(PFX "%s: Canceling nic nl thread", nic->log_name);
+
+ rc = pthread_cancel(nic->nl_process_thread);
+ if (rc != 0)
+ LOG_DEBUG(PFX "%s: Couldn't send cancel to nic nl "
+ "thread", nic->log_name);
+
+ LOG_DEBUG(PFX "%s: Waiting to join nic nl thread",
+ nic->log_name);
+ rc = pthread_join(nic->nl_process_thread, &res);
+ if (rc != 0)
+ LOG_DEBUG(PFX "%s: Couldn't join to canceled nic nl "
+ "thread", nic->log_name);
+ nic->nl_process_thread = INVALID_THREAD;
+ LOG_DEBUG(PFX "%s: nic nl thread cleaned", nic->log_name);
} else {
- LOG_ERR(PFX "%s: NIC thread already canceled", nic->log_name);
+ LOG_DEBUG(PFX "%s: NIC nl thread already canceled",
+ nic->log_name);
}
current = prev = nic_list;
@@ -505,7 +541,7 @@ int nic_remove(nic_t * nic)
/* Before freeing the nic, must free all the associated
nic_iface */
- nic_iface = nic->nic_iface;
+ nic_iface = current->nic_iface;
while (nic_iface != NULL) {
vlan_iface = nic_iface->vlan_next;
while (vlan_iface != NULL) {
@@ -608,7 +644,7 @@ error:
}
/**
- * net_iface_init() - This function is used to add an interface to the
+ * nic_iface_init() - This function is used to add an interface to the
* structure cnic_uio
* @return 0 on success, <0 on failure
*/
@@ -623,6 +659,8 @@ nic_interface_t *nic_iface_init()
memset(nic_iface, 0, sizeof(*nic_iface));
nic_iface->next = NULL;
nic_iface->vlan_next = NULL;
+ nic_iface->iface_num = IFACE_NUM_INVALID;
+ nic_iface->request_type = IP_CONFIG_OFF;
return nic_iface;
}
@@ -630,112 +668,57 @@ nic_interface_t *nic_iface_init()
/**
* nic_add_nic_iface() - This function is used to add an interface to the
* nic structure
+ * Called with nic_mutex held
* @param nic - struct nic device to add the interface to
* @param nic_iface - network interface used to add to the nic
* @return 0 on success, <0 on failure
*/
-int nic_add_nic_iface(nic_t * nic, nic_interface_t * nic_iface)
+int nic_add_nic_iface(nic_t *nic, nic_interface_t *nic_iface)
{
+ nic_interface_t *current, *prev;
+
+ /* Make sure it doesn't already exist */
+ current = nic_find_nic_iface(nic, nic_iface->protocol,
+ nic_iface->vlan_id, nic_iface->iface_num,
+ nic_iface->request_type);
+ if (current) {
+ LOG_DEBUG(PFX "%s: nic interface for VLAN: %d, protocol: %d"
+ " already exist", nic->log_name, nic_iface->vlan_id,
+ nic_iface->protocol);
+ return 0;
+ }
- pthread_mutex_lock(&nic->nic_mutex);
-
- /* Add the nic_interface */
- if (nic->nic_iface == NULL) {
- nic->nic_iface = nic_iface;
- } else {
- nic_interface_t *current = nic->nic_iface;
-
- /* Check to see if this interface already exists via 2
- * conditions: 1) VLAN 2) protocol */
- while (current != NULL) {
- if ((current->protocol == nic_iface->protocol) &&
- (current->vlan_id == nic_iface->vlan_id)) {
- LOG_WARN(PFX "%s: nic interface alread exists"
- "for VLAN: %d, protocol: %d",
- nic->log_name, current->vlan_id,
- current->protocol);
- goto error;
- }
- current = current->next;
- }
-
- /* This interface doesn't exists, we can safely add
- * this nic interface */
- current = nic->nic_iface;
- while (current->next != NULL) {
- current = current->next;
+ prev = NULL;
+ current = nic->nic_iface;
+ while (current != NULL) {
+ if (current->protocol == nic_iface->protocol) {
+ /* Replace parent */
+ nic_iface->vlan_next = current;
+ nic_iface->next = current->next;
+ current->next = NULL;
+ if (prev)
+ prev->next = nic_iface;
+ else
+ nic->nic_iface = nic_iface;
+ goto done;
}
-
- current->next = nic_iface;
+ prev = current;
+ current = current->next;
}
-
+ nic_iface->next = nic->nic_iface;
+ nic->nic_iface = nic_iface;
+done:
/* Set nic_interface common fields */
nic_iface->parent = nic;
+ memcpy(&nic_iface->ustack.uip_ethaddr.addr, nic->mac_addr, ETH_ALEN);
nic->num_of_nic_iface++;
LOG_INFO(PFX "%s: Added nic interface for VLAN: %d, protocol: %d",
nic->log_name, nic_iface->vlan_id, nic_iface->protocol);
-error:
- pthread_mutex_unlock(&nic->nic_mutex);
-
return 0;
}
-/**
- * nic_add_vlan_iface() - This function is used to add a vlan interface to the
- * nic structure
- * @param nic - struct nic device to add the interface to
- * @param nic_iface - network interface to be added to
- * @param vlan_iface - vlan interface used to add to the nic_iface
- * @return 0 on success, <0 on failure
- */
-int nic_add_vlan_iface(nic_t *nic, nic_interface_t *nic_iface,
- nic_interface_t *vlan_iface)
-{
- pthread_mutex_lock(&nic->nic_mutex);
-
- /* Add the nic_interface */
- if (nic_iface == NULL)
- goto error;
- else {
- nic_interface_t *current = nic_iface->vlan_next;
-
- /* Check to see if this interface already exists via 2
- * conditions: 1) VLAN 2) protocol */
- while (current != NULL) {
- if ((current->protocol == vlan_iface->protocol) &&
- (current->vlan_id == vlan_iface->vlan_id)) {
- LOG_WARN(PFX "%s: vlan interface already exists"
- "for VLAN: %d, protocol: %d",
- nic->log_name, current->vlan_id,
- current->protocol);
- goto error;
- }
- current = current->vlan_next;
- }
-
- /* This interface doesn't exists, we can safely add
- * this nic interface */
- current = nic_iface;
- while (current->vlan_next != NULL)
- current = current->vlan_next;
-
- current->vlan_next = vlan_iface;
- }
-
- /* Set nic_interface common fields */
- vlan_iface->parent = nic;
- nic->num_of_nic_iface++;
-
- LOG_INFO(PFX "%s: Added vlan interface for VLAN: %d, protocol: %d",
- nic->log_name, vlan_iface->vlan_id, vlan_iface->protocol);
-
-error:
- pthread_mutex_unlock(&nic->nic_mutex);
-
- return 0;
-}
/******************************************************************************
* Routine to process interrupts from the NIC device
******************************************************************************/
@@ -752,13 +735,13 @@ int nic_process_intr(nic_t * nic, int discard_check)
struct timeval tv;
/* Simple sanity checks */
- if ((discard_check != 1) && (nic->state & NIC_RUNNING) != NIC_RUNNING) {
+ if (discard_check != 1 && nic->state != NIC_RUNNING) {
LOG_ERR(PFX "%s: Couldn't process interupt NIC not running",
nic->log_name);
return -EBUSY;
}
- if ((discard_check != 1) && (nic->fd == INVALID_FD)) {
+ if (discard_check != 1 && nic->fd == INVALID_FD) {
LOG_ERR(PFX "%s: NIC fd not valid", nic->log_name);
return -EIO;
}
@@ -767,11 +750,12 @@ int nic_process_intr(nic_t * nic, int discard_check)
FD_SET(nic->fd, &fdset);
tv.tv_sec = 0;
- if (nic->state & NIC_LONG_SLEEP) {
+ pthread_mutex_lock(&nic->nic_mutex);
+ if (nic->flags & NIC_LONG_SLEEP)
tv.tv_usec = 1000;
- } else {
+ else
tv.tv_usec = nic->rx_poll_usec;
- }
+ pthread_mutex_unlock(&nic->nic_mutex);
/* Wait for an interrupt to come in or timeout */
ret = select(nic->fd + 1, &fdset, NULL, NULL, &tv);
@@ -796,20 +780,20 @@ int nic_process_intr(nic_t * nic, int discard_check)
pthread_mutex_lock(&nic->nic_mutex);
if (ret > 0) {
nic->stats.interrupts++;
- LOG_DEBUG(PFX "%s: interrupt count: %d prev: %d",
- nic->log_name, count, nic->intr_count);
+ LOG_PACKET(PFX "%s: interrupt count: %d prev: %d",
+ nic->log_name, count, nic->intr_count);
if (count == nic->intr_count) {
- LOG_WARN(PFX "%s: got interrupt but count still the "
- "same", nic->log_name, count);
+ LOG_PACKET(PFX "%s: got interrupt but count still the "
+ "same", nic->log_name, count);
}
/* Check if we missed an interrupt. With UIO,
* the count should be incremental */
if (count != nic->intr_count + 1) {
nic->stats.missed_interrupts++;
- LOG_DEBUG(PFX "%s: Missed interrupt! on %d not %d",
- nic->log_name, count, nic->intr_count);
+ LOG_PACKET(PFX "%s: Missed interrupt! on %d not %d",
+ nic->log_name, count, nic->intr_count);
}
nic->intr_count = count;
@@ -833,9 +817,14 @@ static void prepare_ipv4_packet(nic_t * nic,
int queue_rc;
int vlan_id = 0;
- if (nic_iface->vlan_id && !(NIC_VLAN_STRIP_ENABLED & nic->flags))
- vlan_id = nic_iface->vlan_id;
-
+ /* If the rx vlan tag is not stripped and vlan is present in the pkt,
+ manual stripping is required because tx is using hw vlan tag! */
+ if (pkt->network_layer == pkt->data_link_layer +
+ sizeof(struct uip_vlan_eth_hdr)) {
+ /* VLAN is detected in the pkt buf */
+ memcpy(pkt->data_link_layer + 12, pkt->network_layer - 2,
+ pkt->buf_size - sizeof(struct uip_vlan_eth_hdr) + 2);
+ }
dest_ipv4_addr = uip_determine_dest_ipv4_addr(ustack, ipaddr);
if (dest_ipv4_addr == LOCAL_BROADCAST) {
uip_build_eth_header(ustack, ipaddr, NULL, pkt, vlan_id);
@@ -867,9 +856,12 @@ static void prepare_ipv6_packet(nic_t * nic,
struct uip_vlan_eth_hdr *eth_vlan;
int vlan_id = 0;
- if (nic_iface->vlan_id && !(NIC_VLAN_STRIP_ENABLED & nic->flags))
- vlan_id = nic_iface->vlan_id;
-
+ if (pkt->network_layer == pkt->data_link_layer +
+ sizeof(struct uip_vlan_eth_hdr)) {
+ /* VLAN is detected in the pkt buf */
+ memcpy(pkt->data_link_layer + 12, pkt->network_layer - 2,
+ pkt->buf_size - sizeof(struct uip_vlan_eth_hdr) + 2);
+ }
eth = (struct uip_eth_hdr *)ustack->data_link_layer;
eth_vlan = (struct uip_vlan_eth_hdr *)ustack->data_link_layer;
if (vlan_id == 0) {
@@ -897,96 +889,96 @@ static void prepare_ustack(nic_t * nic,
* there is a VLAN tag or not, or if the hardware
* has stripped out the
* VLAN tag */
- if ((nic_iface->vlan_id == 0) || (NIC_VLAN_STRIP_ENABLED & nic->flags)) {
- ustack->network_layer = ustack->data_link_layer +
- sizeof(struct uip_eth_hdr);
- } else {
- ustack->network_layer = ustack->data_link_layer +
- sizeof(struct uip_vlan_eth_hdr);
- }
+ ustack->network_layer = ustack->data_link_layer +
+ sizeof(struct uip_eth_hdr);
/* Init buffer to be IPv6 */
if (nic_iface->ustack.ip_config == IPV6_CONFIG_DHCP ||
nic_iface->ustack.ip_config == IPV6_CONFIG_STATIC) {
eth = (struct ether_header *)ustack->data_link_layer;
- eth->ether_type = UIP_ETHTYPE_IPv6;
+ eth->ether_type = htons(UIP_ETHTYPE_IPv6);
}
}
-static int check_timers(nic_t * nic,
- struct timer *periodic_timer, struct timer *arp_timer)
+int do_timers_per_nic_iface(nic_t *nic, nic_interface_t *nic_iface,
+ struct timer *arp_timer)
{
- if (timer_expired(periodic_timer)) {
- int i;
- nic_interface_t *current;
-
- timer_reset(periodic_timer);
+ packet_t *pkt;
+ struct uip_stack *ustack = &nic_iface->ustack;
+ int i;
- pthread_mutex_lock(&nic->nic_mutex);
+ pkt = get_next_free_packet(nic);
+ if (pkt == NULL)
+ return -EIO;
- current = nic->nic_iface;
- while (current != NULL) {
- packet_t *pkt;
- struct uip_stack *ustack = &current->ustack;
+ if (nic_iface->ustack.ip_config == AF_INET) {
+ for (i = 0; i < UIP_UDP_CONNS; i++) {
+ prepare_ustack(nic, nic_iface, ustack, pkt);
- pkt = get_next_free_packet(nic);
- if (pkt == NULL) {
- current = current->next;
- continue;
+ uip_udp_periodic(ustack, i);
+ /* If the above function invocation resulted
+ * in data that should be sent out on the
+ * network, the global variable uip_len is
+ * set to a value > 0. */
+ if (ustack->uip_len > 0) {
+ pkt->buf_size = ustack->uip_len;
+ prepare_ipv4_packet(nic, nic_iface, ustack,
+ pkt);
+ (*nic->ops->write) (nic, nic_iface, pkt);
+ ustack->uip_len = 0;
}
-
- for (i = 0; i < UIP_UDP_CONNS; i++) {
- prepare_ustack(nic, current, ustack, pkt);
-
- uip_udp_periodic(ustack, i);
- /* If the above function invocation resulted
- * in data that should be sent out on the
- * network, the global variable uip_len is
- * set to a value > 0. */
- if (ustack->uip_len > 0) {
- pkt->buf_size = ustack->uip_len;
-
- prepare_ipv4_packet(nic,
- current,
- ustack, pkt);
-
- (*nic->ops->write) (nic, current, pkt);
- ustack->uip_len = 0;
- }
+ }
+ } else {
+ /* Added periodic poll for IPv6 NDP engine */
+ if (ustack->ndpc != NULL) { /* If engine is active */
+ prepare_ustack(nic, nic_iface, ustack, pkt);
+
+ uip_ndp_periodic(ustack);
+ /* If the above function invocation resulted
+ * in data that should be sent out on the
+ * network, the global variable uip_len is
+ * set to a value > 0. */
+ if (ustack->uip_len > 0) {
+ pkt->buf_size = ustack->uip_len;
+ prepare_ipv6_packet(nic, nic_iface, ustack,
+ pkt);
+ (*nic->ops->write) (nic, nic_iface, pkt);
+ ustack->uip_len = 0;
}
+ }
+ }
+ /* Call the ARP timer function every 10 seconds. */
+ if (timer_expired(arp_timer)) {
+ timer_reset(arp_timer);
+ uip_arp_timer();
+ }
+ put_packet_in_free_queue(pkt, nic);
+ return 0;
+}
- /* Added periodic poll for IPv6 NDP engine */
- if (ustack->ndpc != NULL) { /* If engine is active */
- prepare_ustack(nic, current, ustack, pkt);
-
- uip_ndp_periodic(ustack);
- /* If the above function invocation resulted
- * in data that should be sent out on the
- * network, the global variable uip_len is
- * set to a value > 0. */
- if (ustack->uip_len > 0) {
- pkt->buf_size = ustack->uip_len;
- prepare_ipv6_packet(nic,
- current,
- ustack, pkt);
- (*nic->ops->write) (nic, current, pkt);
- ustack->uip_len = 0;
- }
- }
+static int check_timers(nic_t *nic,
+ struct timer *periodic_timer, struct timer *arp_timer)
+{
+ if (timer_expired(periodic_timer)) {
+ nic_interface_t *nic_iface, *vlan_iface;
- /* Call the ARP timer function every 10 seconds. */
- if (timer_expired(arp_timer)) {
- timer_reset(arp_timer);
- uip_arp_timer();
- }
+ timer_reset(periodic_timer);
- put_packet_in_free_queue(pkt, nic);
+ pthread_mutex_lock(&nic->nic_mutex);
- current = current->next;
+ nic_iface = nic->nic_iface;
+ while (nic_iface != NULL) {
+ do_timers_per_nic_iface(nic, nic_iface, arp_timer);
+ vlan_iface = nic_iface->vlan_next;
+ while (vlan_iface != NULL) {
+ do_timers_per_nic_iface(nic, vlan_iface,
+ arp_timer);
+ vlan_iface = vlan_iface->vlan_next;
+ }
+ nic_iface = nic_iface->next;
}
pthread_mutex_unlock(&nic->nic_mutex);
}
-
return 0;
}
@@ -1012,109 +1004,71 @@ int process_packets(nic_t * nic,
uint16_t type = 0;
int af_type = 0;
struct uip_stack *ustack;
- nic_interface_t *vlan_iface;
+ struct ip_hdr *ip;
+ pIPV6_HDR ip6;
+ void *dst_ip;
+ uint16_t vlan_id;
- if ((pkt->vlan_tag == 0) ||
+ pkt->data_link_layer = pkt->buf;
+
+ vlan_id = pkt->vlan_tag & 0xFFF;
+ if ((vlan_id == 0) ||
(NIC_VLAN_STRIP_ENABLED & nic->flags)) {
type = ntohs(ETH_BUF(pkt->buf)->type);
+ pkt->network_layer = pkt->data_link_layer +
+ sizeof(struct uip_eth_hdr);
} else {
type = ntohs(VLAN_ETH_BUF(pkt->buf)->type);
+ pkt->network_layer = pkt->data_link_layer +
+ sizeof(struct uip_vlan_eth_hdr);
}
switch (type) {
case UIP_ETHTYPE_IPv6:
af_type = AF_INET6;
+ ip6 = (pIPV6_HDR) pkt->network_layer;
+ dst_ip = (void *)&ip6->ipv6_dst;
break;
case UIP_ETHTYPE_IPv4:
- af_type = AF_INET;
- break;
case UIP_ETHTYPE_ARP:
af_type = AF_INET;
+ ip = (struct ip_hdr *) pkt->network_layer;
+ dst_ip = (void *)&ip->destipaddr;
break;
default:
- LOG_DEBUG(PFX "%s: Ignoring vlan:0x%x ethertype:0x%x",
- nic->log_name, pkt->vlan_tag, type);
+ LOG_PACKET(PFX "%s: Ignoring vlan:0x%x ethertype:0x%x",
+ nic->log_name, vlan_id, type);
goto done;
}
- /* check if we have the given VLAN interface */
- if (nic_iface == NULL) {
- nic_iface = nic_find_nic_iface_protocol(nic, 0,
- af_type);
- if (nic_iface == NULL) {
- LOG_INFO(PFX "%s: Couldn't find interface for "
- "VLAN: %d af_type %d creating it",
- nic->log_name, pkt->vlan_tag, af_type);
-
- /* Create the vlan interface */
- nic_iface = nic_iface_init();
-
- if (nic_iface == NULL) {
- LOG_WARN(PFX "%s: Couldn't "
- "allocate "
- "nic_iface for "
- "VLAN: %d af_type %d",
- nic->log_name, pkt->vlan_tag,
- af_type);
- rc = 0;
- goto done;
- }
-
- nic_iface->protocol = af_type;
- nic_iface->vlan_id = 0;
- nic_add_nic_iface(nic, nic_iface);
+ pthread_mutex_lock(&nic->nic_mutex);
- persist_all_nic_iface(nic);
- }
- if (pkt->vlan_tag) {
- vlan_iface = nic_find_vlan_iface_protocol(nic,
- nic_iface, pkt->vlan_tag,
- af_type);
- if (vlan_iface == NULL) {
- LOG_INFO(PFX "%s couldn't find "
- "interface with VLAN ="
- " %d ip_type: 0x%x "
- "creating it",
- nic->log_name, pkt->vlan_tag,
- af_type);
-
- /* Create the nic interface */
- vlan_iface = nic_iface_init();
-
- if (vlan_iface == NULL) {
- LOG_ERR(PFX "Couldn't allocate "
- "nic_iface for VLAN: %d",
- vlan_iface,
- pkt->vlan_tag);
- rc = 0;
- goto done;
- }
- vlan_iface->protocol = af_type;
- vlan_iface->vlan_id = pkt->vlan_tag;
- nic_add_vlan_iface(nic, nic_iface,
- vlan_iface);
- /* TODO: When VLAN support is placed */
- /* in the iface file revisit this */
- /* code */
- memcpy(vlan_iface->ustack.hostaddr,
- nic_iface->ustack.hostaddr,
- sizeof(nic_iface->ustack.hostaddr));
- memcpy(vlan_iface->ustack.netmask,
- nic_iface->ustack.netmask,
- sizeof(nic_iface->ustack.netmask));
- memcpy(vlan_iface->ustack.netmask6,
- nic_iface->ustack.netmask6,
- sizeof(nic_iface->ustack.netmask6));
- memcpy(vlan_iface->ustack.hostaddr6,
- nic_iface->ustack.hostaddr6,
- sizeof(nic_iface->ustack.hostaddr6));
-
- persist_all_nic_iface(nic);
- }
- nic_iface = vlan_iface;
+ /* check if we have the given VLAN interface */
+ if (nic_iface != NULL) {
+ if (vlan_id != nic_iface->vlan_id) {
+ /* Matching nic_iface not found, drop */
+ pthread_mutex_unlock(&nic->nic_mutex);
+ rc = EINVAL; /* Return the +error code */
+ goto done;
}
+ goto nic_iface_present;
}
+ /* Best effort to find the correct instance
+ Input: protocol and vlan_tag */
+ nic_iface = nic_find_nic_iface(nic, af_type, vlan_id,
+ IFACE_NUM_INVALID,
+ IP_CONFIG_OFF);
+ if (nic_iface == NULL) {
+ /* Matching nic_iface not found */
+ pthread_mutex_unlock(&nic->nic_mutex);
+ LOG_PACKET(PFX "%s: Couldn't find interface for "
+ "VLAN: %d af_type %d",
+ nic->log_name, vlan_id, af_type);
+ rc = EINVAL; /* Return the +error code */
+ goto done;
+ }
+nic_iface_present:
pkt->nic_iface = nic_iface;
ustack = &nic_iface->ustack;
@@ -1123,27 +1077,17 @@ int process_packets(nic_t * nic,
ustack->uip_len = pkt->buf_size;
ustack->data_link_layer = pkt->buf;
- pkt->data_link_layer = pkt->buf;
-
/* Adjust the network layer pointer depending if there is a
* VLAN tag or not, or if the hardware has stripped out the
* VLAN tag */
- if ((pkt->vlan_tag == 0) ||
- (NIC_VLAN_STRIP_ENABLED & nic->flags)) {
+ if ((vlan_id == 0) ||
+ (NIC_VLAN_STRIP_ENABLED & nic->flags))
ustack->network_layer = ustack->data_link_layer +
sizeof(struct uip_eth_hdr);
- pkt->network_layer = pkt->data_link_layer +
- sizeof(struct uip_eth_hdr);
- type = ntohs(ETH_BUF(pkt->buf)->type);
- } else {
+ else
ustack->network_layer = ustack->data_link_layer +
sizeof(struct uip_vlan_eth_hdr);
- pkt->network_layer = pkt->data_link_layer +
- sizeof(struct uip_vlan_eth_hdr);
- type = ntohs(VLAN_ETH_BUF(pkt->buf)->type);
- }
- pthread_mutex_lock(&nic->nic_mutex);
/* determine how we should process this packet based on the
* ethernet type */
switch (type) {
@@ -1270,25 +1214,174 @@ static int process_dhcp_loop(nic_t * nic,
}
if (timercmp(&total_time, &current_time, <)) {
- LOG_ERR(PFX "%s: timeout waiting for DHCP",
+ LOG_ERR(PFX "%s: timeout waiting for DHCP/NDP",
nic->log_name);
+ if (nic_iface->ustack.ip_config == IPV6_CONFIG_DHCP ||
+ nic_iface->ustack.ip_config == IPV6_CONFIG_STATIC)
+ n->retry_count = IPV6_MAX_ROUTER_SOL_RETRY;
return -EIO;
}
}
if (nic->flags & NIC_GOING_DOWN)
return -EIO;
+ else if (nic->flags & NIC_DISABLED)
+ return -EINVAL;
else
return 0;
}
+/* Called with nic_mutex locked */
+static int do_acquisition(nic_t *nic, nic_interface_t *nic_iface,
+ struct timer *periodic_timer, struct timer *arp_timer)
+{
+ struct in_addr addr;
+ struct in6_addr addr6;
+ void *res;
+ char buf[INET6_ADDRSTRLEN];
+ int rc = -1;
+
+ /* New acquisition */
+ uip_init(&nic_iface->ustack, nic->flags & NIC_IPv6_ENABLED);
+ memcpy(&nic_iface->ustack.uip_ethaddr.addr, nic->mac_addr, ETH_ALEN);
+
+ LOG_INFO(PFX "%s: Initialized ip stack: VLAN: %d",
+ nic->log_name, nic_iface->vlan_id);
+
+ LOG_INFO(PFX "%s: mac: %02x:%02x:%02x:%02x:%02x:%02x",
+ nic->log_name,
+ nic_iface->mac_addr[0],
+ nic_iface->mac_addr[1],
+ nic_iface->mac_addr[2],
+ nic_iface->mac_addr[3],
+ nic_iface->mac_addr[4],
+ nic_iface->mac_addr[5]);
+
+ switch (nic_iface->ustack.ip_config) {
+ case IPV4_CONFIG_STATIC:
+ memcpy(&addr.s_addr, nic_iface->ustack.hostaddr,
+ sizeof(addr.s_addr));
+
+ LOG_INFO(PFX "%s: Using IP address: %s",
+ nic->log_name, inet_ntoa(addr));
+
+ memcpy(&addr.s_addr, nic_iface->ustack.netmask,
+ sizeof(addr.s_addr));
+
+ LOG_INFO(PFX "%s: Using netmask: %s",
+ nic->log_name, inet_ntoa(addr));
+
+ set_uip_stack(&nic_iface->ustack,
+ &nic_iface->ustack.hostaddr,
+ &nic_iface->ustack.netmask,
+ &nic_iface->ustack.default_route_addr,
+ nic_iface->mac_addr);
+ break;
+
+ case IPV4_CONFIG_DHCP:
+ set_uip_stack(&nic_iface->ustack,
+ &nic_iface->ustack.hostaddr,
+ &nic_iface->ustack.netmask,
+ &nic_iface->ustack.default_route_addr,
+ nic_iface->mac_addr);
+ if (dhcpc_init(nic, &nic_iface->ustack,
+ nic_iface->mac_addr, ETH_ALEN)) {
+ if (nic_iface->ustack.dhcpc) {
+ LOG_DEBUG(PFX "%s: DHCPv4 engine already "
+ "initialized!", nic->log_name);
+ goto skip;
+ } else {
+ LOG_DEBUG(PFX "%s: DHCPv4 engine failed "
+ "initialization!", nic->log_name);
+ goto error;
+ }
+ }
+ pthread_mutex_unlock(&nic->nic_mutex);
+ rc = process_dhcp_loop(nic, nic_iface, periodic_timer,
+ arp_timer);
+ pthread_mutex_lock(&nic->nic_mutex);
+
+ if (rc) {
+ LOG_ERR(PFX "%s: DHCP failed", nic->log_name);
+ /* For DHCPv4 failure, the ustack must be cleaned so
+ it can re-acquire on the next iscsid request */
+ uip_reset(&nic_iface->ustack);
+
+ /* Signal that the device enable is
+ done */
+ pthread_cond_broadcast(&nic->enable_done_cond);
+ pthread_mutex_unlock(&nic->nic_mutex);
+
+ if (nic->enable_thread == INVALID_THREAD)
+ goto dhcp_err;
+
+ rc = pthread_join(nic->enable_thread, &res);
+ if (rc != 0)
+ LOG_ERR(PFX "%s: Couldn't join to canceled "
+ "enable nic thread", nic->log_name);
+dhcp_err:
+ pthread_mutex_lock(&nic->nic_mutex);
+ goto error;
+ }
+
+ if (nic->flags & NIC_DISABLED) {
+ /* Break out of this loop */
+ break;
+ }
+
+ LOG_INFO(PFX "%s: Initialized dhcp client", nic->log_name);
+ break;
+
+ case IPV6_CONFIG_DHCP:
+ case IPV6_CONFIG_STATIC:
+ if (ndpc_init(nic, &nic_iface->ustack, nic_iface->mac_addr,
+ ETH_ALEN)) {
+ LOG_DEBUG(PFX "%s: IPv6 engine already initialized!",
+ nic->log_name);
+ goto skip;
+ }
+ pthread_mutex_unlock(&nic->nic_mutex);
+ rc = process_dhcp_loop(nic, nic_iface, periodic_timer,
+ arp_timer);
+ pthread_mutex_lock(&nic->nic_mutex);
+ if (rc) {
+ /* Don't reset and allow to use RA and LL */
+ LOG_ERR(PFX "%s: IPv6 DHCP/NDP failed", nic->log_name);
+ }
+ if (nic_iface->ustack.ip_config == IPV6_CONFIG_STATIC) {
+ memcpy(&addr6.s6_addr, nic_iface->ustack.hostaddr6,
+ sizeof(addr6.s6_addr));
+ inet_ntop(AF_INET6, addr6.s6_addr, buf, sizeof(buf));
+ LOG_INFO(PFX "%s: hostaddr IP: %s", nic->log_name, buf);
+ memcpy(&addr6.s6_addr, nic_iface->ustack.netmask6,
+ sizeof(addr6.s6_addr));
+ inet_ntop(AF_INET6, addr6.s6_addr, buf, sizeof(buf));
+ LOG_INFO(PFX "%s: netmask IP: %s", nic->log_name, buf);
+ }
+ break;
+
+ default:
+ LOG_INFO(PFX "%s: ipconfig = %d?", nic->log_name,
+ nic_iface->ustack.ip_config);
+ }
+skip:
+ /* Mark acquisition done for this nic iface */
+ nic_iface->flags &= ~NIC_IFACE_ACQUIRE;
+
+ LOG_INFO(PFX "%s: enabled vlan %d protocol: %d", nic->log_name,
+ nic_iface->vlan_id, nic_iface->protocol);
+ return 0;
+
+error:
+ return -EIO;
+}
+
void *nic_loop(void *arg)
{
nic_t *nic = (nic_t *) arg;
int rc = -1;
- struct timer periodic_timer, arp_timer;
sigset_t set;
- void *res;
+ struct timer periodic_timer, arp_timer;
sigfillset(&set);
rc = pthread_sigmask(SIG_BLOCK, &set, NULL);
@@ -1302,10 +1395,11 @@ void *nic_loop(void *arg)
pthread_mutex_lock(&nic->nic_mutex);
pthread_cond_signal(&nic->nic_loop_started_cond);
+ /* nic_mutex must be locked */
while ((event_loop_stop == 0) &&
!(nic->flags & NIC_EXIT_MAIN_LOOP) &&
!(nic->flags & NIC_GOING_DOWN)) {
- nic_interface_t *nic_iface;
+ nic_interface_t *nic_iface, *vlan_iface;
if (nic->flags & NIC_DISABLED) {
LOG_DEBUG(PFX "%s: Waiting to be enabled",
@@ -1322,8 +1416,6 @@ void *nic_loop(void *arg)
}
LOG_DEBUG(PFX "%s: is now enabled", nic->log_name);
}
- pthread_mutex_unlock(&nic->nic_mutex);
-
/* initialize the device to send/rec data */
rc = (*nic->ops->open) (nic);
if (rc != 0) {
@@ -1331,18 +1423,17 @@ void *nic_loop(void *arg)
nic->log_name);
if (rc == -ENOTSUP)
- nic->flags &= NIC_EXIT_MAIN_LOOP;
+ nic->flags |= NIC_EXIT_MAIN_LOOP;
else
nic->flags &= ~NIC_ENABLED;
/* Signal that the device enable is done */
pthread_cond_broadcast(&nic->enable_done_cond);
pthread_mutex_unlock(&nic->nic_mutex);
-
goto dev_close;
}
-
nic_set_all_nic_iface_mac_to_parent(nic);
+ pthread_mutex_unlock(&nic->nic_mutex);
rc = alloc_free_queue(nic, 5);
if (rc != 5) {
@@ -1354,13 +1445,12 @@ void *nic_loop(void *arg)
"instead of %d", nic->log_name, 5);
/* Signal that the device enable is done */
pthread_cond_broadcast(&nic->enable_done_cond);
- pthread_mutex_unlock(&nic->nic_mutex);
goto dev_close;
}
}
/* Indication for the nic_disable routine that the nic
has started running */
- nic->state |= NIC_STARTED_RUNNING;
+ nic->state = NIC_STARTED_RUNNING;
/* Initialize the system clocks */
timer_set(&periodic_timer, CLOCK_SECOND / 2);
@@ -1369,192 +1459,25 @@ void *nic_loop(void *arg)
/* Prepare the stack for each of the VLAN interfaces */
pthread_mutex_lock(&nic->nic_mutex);
+ /* If DHCP fails, exit loop and restart the engine */
nic_iface = nic->nic_iface;
while (nic_iface != NULL) {
- uip_init(&nic_iface->ustack,
- nic->flags & NIC_IPv6_ENABLED);
- memcpy(&nic_iface->ustack.uip_ethaddr.addr,
- nic->mac_addr, 6);
-
- LOG_INFO(PFX "%s: Initialized ip stack: VLAN: %d",
- nic->log_name, nic_iface->vlan_id);
-
- LOG_INFO(PFX "%s: mac: %02x:%02x:%02x:%02x:%02x:%02x",
- nic->log_name,
- nic_iface->mac_addr[0],
- nic_iface->mac_addr[1],
- nic_iface->mac_addr[2],
- nic_iface->mac_addr[3],
- nic_iface->mac_addr[4],
- nic_iface->mac_addr[5]);
-
- if (nic_iface->ustack.ip_config == IPV4_CONFIG_STATIC) {
- struct in_addr addr;
- uip_ip4addr_t tmp = { 0, 0 };
-
- memcpy(&addr.s_addr, nic_iface->ustack.hostaddr,
- sizeof(addr.s_addr));
-
- LOG_INFO(PFX "%s: Using IP address: %s",
- nic->log_name, inet_ntoa(addr));
-
- memcpy(&addr.s_addr, nic_iface->ustack.netmask,
- sizeof(addr.s_addr));
-
- LOG_INFO(PFX "%s: Using netmask: %s",
- nic->log_name, inet_ntoa(addr));
-
- set_uip_stack(&nic_iface->ustack,
- &nic_iface->ustack.hostaddr,
- &nic_iface->ustack.netmask,
- &tmp, nic_iface->mac_addr);
-
- } else if (nic_iface->ustack.ip_config ==
- IPV4_CONFIG_DHCP) {
- struct uip_stack *ustack = &nic_iface->ustack;
- uip_ip4addr_t tmp = { 0, 0 };
-
- set_uip_stack(&nic_iface->ustack,
- &nic_iface->ustack.hostaddr,
- &nic_iface->ustack.netmask,
- &tmp, nic_iface->mac_addr);
- if (dhcpc_init(nic, ustack,
- nic_iface->mac_addr, ETH_ALEN)) {
- if (ustack->dhcpc) {
- LOG_DEBUG(PFX "%s: DHCPv4 "
- "engine already "
- "initialized!",
- nic->log_name);
- goto skip;
- } else {
- LOG_DEBUG(PFX "%s: DHCPv4 "
- "engine failed "
- "initialization!",
- nic->log_name);
- goto dev_close_free;
- }
- }
- pthread_mutex_unlock(&nic->nic_mutex);
- rc = process_dhcp_loop(nic, nic_iface,
+ if (nic_iface->flags & NIC_IFACE_ACQUIRE) {
+ do_acquisition(nic, nic_iface,
+ &periodic_timer,
+ &arp_timer);
+ }
+ vlan_iface = nic_iface->vlan_next;
+ while (vlan_iface != NULL) {
+ if (vlan_iface->flags & NIC_IFACE_ACQUIRE) {
+ do_acquisition(nic, vlan_iface,
&periodic_timer,
&arp_timer);
- pthread_mutex_lock(&nic->nic_mutex);
-
- if (rc) {
- LOG_ERR(PFX "%s: DHCP failed",
- nic->log_name);
- nic->flags |= NIC_DISABLED |
- NIC_RESET_UIP;
- nic->flags &= ~NIC_ENABLED;
- /* Signal that the device enable is
- done */
- pthread_cond_broadcast(
- &nic->enable_done_cond);
-
- pthread_mutex_unlock(&nic->nic_mutex);
-
- if (nic->enable_thread ==
- INVALID_THREAD)
- goto dev_close_free;
-
- rc = pthread_join(nic->enable_thread,
- &res);
- if (rc != 0)
- LOG_ERR(PFX "%s: Couldn't join "
- "to canceled enable nic"
- " thread",
- nic->log_name);
-
- goto dev_close_free;
}
-
- if (nic->flags & NIC_DISABLED) {
- pthread_mutex_unlock(&nic->nic_mutex);
- break;
- }
-
- LOG_INFO(PFX "%s: Initialized dhcp client",
- nic->log_name);
- } else if (nic_iface->ustack.ip_config ==
- IPV6_CONFIG_DHCP ||
- nic_iface->ustack.ip_config ==
- IPV6_CONFIG_STATIC) {
- struct in6_addr addr6;
- char buf[INET6_ADDRSTRLEN];
-
- /* Do router solicitation for both STATIC and
- DHCP - all NDP handling will take place in
- the DHCP loop
- STATIC - router advertisement will be handled
- in the uip background loop
- */
- if (ndpc_init(nic, &nic_iface->ustack,
- nic_iface->mac_addr, ETH_ALEN)) {
- LOG_DEBUG(PFX "%s: IPv6 engine already"
- "initialized!",
- nic->log_name);
- goto skip;
- }
- if (nic_iface->ustack.ip_config ==
- IPV6_CONFIG_DHCP) {
- pthread_mutex_unlock(&nic->nic_mutex);
- rc = process_dhcp_loop(nic, nic_iface,
- &periodic_timer,
- &arp_timer);
- pthread_mutex_lock(&nic->nic_mutex);
- if (rc) {
- /* Don't reset and allow to
- use RA and LL */
- LOG_ERR(PFX "%s: DHCPv6 failed",
- nic->log_name);
- }
- if (nic->flags & NIC_DISABLED) {
- pthread_mutex_unlock(&nic->
- nic_mutex);
- break;
- }
- } else {
- pthread_mutex_unlock(&nic->nic_mutex);
- rc = process_dhcp_loop(nic, nic_iface,
- &periodic_timer,
- &arp_timer);
- pthread_mutex_lock(&nic->nic_mutex);
- if (rc) {
- LOG_ERR(PFX "%s: IPv6 rtr "
- "failed",
- nic->log_name);
- }
- memcpy(&addr6.s6_addr,
- nic_iface->ustack.hostaddr6,
- sizeof(addr6.s6_addr));
- inet_ntop(AF_INET6,
- addr6.s6_addr,
- buf, sizeof(buf));
- LOG_INFO(PFX "%s: hostaddr IP: %s",
- nic->log_name, buf);
-
- memcpy(&addr6.s6_addr,
- nic_iface->ustack.netmask6,
- sizeof(addr6.s6_addr));
- inet_ntop(AF_INET6,
- addr6.s6_addr,
- buf, sizeof(buf));
- LOG_INFO(PFX "%s: netmask IP: %s",
- nic->log_name, buf);
- }
- } else {
- LOG_INFO(PFX "%s: ipconfig = %d?",
- nic->log_name,
- nic_iface->ustack.ip_config);
+ vlan_iface = vlan_iface->next;
}
-skip:
- LOG_INFO(PFX "%s: enabled vlan %d protocol: %d",
- nic->log_name,
- nic_iface->vlan_id, nic_iface->protocol);
-
- nic_iface = nic_iface->vlan_next;
+ nic_iface = nic_iface->next;
}
-
if (nic->flags & NIC_DISABLED) {
LOG_WARN(PFX "%s: nic was disabled during nic loop, "
"closing flag 0x%x",
@@ -1567,10 +1490,7 @@ skip:
/* This is when we start the processing of packets */
nic->start_time = time(NULL);
- nic->flags &= ~NIC_UNITIALIZED;
- nic->flags |= NIC_INITIALIZED;
- nic->state &= ~NIC_STOPPED;
- nic->state |= NIC_RUNNING;
+ nic->state = NIC_RUNNING;
nic->flags &= ~NIC_ENABLED_PENDING;
@@ -1580,14 +1500,14 @@ skip:
LOG_INFO(PFX "%s: entering main nic loop", nic->log_name);
- while ((nic->state & NIC_RUNNING) &&
+ while ((nic->state == NIC_RUNNING) &&
(event_loop_stop == 0) &&
!(nic->flags & NIC_GOING_DOWN)) {
/* Check the periodic and ARP timer */
check_timers(nic, &periodic_timer, &arp_timer);
rc = nic_process_intr(nic, 0);
while ((rc > 0) &&
- (nic->state & NIC_RUNNING) &&
+ (nic->state == NIC_RUNNING) &&
!(nic->flags & NIC_GOING_DOWN)) {
rc = process_packets(nic,
&periodic_timer,
@@ -1609,33 +1529,7 @@ dev_close:
} else {
pthread_mutex_destroy(&nic->xmit_mutex);
pthread_mutex_init(&nic->xmit_mutex, NULL);
-
- if (nic->flags & NIC_RESET_UIP) {
- nic_interface_t *nic_iface = nic->nic_iface;
- nic_interface_t *vlan_iface;
- while (nic_iface != NULL) {
- LOG_INFO(PFX "%s: resetting uIP stack",
- nic->log_name);
- uip_reset(&nic_iface->ustack);
- vlan_iface = nic_iface->vlan_next;
- while (vlan_iface != NULL) {
- LOG_INFO(PFX "%s: resetting "
- "vlan uIP stack",
- nic->log_name);
- uip_reset(&vlan_iface->ustack);
- vlan_iface =
- vlan_iface->vlan_next;
- }
- nic_iface = nic_iface->next;
- }
- nic->flags &= ~NIC_RESET_UIP;
- }
}
-
- nic->flags |= NIC_UNITIALIZED;
- nic->flags &= ~NIC_INITIALIZED;
- nic->flags &= ~NIC_ENABLED_PENDING;
-
nic->pending_count = 0;
if (!(nic->flags & NIC_EXIT_MAIN_LOOP)) {
@@ -1643,6 +1537,9 @@ dev_close:
pthread_cond_broadcast(&nic->disable_wait_cond);
}
}
+ /* clean up the nic flags */
+ nic->flags &= ~NIC_ENABLED_PENDING;
+
pthread_mutex_unlock(&nic->nic_mutex);
LOG_INFO(PFX "%s: nic loop thread exited", nic->log_name);
diff --git a/iscsiuio/src/unix/nic.h b/iscsiuio/src/unix/nic.h
index 57d89b4..da900c5 100644
--- a/iscsiuio/src/unix/nic.h
+++ b/iscsiuio/src/unix/nic.h
@@ -67,6 +67,8 @@ extern struct nic_lib_handle *nic_lib_list;
extern pthread_mutex_t nic_list_mutex;
extern struct nic *nic_list;
+extern void *nl_process_handle_thread(void *arg);
+
/*******************************************************************************
* Constants
******************************************************************************/
@@ -117,20 +119,30 @@ struct nic_stats {
* NIC interface structure
******************************************************************************/
typedef struct nic_interface {
+ struct nic_interface *vlan_next;
struct nic_interface *next;
struct nic *parent;
uint16_t protocol;
uint16_t flags;
-#define NIC_IFACE_PERSIST 0x0001
+#define NIC_IFACE_PERSIST (1<<0)
+#define NIC_IFACE_ACQUIRE (1<<1)
+#define NIC_IFACE_PATHREQ_WAIT1 (1<<2)
+#define NIC_IFACE_PATHREQ_WAIT2 (1<<3)
+#define NIC_IFACE_PATHREQ_WAIT (NIC_IFACE_PATHREQ_WAIT1 | \
+ NIC_IFACE_PATHREQ_WAIT2)
uint8_t mac_addr[ETH_ALEN];
uint8_t vlan_priority;
uint16_t vlan_id;
+#define NO_VLAN 0x8000
+ uint16_t mtu;
time_t start_time;
struct uip_stack ustack;
- struct nic_interface *vlan_next;
+
+ int iface_num;
+ int request_type;
} nic_interface_t;
/******************************************************************************
@@ -178,8 +190,9 @@ typedef struct nic_ops {
int (*clear_tx_intr) (struct nic *);
int (*handle_iscsi_path_req) (struct nic *,
int,
- struct iscsi_uevent * ev,
- struct iscsi_path * path);
+ struct iscsi_uevent *ev,
+ struct iscsi_path *path,
+ nic_interface_t *nic_iface);
} net_ops_t;
typedef struct nic_lib_handle {
@@ -199,6 +212,9 @@ typedef struct nic {
#define NIC_DISABLED 0x0008
#define NIC_IPv6_ENABLED 0x0010
#define NIC_ADDED_MULICAST 0x0020
+#define NIC_LONG_SLEEP 0x0040
+#define NIC_PATHREQ_WAIT 0x0080
+
#define NIC_VLAN_STRIP_ENABLED 0x0100
#define NIC_MSIX_ENABLED 0x0200
#define NIC_TX_HAS_SENT 0x0400
@@ -214,7 +230,6 @@ typedef struct nic {
#define NIC_STOPPED 0x0001
#define NIC_STARTED_RUNNING 0x0002
#define NIC_RUNNING 0x0004
-#define NIC_LONG_SLEEP 0x0008
#define NIC_EXIT 0x0010
int fd; /* Holds the file descriptor to UIO */
@@ -232,6 +247,7 @@ typedef struct nic {
uint32_t intr_count; /* Total UIO interrupt count */
+ /* Held for nic ops manipulation */
pthread_mutex_t nic_mutex;
/* iSCSI ring ethernet MAC address */
@@ -268,6 +284,7 @@ typedef struct nic {
/* Number of retrys from iscsid */
uint32_t pending_count;
+ uint32_t pathreq_pending_count;
#define DEFAULT_RX_POLL_USEC 100 /* usec */
/* options enabled by the user */
@@ -295,6 +312,19 @@ typedef struct nic {
int (*process_intr) (struct nic * nic);
struct nic_ops *ops;
+
+ /* NL processing parameters */
+ pthread_t nl_process_thread;
+ pthread_cond_t nl_process_cond;
+ pthread_cond_t nl_process_if_down_cond;
+ pthread_mutex_t nl_process_mutex;
+ int nl_process_if_down;
+ int nl_process_head;
+ int nl_process_tail;
+#define NIC_NL_PROCESS_MAX_RING_SIZE 128
+#define NIC_NL_PROCESS_LAST_ENTRY (NIC_NL_PROCESS_MAX_RING_SIZE - 1)
+#define NIC_NL_PROCESS_NEXT_ENTRY(x) ((x + 1) & NIC_NL_PROCESS_MAX_RING_SIZE)
+ void *nl_process_ring[NIC_NL_PROCESS_MAX_RING_SIZE];
} nic_t;
/******************************************************************************
@@ -307,8 +337,6 @@ void nic_add(nic_t *nic);
int nic_remove(nic_t *nic);
int nic_add_nic_iface(nic_t *nic, nic_interface_t *nic_iface);
-int nic_add_vlan_iface(nic_t *nic, nic_interface_t *nic_iface,
- nic_interface_t *vlan_iface);
int nic_process_intr(nic_t *nic, int discard_check);
nic_interface_t *nic_iface_init();
@@ -339,14 +367,6 @@ int enable_multicast(nic_t * nic);
int disable_multicast(nic_t * nic);
void nic_set_all_nic_iface_mac_to_parent(nic_t * nic);
-struct nic_interface *nic_find_nic_iface(nic_t * nic, uint16_t vlan_id);
-struct nic_interface *nic_find_nic_iface_protocol(nic_t * nic,
- uint16_t vlan_id,
- uint16_t protocol);
-struct nic_interface *nic_find_vlan_iface_protocol(nic_t *nic,
- nic_interface_t *nic_iface,
- uint16_t vlan_id,
- uint16_t protocol);
int find_nic_lib_using_pci_id(uint32_t vendor, uint32_t device,
uint32_t subvendor, uint32_t subdevice,
nic_lib_handle_t ** handle,
diff --git a/iscsiuio/src/unix/nic_nl.c b/iscsiuio/src/unix/nic_nl.c
index 971f350..34e2062 100644
--- a/iscsiuio/src/unix/nic_nl.c
+++ b/iscsiuio/src/unix/nic_nl.c
@@ -83,20 +83,6 @@ const static struct sockaddr_nl dest_addr = {
/* Netlink */
int nl_sock = INVALID_FD;
-/* Items used to handle the thread used to send/process ARP's */
-static pthread_t nl_process_thread;
-static pthread_cond_t nl_process_cond;
-pthread_cond_t nl_process_if_down_cond;
-pthread_mutex_t nl_process_mutex;
-int nl_process_if_down = 0;
-
-#define NL_PROCESS_MAX_RING_SIZE 128
-#define NL_PROCESS_LAST_ENTRY NL_PROCESS_MAX_RING_SIZE - 1
-#define NL_PROCESS_NEXT_ENTRY(x) ((x + 1) & NL_PROCESS_MAX_RING_SIZE)
-static int nl_process_head;
-static int nl_process_tail;
-static void *nl_process_ring[NL_PROCESS_MAX_RING_SIZE];
-
#define MAX_TX_DESC_CNT (TX_DESC_CNT - 1)
#define NEXT_TX_BD(x) (((x) & (MAX_TX_DESC_CNT - 1)) == \
@@ -222,10 +208,11 @@ int __kipc_call(int fd, void *iov_base, int iov_len)
static int pull_from_nl(char **buf)
{
int rc;
- size_t ev_size;
+ size_t ev_size, payload_size, alloc_size;
char nlm_ev[NLMSG_SPACE(sizeof(struct iscsi_uevent))];
struct nlmsghdr *nlh;
char *data = NULL;
+ struct iscsi_uevent *ev;
/* Take a quick peek at what how much uIP will need to read */
rc = nl_read(nl_sock, nlm_ev,
@@ -249,14 +236,26 @@ static int pull_from_nl(char **buf)
return -EINVAL;
}
- data = (char *)malloc(nlh->nlmsg_len);
+ ev = (struct iscsi_uevent *)NLMSG_DATA(nlh);
+ if (ev->type == ISCSI_KEVENT_PATH_REQ) {
+ ev_size = nlh->nlmsg_len - NLMSG_ALIGN(sizeof(struct nlmsghdr));
+ payload_size = ev_size - sizeof(struct iscsi_uevent);
+ if (payload_size < sizeof(struct iscsi_path))
+ alloc_size = nlh->nlmsg_len + (payload_size -
+ sizeof(struct iscsi_path));
+ else
+ alloc_size = nlh->nlmsg_len;
+ } else {
+ alloc_size = nlh->nlmsg_len;
+ }
+ data = (char *)malloc(alloc_size);
if (unlikely(data == NULL)) {
LOG_ERR(PFX "Couldn't allocate %d bytes for Netlink "
- "iSCSI message", nlh->nlmsg_len);
+ "iSCSI message", alloc_size);
return -ENOMEM;
}
- memset(data, 0, nlh->nlmsg_len);
+ memset(data, 0, alloc_size);
ev_size = nlh->nlmsg_len - NLMSG_ALIGN(sizeof(struct nlmsghdr));
rc = nl_read(nl_sock, data, (int)nlh->nlmsg_len, MSG_WAITALL);
if (rc <= 0) {
@@ -269,10 +268,9 @@ static int pull_from_nl(char **buf)
goto error;
}
-
*buf = data;
return 0;
- error:
+error:
if (data != NULL)
free(data);
@@ -284,9 +282,8 @@ const static struct timespec ctldev_sleep_req = {
.tv_nsec = 250000000,
};
-static int ctldev_handle(char *data)
+static int ctldev_handle(char *data, nic_t *nic)
{
- nic_t *nic = NULL;
int rc;
struct iscsi_uevent *ev;
uint8_t *payload;
@@ -294,18 +291,12 @@ static int ctldev_handle(char *data)
char *msg_type_str;
uint32_t host_no;
int i;
+ nic_interface_t *nic_iface = NULL;
ev = (struct iscsi_uevent *)NLMSG_DATA(data);
switch (ev->type) {
case ISCSI_KEVENT_PATH_REQ:
msg_type_str = "path_req";
-
- host_no = ev->r.req_path.host_no;
- break;
- case ISCSI_KEVENT_IF_DOWN:
- msg_type_str = "if_down";
-
- host_no = ev->r.notify_if_down.host_no;
break;
default:
/* We don't care about other iSCSI Netlink messages */
@@ -315,22 +306,16 @@ static int ctldev_handle(char *data)
}
/* This is a message that drivers should be interested in */
- LOG_INFO("Received: '%s': host_no: %d", msg_type_str, host_no);
-
- rc = from_host_no_find_associated_eth_device(host_no, &nic);
- if (rc != 0) {
- LOG_ERR(PFX "Dropping msg, couldn't find nic with host no:%d",
- host_no);
- goto error;
- }
+ LOG_INFO(PFX "%s: Processing '%s'", nic->log_name, msg_type_str);
payload = (uint8_t *) ((uint8_t *) ev) + sizeof(*ev);
path = (struct iscsi_path *)payload;
if (ev->type == ISCSI_KEVENT_PATH_REQ) {
struct timespec sleep_rem;
- nic_interface_t *nic_iface, *vlan_iface;
+ nic_interface_t *vlan_iface;
uint16_t ip_type;
+ int iface_num, vlan_id;
if (path->ip_addr_len == 4)
ip_type = AF_INET;
@@ -339,67 +324,107 @@ static int ctldev_handle(char *data)
else
ip_type = 0;
- /* Find the parent nic_iface */
- nic_iface = nic_find_nic_iface_protocol(nic, 0, ip_type);
+ /* Find the nic_iface to use */
+ iface_num = ev->r.req_path.iface_num ?
+ ev->r.req_path.iface_num : IFACE_NUM_INVALID;
+ vlan_id = path->vlan_id ? path->vlan_id : NO_VLAN;
+
+ LOG_DEBUG(PFX "%s: PATH_REQ with iface_num %d VLAN %d",
+ nic->log_name, iface_num, vlan_id);
+
+ pthread_mutex_lock(&nic->nic_mutex);
+
+ nic_iface = nic_find_nic_iface(nic, ip_type, vlan_id,
+ iface_num, IP_CONFIG_OFF);
if (nic_iface == NULL) {
- LOG_ERR(PFX "%s: Couldn't find nic iface "
- "vlan: %d ip_type: %d "
- "ip_addr_len: %d to clone",
- nic->log_name, path->vlan_id, ip_type,
- path->ip_addr_len);
- goto error;
- }
- if (path->vlan_id) {
- vlan_iface = nic_find_vlan_iface_protocol(nic,
- nic_iface, path->vlan_id, ip_type);
- if (vlan_iface == NULL) {
- /* Create a vlan_iface */
- vlan_iface = nic_iface_init();
- if (vlan_iface == NULL) {
- LOG_ERR(PFX "%s: Couldn't allocate "
- "space for vlan: %d ip_type: "
- "%d ip_addr_len: %d",
- nic->log_name, path->vlan_id,
- ip_type, path->ip_addr_len);
- goto error;
+ nic_iface = nic_find_nic_iface(nic, ip_type,
+ NO_VLAN,
+ IFACE_NUM_INVALID,
+ IP_CONFIG_OFF);
+ if (nic_iface == NULL) {
+ pthread_mutex_unlock(&nic->nic_mutex);
+ LOG_ERR(PFX "%s: Couldn't find nic iface parent"
+ " vlan: %d ip_type: %d "
+ "ip_addr_len: %d to clone",
+ nic->log_name, path->vlan_id, ip_type,
+ path->ip_addr_len);
+ goto error;
+ }
+ if (nic_iface->iface_num != IFACE_NUM_INVALID) {
+ /* New VLAN support:
+ Use the nic_iface found from the top
+ of the protocol family and ignore
+ the VLAN id from the path_req */
+ if (!(nic_iface->iface_num == 0 &&
+ nic_iface->vlan_id == 0 &&
+ path->vlan_id)) {
+ pthread_mutex_unlock(&nic->nic_mutex);
+ goto nic_iface_done;
}
-
- vlan_iface->protocol = ip_type;
- vlan_iface->vlan_id = path->vlan_id;
- nic_add_vlan_iface(nic, nic_iface, vlan_iface);
-
- /* TODO: When VLAN support is placed in */
- /* the iface file revisit this code */
- vlan_iface->ustack.ip_config =
- nic_iface->ustack.ip_config;
- memcpy(vlan_iface->ustack.hostaddr,
- nic_iface->ustack.hostaddr,
- sizeof(nic_iface->ustack.hostaddr));
- memcpy(vlan_iface->ustack.netmask,
- nic_iface->ustack.netmask,
- sizeof(nic_iface->ustack.netmask));
- memcpy(vlan_iface->ustack.netmask6,
- nic_iface->ustack.netmask6,
- sizeof(nic_iface->ustack.netmask6));
- memcpy(vlan_iface->ustack.hostaddr6,
- nic_iface->ustack.hostaddr6,
- sizeof(nic_iface->ustack.hostaddr6));
-
- persist_all_nic_iface(nic);
- nic_disable(nic, 0);
- nic_iface = vlan_iface;
+ /* If iface_num == 0 and vlan_id == 0 but
+ the vlan_id from path_req is > 0,
+ then fallthru to the legacy support since
+ this is most likely from an older iscsid
+ (RHEL6.2/6.3 but has iface_num support)
+ */
}
- }
+ /* Legacy VLAN support:
+ This newly created nic_iface must inherit the
+ network parameters from the parent nic_iface
+ */
+ LOG_DEBUG(PFX "%s: Created the nic_iface for vlan: %d "
+ "ip_type: %d", nic->log_name, path->vlan_id,
+ ip_type);
+ vlan_iface = nic_iface_init();
+ if (vlan_iface == NULL) {
+ pthread_mutex_unlock(&nic->nic_mutex);
+ LOG_ERR(PFX "%s: Couldn't allocate "
+ "space for vlan: %d ip_type: "
+ "%d", nic->log_name, path->vlan_id,
+ ip_type);
+ goto error;
+ }
+ vlan_iface->protocol = ip_type;
+ vlan_iface->vlan_id = path->vlan_id;
+ nic_add_nic_iface(nic, vlan_iface);
+
+ vlan_iface->ustack.ip_config =
+ nic_iface->ustack.ip_config;
+ memcpy(vlan_iface->ustack.hostaddr,
+ nic_iface->ustack.hostaddr,
+ sizeof(nic_iface->ustack.hostaddr));
+ memcpy(vlan_iface->ustack.netmask,
+ nic_iface->ustack.netmask,
+ sizeof(nic_iface->ustack.netmask));
+ memcpy(vlan_iface->ustack.netmask6,
+ nic_iface->ustack.netmask6,
+ sizeof(nic_iface->ustack.netmask6));
+ memcpy(vlan_iface->ustack.hostaddr6,
+ nic_iface->ustack.hostaddr6,
+ sizeof(nic_iface->ustack.hostaddr6));
+
+ /* Persist so when nic_close won't call uip_reset
+ to nullify nic_iface->ustack */
+ persist_all_nic_iface(nic);
+
+ nic_iface = vlan_iface;
+
+ pthread_mutex_unlock(&nic->nic_mutex);
+ /* nic_disable but not going down */
+ nic_disable(nic, 0);
+ } else {
+ pthread_mutex_unlock(&nic->nic_mutex);
+ }
+nic_iface_done:
/* Force enable the NIC */
- if ((nic->state & NIC_STOPPED) &&
- !(nic->flags & NIC_ENABLED_PENDING))
+ if (nic->state == NIC_STOPPED)
nic_enable(nic);
/* Ensure that the NIC is RUNNING */
rc = -EIO;
for (i = 0; i < 10; i++) {
- if ((nic->state & NIC_RUNNING) == NIC_RUNNING) {
+ if (nic->state == NIC_RUNNING) {
rc = 0;
break;
}
@@ -418,49 +443,25 @@ static int ctldev_handle(char *data)
}
if (nic->ops) {
- char eth_device_name[IFNAMSIZ];
-
switch (ev->type) {
case ISCSI_KEVENT_PATH_REQ:
/* pass the request up to the user space
* library driver */
- if (nic->ops->handle_iscsi_path_req) {
+ nic_iface->flags |= NIC_IFACE_PATHREQ_WAIT2;
+ nic_iface->flags &= ~NIC_IFACE_PATHREQ_WAIT1;
+ if (nic->ops->handle_iscsi_path_req)
nic->ops->handle_iscsi_path_req(nic,
nl_sock, ev,
- path);
- }
-
- LOG_INFO(PFX "%s: 'path_req' operation finished",
- nic->log_name);
-
- rc = 0;
- break;
- case ISCSI_KEVENT_IF_DOWN:
- memcpy(eth_device_name, nic->eth_device_name,
- sizeof(eth_device_name));
-
- pthread_mutex_lock(&nic_list_mutex);
-
+ path,
+ nic_iface);
+ nic_iface->flags &= ~NIC_IFACE_PATHREQ_WAIT;
pthread_mutex_lock(&nic->nic_mutex);
- nic->flags |= NIC_EXIT_MAIN_LOOP;
+ nic->flags &= ~NIC_PATHREQ_WAIT;
pthread_mutex_unlock(&nic->nic_mutex);
-
- pthread_cond_broadcast(&nic->enable_done_cond);
-
- nic_disable(nic, 1);
-
- nic_remove(nic);
- pthread_mutex_unlock(&nic_list_mutex);
-
- pthread_mutex_lock(&nl_process_mutex);
- nl_process_if_down = 0;
- pthread_mutex_unlock(&nl_process_mutex);
+ LOG_INFO(PFX "%s: 'path_req' operation finished",
+ nic->log_name);
rc = 0;
-
- LOG_INFO(PFX "%s: 'if_down' operation finished",
- eth_device_name);
-
break;
default:
rc = -EAGAIN;
@@ -468,55 +469,62 @@ static int ctldev_handle(char *data)
}
}
- error:
+error:
return rc;
}
-static void *nl_process_handle_thread(void *arg)
+/* NIC specific nl processing thread */
+void *nl_process_handle_thread(void *arg)
{
int rc;
+ nic_t *nic = (nic_t *)arg;
+
+ if (nic == NULL)
+ goto error;
while (!event_loop_stop) {
char *data = NULL;
- rc = pthread_cond_wait(&nl_process_cond, &nl_process_mutex);
+ rc = pthread_cond_wait(&nic->nl_process_cond,
+ &nic->nl_process_mutex);
if (rc != 0) {
LOG_ERR("Fatal error in NL processing thread "
"during wait[%s]", strerror(rc));
break;
}
- data = nl_process_ring[nl_process_head];
- nl_process_ring[nl_process_head] = NULL;
- nl_process_tail = NL_PROCESS_NEXT_ENTRY(nl_process_tail);
+ data = nic->nl_process_ring[nic->nl_process_head];
+ nic->nl_process_ring[nic->nl_process_head] = NULL;
+ nic->nl_process_tail =
+ NIC_NL_PROCESS_NEXT_ENTRY(nic->nl_process_tail);
- pthread_mutex_unlock(&nl_process_mutex);
+ pthread_mutex_unlock(&nic->nl_process_mutex);
if (data) {
- ctldev_handle(data);
+ ctldev_handle(data, nic);
free(data);
}
}
-
+error:
return NULL;
}
-static void flush_nl_process_ring()
+static void flush_nic_nl_process_ring(nic_t *nic)
{
int i;
- for (i = 0; i < NL_PROCESS_MAX_RING_SIZE; i++) {
- if (nl_process_ring[i] != NULL) {
- free(nl_process_ring[i]);
- nl_process_ring[i] = NULL;
+ for (i = 0; i < NIC_NL_PROCESS_MAX_RING_SIZE; i++) {
+ if (nic->nl_process_ring[i] != NULL) {
+ free(nic->nl_process_ring[i]);
+ nic->nl_process_ring[i] = NULL;
}
}
- nl_process_head = 0;
- nl_process_tail = 0;
+ nic->nl_process_head = 0;
+ nic->nl_process_tail = 0;
- LOG_DEBUG(PFX "Flushed NL ring");
+ LOG_DEBUG(PFX "%s: Flushed NIC NL ring", nic->log_name);
}
/**
@@ -528,25 +536,9 @@ static void flush_nl_process_ring()
int nic_nl_open()
{
int rc;
+ char *msg_type_str;
- /* Prepare the thread to issue the ARP's */
- nl_process_head = 0;
- nl_process_tail = 0;
- nl_process_if_down = 0;
- memset(&nl_process_ring, 0, sizeof(nl_process_ring));
-
- pthread_mutex_init(&nl_process_mutex, NULL);
- pthread_cond_init(&nl_process_cond, NULL);
- pthread_cond_init(&nl_process_if_down_cond, NULL);
-
- rc = pthread_create(&nl_process_thread, NULL,
- nl_process_handle_thread, NULL);
- if (rc != 0) {
- LOG_ERR("Could not create NL processing thread [%s]",
- strerror(rc));
- return -EIO;
- }
-
+ /* Prepare the thread to issue the ARP's */
nl_sock = socket(PF_NETLINK, SOCK_RAW, NETLINK_ISCSI);
if (nl_sock < 0) {
LOG_ERR(PFX "can not create NETLINK_ISCSI socket [%s]",
@@ -581,6 +573,8 @@ int nic_nl_open()
while (!event_loop_stop) {
struct iscsi_uevent *ev;
char *buf = NULL;
+ uint32_t host_no;
+ nic_t *nic;
rc = pull_from_nl(&buf);
if (rc != 0)
@@ -588,33 +582,91 @@ int nic_nl_open()
/* Try to abort ARP'ing if a if_down was recieved */
ev = (struct iscsi_uevent *)NLMSG_DATA(buf);
- if (ev->type == ISCSI_KEVENT_IF_DOWN) {
- LOG_INFO(PFX "Received if_down event");
+ switch (ev->type) {
+ case ISCSI_KEVENT_IF_DOWN:
+ host_no = ev->r.notify_if_down.host_no;
+ msg_type_str = "if_down";
+ break;
+ case ISCSI_KEVENT_PATH_REQ:
+ host_no = ev->r.req_path.host_no;
+ msg_type_str = "path_req";
+ break;
+ default:
+ /* We don't care about other iSCSI Netlink messages */
+ continue;
+ }
+ LOG_INFO(PFX "Received %s for host %d", msg_type_str, host_no);
- pthread_mutex_lock(&nl_process_mutex);
- /* Don't flush the nl ring if another if_down
- is in progress */
- if (!nl_process_if_down) {
- nl_process_if_down = 1;
+ /* Make sure the nic list doesn't get yanked */
+ pthread_mutex_lock(&nic_list_mutex);
- flush_nl_process_ring();
- }
- pthread_mutex_unlock(&nl_process_mutex);
+ rc = from_host_no_find_associated_eth_device(host_no, &nic);
+ if (rc != 0) {
+ pthread_mutex_unlock(&nic_list_mutex);
+ LOG_ERR(PFX "Dropping msg, couldn't find nic with host "
+ "no: %d", host_no);
+ continue;
+ }
+
+ /* Found the nic */
+ if (nic->nl_process_thread == INVALID_THREAD) {
+ /* If thread is not valid, just drop it */
+ pthread_mutex_unlock(&nic_list_mutex);
+ LOG_ERR(PFX "Dropping msg, nic nl process thread "
+ "not ready for host no: %d", host_no);
+ continue;
}
- if ((nl_process_head + 1 == nl_process_tail) ||
- (nl_process_tail == 0 &&
- nl_process_head == NL_PROCESS_LAST_ENTRY)) {
- LOG_WARN(PFX "No space on Netlink ring");
+ if (ev->type == ISCSI_KEVENT_IF_DOWN) {
+ char eth_device_name[IFNAMSIZ];
+
+ pthread_mutex_lock(&nic->nl_process_mutex);
+ nic->nl_process_if_down = 1;
+ flush_nic_nl_process_ring(nic);
+ pthread_cond_broadcast(&nic->nl_process_if_down_cond);
+ pthread_mutex_unlock(&nic->nl_process_mutex);
+
+ memcpy(eth_device_name, nic->eth_device_name,
+ sizeof(eth_device_name));
+
+ pthread_mutex_lock(&nic->nic_mutex);
+ nic->flags &= ~NIC_PATHREQ_WAIT;
+ nic->flags |= NIC_EXIT_MAIN_LOOP;
+ pthread_cond_broadcast(&nic->enable_done_cond);
+ pthread_mutex_unlock(&nic->nic_mutex);
+
+ pthread_mutex_lock(&nic->nl_process_mutex);
+ nic->nl_process_if_down = 0;
+ pthread_mutex_unlock(&nic->nl_process_mutex);
+
+ nic_disable(nic, 1);
+
+ nic_remove(nic);
+ pthread_mutex_unlock(&nic_list_mutex);
+
+ LOG_INFO(PFX "%s: 'if_down' operation finished",
+ eth_device_name);
+ continue;
+ }
+ /* Place msg into the nic specific queue */
+ pthread_mutex_lock(&nic->nl_process_mutex);
+ if ((nic->nl_process_head + 1 == nic->nl_process_tail) ||
+ (nic->nl_process_tail == 0 &&
+ nic->nl_process_head == NIC_NL_PROCESS_LAST_ENTRY)) {
+ pthread_mutex_unlock(&nic->nl_process_mutex);
+ pthread_mutex_unlock(&nic_list_mutex);
+ LOG_WARN(PFX "%s: No space on Netlink ring",
+ nic->log_name);
continue;
}
+ nic->nl_process_ring[nic->nl_process_head] = buf;
+ nic->nl_process_head =
+ NIC_NL_PROCESS_NEXT_ENTRY(nic->nl_process_head);
+ pthread_cond_signal(&nic->nl_process_cond);
- pthread_mutex_lock(&nl_process_mutex);
- nl_process_ring[nl_process_head] = buf;
- nl_process_head = NL_PROCESS_NEXT_ENTRY(nl_process_head);
+ pthread_mutex_unlock(&nic->nl_process_mutex);
- pthread_cond_signal(&nl_process_cond);
- pthread_mutex_unlock(&nl_process_mutex);
+ pthread_mutex_unlock(&nic_list_mutex);
LOG_DEBUG(PFX "Pulled nl event");
}
diff --git a/iscsiuio/src/unix/nic_utils.c b/iscsiuio/src/unix/nic_utils.c
index fe58df8..a1d3e72 100644
--- a/iscsiuio/src/unix/nic_utils.c
+++ b/iscsiuio/src/unix/nic_utils.c
@@ -65,7 +65,7 @@
*****************************************************************************/
static const char nic_uio_sysfs_name_tempate[] = "/sys/class/uio/uio%i/name";
static const char cnic_sysfs_uio_event_template[] =
- "/sys/class/uio/uio%d/event";
+ "/sys/class/uio/uio%d/event";
static const char base_uio_sysfs_name[] = "/sys/class/uio/";
static const char uio_name[] = "uio";
@@ -77,7 +77,7 @@ static const char base_iscsi_host_name[] = "/sys/class/iscsi_host/";
static const char host_template[] = "host%d";
static const char iscsi_host_path_template[] = "/sys/class/iscsi_host/host%d";
static const char iscsi_host_path_netdev_template[] =
- "/sys/class/iscsi_host/host%d/netdev";
+ "/sys/class/iscsi_host/host%d/netdev";
static const char cnic_uio_sysfs_resc_template[] =
"/sys/class/uio/uio%i/device/resource%i";
@@ -208,6 +208,7 @@ int nic_discover_iscsi_hosts()
default:
/* There are iSCSI hosts */
+ pthread_mutex_lock(&nic_list_mutex);
for (i = 0; i < count; i++) {
int host_no;
char *raw = NULL;
@@ -267,6 +268,7 @@ int nic_discover_iscsi_hosts()
free(raw);
}
+ pthread_mutex_unlock(&nic_list_mutex);
/* Cleanup the scandir() call */
for (i = 0; i < count; i++)
@@ -402,6 +404,7 @@ static char *extract_none(struct dirent **files)
/**
* from_host_no_find_nic() - Given the host number
* this function will try to find the assoicated nic interface
+ * Must be called with nic_list_mutex lock
* @param host_no - minor number of the UIO device
* @param nic - pointer to the NIC will set if successful
* @return 0 on success, <0 on error
@@ -431,7 +434,6 @@ int from_host_no_find_associated_eth_device(int host_no, nic_t ** nic)
rc = -EIO;
- pthread_mutex_lock(&nic_list_mutex);
current_nic = nic_list;
while (current_nic != NULL) {
if (strcmp(raw, current_nic->eth_device_name) == 0) {
@@ -442,7 +444,6 @@ int from_host_no_find_associated_eth_device(int host_no, nic_t ** nic)
current_nic = current_nic->next;
}
- pthread_mutex_unlock(&nic_list_mutex);
free(raw);
@@ -923,7 +924,7 @@ int nic_enable(nic_t * nic)
nic->log_name, nic->flags, nic->state);
return -EINVAL;
}
- if (nic->state & NIC_STOPPED) {
+ if (nic->state == NIC_STOPPED) {
struct timespec ts;
struct timeval tp;
int rc;
@@ -940,48 +941,20 @@ int nic_enable(nic_t * nic)
rc = gettimeofday(&tp, NULL);
ts.tv_sec = tp.tv_sec;
ts.tv_nsec = tp.tv_usec * 1000;
- ts.tv_sec += 10;
+ ts.tv_sec += 100;
/* Wait for the device to be enabled */
rc = pthread_cond_timedwait(&nic->enable_done_cond,
&nic->nic_mutex, &ts);
-#if 0
- if (rc || !nic->flags & NIC_ENABLED) {
- /* Give it one more shout */
- pthread_cond_broadcast(&nic->enable_wait_cond);
- rc = gettimeofday(&tp, NULL);
- ts.tv_sec = tp.tv_sec;
- ts.tv_nsec = tp.tv_usec * 1000;
- ts.tv_sec += 5;
- rc = pthread_cond_timedwait(&nic->enable_done_cond,
- &nic->nic_mutex, &ts);
- }
-#endif
- nic->flags &= ~NIC_ENABLED_PENDING;
-
if (rc == 0 && nic->flags & NIC_ENABLED) {
LOG_DEBUG(PFX "%s: device enabled", nic->log_name);
} else {
- LOG_ERR(PFX "%s: waiting to finish nic_enable err:%s",
+ nic->flags &= ~NIC_ENABLED;
+ nic->flags |= NIC_DISABLED;
+ nic->flags &= ~NIC_ENABLED_PENDING;
+
+ LOG_ERR(PFX "%s: waiting to finish nic_enable err: %s",
nic->log_name, strerror(rc));
- /* Must clean up the ustack */
- nic_interface_t *nic_iface = nic->nic_iface;
- nic_interface_t *vlan_iface;
- while (nic_iface != NULL) {
- LOG_INFO(PFX "%s: resetting uIP stack",
- nic->log_name);
- uip_reset(&nic_iface->ustack);
- vlan_iface = nic_iface->vlan_next;
- while (vlan_iface != NULL) {
- LOG_INFO(PFX "%s: resetting "
- "vlan uIP stack",
- nic->log_name);
- uip_reset(&vlan_iface->ustack);
- vlan_iface =
- vlan_iface->vlan_next;
- }
- nic_iface = nic_iface->next;
- }
}
pthread_mutex_unlock(&nic->nic_mutex);
@@ -1001,7 +974,8 @@ int nic_enable(nic_t * nic)
*/
int nic_disable(nic_t * nic, int going_down)
{
- if (nic->state & (NIC_STARTED_RUNNING | NIC_RUNNING)) {
+ if (nic->state == NIC_STARTED_RUNNING ||
+ nic->state == NIC_RUNNING) {
struct timespec ts;
struct timeval tp;
int rc;
@@ -1012,8 +986,7 @@ int nic_disable(nic_t * nic, int going_down)
nic->flags &= ~NIC_ENABLED;
nic->flags |= NIC_DISABLED;
nic->flags &= ~NIC_STARTED_RUNNING;
- nic->state &= ~NIC_RUNNING;
- nic->state |= NIC_STOPPED;
+ nic->state = NIC_STOPPED;
if (going_down)
nic->flags |= NIC_GOING_DOWN;
@@ -1070,7 +1043,9 @@ void nic_remove_all()
nic = nic_list;
while (nic != NULL) {
nic_next = nic->next;
+ pthread_mutex_lock(&nic->nic_mutex);
nic_close(nic, 1, FREE_ALL_STRINGS);
+ pthread_mutex_unlock(&nic->nic_mutex);
nic_remove(nic);
nic = nic_next;
}
@@ -1127,14 +1102,13 @@ error:
* nic_set_all_nic_iface_mac_to_parent() - This is a utility function used to
* intialize all the MAC addresses of the network interfaces for a given
* CNIC UIO device
+ * Call with nic mutex held
* @param dev - CNIC UIO device to initialize
*/
-void nic_set_all_nic_iface_mac_to_parent(nic_t * nic)
+void nic_set_all_nic_iface_mac_to_parent(nic_t *nic)
{
nic_interface_t *current, *vlan_current;
- pthread_mutex_lock(&nic->nic_mutex);
-
current = nic->nic_iface;
while (current != NULL) {
/* Set the initial MAC address of this interface to the parent
@@ -1148,8 +1122,6 @@ void nic_set_all_nic_iface_mac_to_parent(nic_t * nic)
}
current = current->next;
}
-
- pthread_mutex_unlock(&nic->nic_mutex);
}
/*******************************************************************************
@@ -1272,143 +1244,144 @@ void nic_fill_ethernet_header(nic_interface_t * nic_iface,
* NIC interface management utility functions
******************************************************************************/
/**
- * nic_find_nic_iface() - This function is used to find an interface from the
- * NIC
- * @param nic - NIC to look for network interfaces
- * @param vlan_id - VLAN id to look for
- * @return nic_iface - if found network interface with the given VLAN ID
- * if not found a NULL is returned
- */
-nic_interface_t *nic_find_nic_iface(nic_t * nic, uint16_t vlan_id)
-{
- nic_interface_t *current;
-
- pthread_mutex_lock(&nic->nic_mutex);
-
- current = nic->nic_iface;
- while (current != NULL) {
- if (current->vlan_id == vlan_id) {
- pthread_mutex_unlock(&nic->nic_mutex);
- return current;
- }
-
- current = current->next;
- }
-
- pthread_mutex_unlock(&nic->nic_mutex);
-
- return NULL;
-}
-
-/**
- * nic_find_nic_iface_protocol() - This function is used to find an interface
- * from the NIC
+ * nic_find_nic_iface() - This function is used to find an interface
+ * from the NIC
* @param nic - NIC to look for network interfaces
* @param vlan_id - VLAN id to look for
* @param protocol - either AF_INET or AF_INET6
+ * @param iface_num - iface num to use if present
+ * @param request_type - IPV4/6 DHCP/STATIC
* @return nic_iface - if found network interface with the given VLAN ID
* if not found a NULL is returned
*/
-nic_interface_t *nic_find_nic_iface_protocol(nic_t * nic,
- uint16_t vlan_id,
- uint16_t protocol)
+nic_interface_t *nic_find_nic_iface(nic_t *nic,
+ uint16_t protocol,
+ uint16_t vlan_id,
+ int iface_num,
+ int request_type)
{
- nic_interface_t *current;
+ nic_interface_t *current = nic->nic_iface;
+ nic_interface_t *current_vlan = NULL;
- pthread_mutex_lock(&nic->nic_mutex);
-
- current = nic->nic_iface;
while (current != NULL) {
- if ((current->vlan_id == vlan_id) &&
- (current->protocol == protocol)) {
- pthread_mutex_unlock(&nic->nic_mutex);
- return current;
+ if (current->protocol != protocol)
+ goto next;
+
+ /* Check for iface_num first */
+ if (iface_num != IFACE_NUM_INVALID) {
+ if (current->iface_num == iface_num) {
+ /* Exception is when iface_num == 0, need to
+ check for request_type also if !=
+ IP_CONFIG_OFF */
+ if (!iface_num && request_type !=
+ IP_CONFIG_OFF) {
+ if (current->request_type ==
+ request_type)
+ goto found;
+ } else {
+ goto found;
+ }
+ }
+ } else if (vlan_id == NO_VLAN) {
+ /* Just return the top of the family */
+ goto found;
+ } else {
+ if ((current->vlan_id == vlan_id) &&
+ ((request_type == IP_CONFIG_OFF) ||
+ (current->request_type == request_type)))
+ goto found;
}
+ /* vlan_next loop */
+ current_vlan = current->vlan_next;
+ while (current_vlan != NULL) {
+ if (iface_num != IFACE_NUM_INVALID) {
+ if (current_vlan->iface_num == iface_num) {
+ if (!iface_num && request_type !=
+ IP_CONFIG_OFF) {
+ if (current_vlan->request_type
+ == request_type)
+ goto vlan_found;
+ } else {
+ goto vlan_found;
+ }
+ }
+ }
+ if ((current_vlan->vlan_id == vlan_id) &&
+ ((request_type == IP_CONFIG_OFF) ||
+ (current_vlan->request_type == request_type)))
+ goto vlan_found;
+ current_vlan = current_vlan->vlan_next;
+ }
+next:
current = current->next;
}
-
- pthread_mutex_unlock(&nic->nic_mutex);
-
- return NULL;
+vlan_found:
+ current = current_vlan;
+found:
+ return current;
}
+/* Called with nic mutex held */
void persist_all_nic_iface(nic_t * nic)
{
- nic_interface_t *current, *vlan_iface;
-
- pthread_mutex_lock(&nic->nic_mutex);
+ nic_interface_t *current_vlan, *current;
current = nic->nic_iface;
while (current != NULL) {
current->flags |= NIC_IFACE_PERSIST;
- vlan_iface = current->vlan_next;
- while (vlan_iface != NULL) {
- vlan_iface->flags |= NIC_IFACE_PERSIST;
- vlan_iface = vlan_iface->vlan_next;
+ current_vlan = current->vlan_next;
+ while (current_vlan != NULL) {
+ current_vlan->flags |= NIC_IFACE_PERSIST;
+ current_vlan = current_vlan->vlan_next;
}
current = current->next;
}
-
- pthread_mutex_unlock(&nic->nic_mutex);
-}
-
-/**
- * nic_find_vlan_iface_protocol() - This function is used to find an interface
- * from the NIC
- * @param nic_iface - Base NIC to look for the vlan interfaces
- * @param vlan_id - VLAN id to look for
- * @param protocol - either AF_INET or AF_INET6
- * @return nic_iface - if found network interface with the given VLAN ID
- * if not found a NULL is returned
- */
-nic_interface_t *nic_find_vlan_iface_protocol(nic_t *nic,
- nic_interface_t *nic_iface,
- uint16_t vlan_id,
- uint16_t protocol)
-{
- nic_interface_t *current;
-
- pthread_mutex_lock(&nic->nic_mutex);
-
- current = nic_iface->vlan_next;
- while (current != NULL) {
- if ((current->vlan_id == vlan_id) &&
- (current->protocol == protocol)) {
- pthread_mutex_unlock(&nic->nic_mutex);
- return current;
- }
- current = current->vlan_next;
- }
-
- pthread_mutex_unlock(&nic->nic_mutex);
- return NULL;
}
+/* Sets the nic_iface to the front of the AF */
void set_nic_iface(nic_t *nic, nic_interface_t *nic_iface)
{
nic_interface_t *current, *prev;
+ nic_interface_t *current_vlan, *prev_vlan;
- pthread_mutex_lock(&nic->nic_mutex);
-
- if (nic->nic_iface == nic_iface)
- goto done;
-
- prev = nic->nic_iface;
- current = nic->nic_iface->next;
+ prev = NULL;
+ current = nic->nic_iface;
while (current != NULL) {
- if (current == nic_iface) {
- prev->next = current->next;
- current->next = nic->nic_iface;
- nic->nic_iface = current;
+ if (current->protocol != nic_iface->protocol)
+ goto next;
+ /* If its already on top of the list, exit */
+ if (current == nic_iface)
goto done;
+
+ prev_vlan = current;
+ current_vlan = current->vlan_next;
+
+ while (current_vlan != NULL) {
+ if (current_vlan == nic_iface) {
+ /* Found inside the vlan list */
+ /* For vlan == 0, place on top of
+ the AF list */
+ prev_vlan->vlan_next =
+ current_vlan->vlan_next;
+ current_vlan->vlan_next = current;
+ if (prev)
+ prev->next = current_vlan;
+ else
+ nic->nic_iface = current_vlan;
+ goto done;
+ }
+ prev_vlan = current_vlan;
+ current_vlan = current_vlan->vlan_next;
}
+next:
prev = current;
current = current->next;
}
done:
- pthread_mutex_unlock(&nic->nic_mutex);
+ return;
}
+
/*******************************************************************************
* Packet management utility functions
******************************************************************************/
@@ -1639,7 +1612,7 @@ int capture_file(char **raw, uint32_t * raw_size, const char *path)
}
read_size = fread(*raw, file_size, 1, fp);
- if (read_size < 0) {
+ if (!read_size) {
LOG_ERR("Could not read capture, path: %s len: %d [%s]",
path, file_size, strerror(ferror(fp)));
free(*raw);
diff --git a/iscsiuio/src/unix/nic_utils.h b/iscsiuio/src/unix/nic_utils.h
index ff76f6b..6c57701 100644
--- a/iscsiuio/src/unix/nic_utils.h
+++ b/iscsiuio/src/unix/nic_utils.h
@@ -67,7 +67,9 @@ void nic_fill_ethernet_header(nic_interface_t * nic_iface,
int *pkt_size, void **start_addr,
uint16_t ether_type);
-nic_interface_t *nic_find_nic_iface(nic_t * nic, uint16_t vlan_id);
+struct nic_interface *nic_find_nic_iface(nic_t *nic, uint16_t protocol,
+ uint16_t vlan_id, int iface_num,
+ int request_type);
void set_nic_iface(nic_t *nic, nic_interface_t *nic_iface);
void persist_all_nic_iface(nic_t * nic);
diff --git a/iscsiuio/src/unix/nic_vlan.c b/iscsiuio/src/unix/nic_vlan.c
index 4f8f551..90a6244 100644
--- a/iscsiuio/src/unix/nic_vlan.c
+++ b/iscsiuio/src/unix/nic_vlan.c
@@ -332,7 +332,8 @@ int find_vlans_using_phy_interface(struct vlan_handle *handle,
*/
int valid_vlan(short int vlan)
{
- if (vlan > 1 && vlan < 4095)
+ /* Allow vlan 1 to connect */
+ if (vlan > 0 && vlan < 4095)
return 1;
return 0;
diff --git a/iscsiuio/src/unix/packet.c b/iscsiuio/src/unix/packet.c
index 4d8bf55..5047030 100644
--- a/iscsiuio/src/unix/packet.c
+++ b/iscsiuio/src/unix/packet.c
@@ -88,7 +88,7 @@ void free_packet(struct packet *pkt)
* reset_packet() - This will reset the packet fields to default values
* @param pkt - the packet to reset
*/
-void reset_packet(packet_t * pkt)
+void reset_packet(packet_t *pkt)
{
pkt->next = NULL;
@@ -101,7 +101,7 @@ void reset_packet(packet_t * pkt)
pkt->network_layer = NULL;
}
-int alloc_free_queue(nic_t * nic, size_t num_of_packets)
+int alloc_free_queue(nic_t *nic, size_t num_of_packets)
{
int rc, i;