[ipxe-devel] [PATCH 11/11] ibft: multiple session support

Hannes Reinecke hare at suse.de
Thu May 7 10:25:06 BST 2015


It is possible to open several iSCSI sessions, so we should be
updating the iBFT tables to handle several connections.

Signed-off-by: Hannes Reinecke <hare at suse.de>
---
 src/drivers/block/ibft.c | 183 ++++++++++++++++++++++++++++++++++-------------
 1 file changed, 132 insertions(+), 51 deletions(-)

diff --git a/src/drivers/block/ibft.c b/src/drivers/block/ibft.c
index 47d0a4b..827d9bf 100644
--- a/src/drivers/block/ibft.c
+++ b/src/drivers/block/ibft.c
@@ -64,10 +64,14 @@ struct ipxe_ibft {
 	struct ibft_table table;
 	/** The Initiator section */
 	struct ibft_initiator initiator __attribute__ (( aligned ( 16 ) ));
-	/** The NIC section */
-	struct ibft_nic nic __attribute__ (( aligned ( 16 ) ));
-	/** The Target section */
-	struct ibft_target target __attribute__ (( aligned ( 16 ) ));
+	/** The 1. NIC section */
+	struct ibft_nic nic0 __attribute__ (( aligned ( 16 ) ));
+	/** The 1. Target section */
+	struct ibft_target target0 __attribute__ (( aligned ( 16 ) ));
+	/** The 2. NIC section */
+	struct ibft_nic nic1 __attribute__ (( aligned ( 16 ) ));
+	/** The 2. Target section */
+	struct ibft_target target1 __attribute__ (( aligned ( 16 ) ));
 	/** Strings block */
 	char strings[0];
 } __attribute__ (( packed, aligned ( 16 ) ));
@@ -276,9 +280,7 @@ static const char * ibft_string ( struct ibft_strings *strings,
  * @ret netdev		Return network device
  */
 static struct net_device * ibft_fill_nic_ipv4 ( struct ibft_nic *nic,
-						struct sockaddr_in *dest ) {
-
-	struct ipv4_miniroute *route4 = ipv4_route(&dest->sin_addr);
+						struct ipv4_miniroute *route4 ) {
 	struct settings *parent;
 	struct settings *origin;
 	struct in_addr netmask_addr = { 0 };
@@ -290,19 +292,23 @@ static struct net_device * ibft_fill_nic_ipv4 ( struct ibft_nic *nic,
 
 	nic->origin = ( ( origin == parent ) ?
 			IBFT_NIC_ORIGIN_MANUAL : IBFT_NIC_ORIGIN_DHCP );
-	DBG ( "iBFT NIC origin = %d\n", nic->origin );
+	DBG ( "iBFT NIC[%d] origin = %d\n",
+	      nic->header.index, nic->origin );
 
 	/* Extract values from configuration settings */
 	fetch_setting ( parent, &ip_setting, &origin, NULL, NULL, 0 );
 
 	ibft_set_ipaddr ( &nic->ip_address, route4->address );
-	DBG ( "iBFT NIC IP = %s\n", ibft_ipaddr ( &nic->ip_address ) );
+	DBG ( "iBFT NIC[%d] IP = %s\n", nic->header.index,
+	      ibft_ipaddr ( &nic->ip_address ) );
 	ibft_set_ipaddr ( &nic->gateway, route4->gateway );
-	DBG ( "iBFT NIC gateway = %s\n", ibft_ipaddr ( &nic->gateway ) );
+	DBG ( "iBFT NIC[%d] gateway = %s\n", nic->header.index,
+	      ibft_ipaddr ( &nic->gateway ) );
 	ibft_set_ipaddr_setting ( NULL, &nic->dns[0], &dns_setting,
 				  ( sizeof ( nic->dns ) /
 				    sizeof ( nic->dns[0] ) ) );
-	DBG ( "iBFT NIC DNS = %s", ibft_ipaddr ( &nic->dns[0] ) );
+	DBG ( "iBFT NIC[%d] DNS = %s", nic->header.index,
+	      ibft_ipaddr ( &nic->dns[0] ) );
 	DBG ( ", %s\n", ibft_ipaddr ( &nic->dns[1] ) );
 	/* Derive subnet mask prefix from subnet mask */
 	netmask_addr = route4->netmask;
@@ -312,7 +318,8 @@ static struct net_device * ibft_fill_nic_ipv4 ( struct ibft_nic *nic,
 		netmask_addr.s_addr >>= 1;
 	}
 	nic->subnet_mask_prefix = netmask_count;
-	DBG ( "iBFT NIC subnet = /%d\n", nic->subnet_mask_prefix );
+	DBG ( "iBFT NIC[%d] subnet = /%d\n", nic->header.index,
+	      nic->subnet_mask_prefix );
 	return route4->netdev;
 }
 
@@ -324,31 +331,34 @@ static struct net_device * ibft_fill_nic_ipv4 ( struct ibft_nic *nic,
  * @ret rc		Return network device
  */
 static struct net_device * ibft_fill_nic_ipv6 ( struct ibft_nic *nic,
-						struct sockaddr_in6 * dest ) {
-	struct ipv6_miniroute *route6;
-	struct in6_addr *router = &dest->sin6_addr;
+						struct ipv6_miniroute *route6,
+						struct in6_addr * router ) {
 	struct settings *parent;
 	struct settings *origin;
 
-	route6 = ipv6_route(dest->sin6_scope_id, &router);
 	parent = netdev_settings(route6->netdev);
 	fetch_setting ( parent, &ip6_setting, &origin, NULL, NULL, 0 );
 	nic->origin = ( ( origin == parent ) ?
 			IBFT_NIC_ORIGIN_MANUAL : IBFT_NIC_ORIGIN_DHCP );
-	DBG ( "iBFT NIC origin = %d\n", nic->origin );
+	DBG ( "iBFT NIC[%d] origin = %d\n",
+	      nic->header.index, nic->origin );
 
 	/* Extract values from configuration settings */
 	ibft_set_ip6addr ( &nic->ip_address, route6->address );
-	DBG ( "iBFT NIC IP = %s\n", ibft_ipaddr ( &nic->ip_address ) );
+	DBG ( "iBFT NIC[%d] IP = %s\n",
+	      nic->header.index, ibft_ipaddr ( &nic->ip_address ) );
 	ibft_set_ip6addr ( &nic->gateway, *router );
-	DBG ( "iBFT NIC gateway = %s\n", ibft_ipaddr ( &nic->gateway ) );
+	DBG ( "iBFT NIC[%d] gateway = %s\n",
+	      nic->header.index, ibft_ipaddr ( &nic->gateway ) );
 	ibft_set_ip6addr_setting ( NULL, &nic->dns[0], &dns6_setting,
 				   ( sizeof ( nic->dns ) /
 				     sizeof ( nic->dns[0] ) ) );
-	DBG ( "iBFT NIC DNS = %s", ibft_ipaddr ( &nic->dns[0] ) );
+	DBG ( "iBFT NIC[%d] DNS = %s", nic->header.index,
+	      ibft_ipaddr ( &nic->dns[0] ) );
 	DBG ( ", %s\n", ibft_ipaddr ( &nic->dns[1] ) );
 	nic->subnet_mask_prefix = route6->prefix_len;
-	DBG ( "iBFT NIC subnet = /%d\n", nic->subnet_mask_prefix );
+	DBG ( "iBFT NIC[%d] subnet = /%d\n",
+	      nic->header.index, nic->subnet_mask_prefix );
 
 	return route6->netdev;
 }
@@ -363,44 +373,79 @@ static struct net_device * ibft_fill_nic_ipv6 ( struct ibft_nic *nic,
  */
 static int ibft_fill_nic ( struct ibft_nic *nic,
 			   struct ibft_strings *strings,
-			   struct iscsi_session *iscsi ) {
+			   struct iscsi_session *iscsi,
+			   int nic_index ) {
 	struct sockaddr_in *sin_target =
 		( struct sockaddr_in * ) &iscsi->target_sockaddr;
 	struct sockaddr_in6 *sin6_target =
 		( struct sockaddr_in6 * ) &iscsi->target_sockaddr;
+	struct ipv4_miniroute * route4 = NULL;
+	struct ipv6_miniroute * route6 = NULL;
+	struct in6_addr *router6;
 	struct net_device *netdev;
 	struct ll_protocol *ll_protocol;
 	int rc;
 
+	if (sin_target->sin_family == AF_INET) {
+		struct in_addr router4 = sin_target->sin_addr;
+		route4 = ipv4_route(&router4);
+		if (!route4)
+			return -EHOSTUNREACH;
+		if (nic->header.flags & IBFT_FL_NIC_BLOCK_VALID) {
+			struct ibft_ipaddr tmp;
+			ibft_set_ipaddr( &tmp, route4->address );
+			if (memcmp(&nic->ip_address, &tmp, sizeof(tmp)))
+				return -EBUSY;
+		}
+	} else if (sin6_target->sin6_family == AF_INET6) {
+		router6 = &sin6_target->sin6_addr;
+		route6 = ipv6_route(sin6_target->sin6_scope_id, &router6);
+		if (!route6)
+			return -EHOSTUNREACH;
+		if (nic->header.flags & IBFT_FL_NIC_BLOCK_VALID) {
+			struct ibft_ipaddr tmp;
+			ibft_set_ip6addr( &tmp, route6->address );
+			if (memcmp(&nic->ip_address, &tmp, sizeof(tmp)))
+				return -EBUSY;
+		}
+	} else
+		return -EPROTONOSUPPORT;
+
+
 	/* Fill in common header */
 	nic->header.structure_id = IBFT_STRUCTURE_ID_NIC;
 	nic->header.version = 1;
+	nic->header.index = nic_index;
 	nic->header.length = cpu_to_le16 ( sizeof ( *nic ) );
 	nic->header.flags = ( IBFT_FL_NIC_BLOCK_VALID |
 			      IBFT_FL_NIC_FIRMWARE_BOOT_SELECTED );
 
 	if (sin_target->sin_family == AF_INET)
-		netdev = ibft_fill_nic_ipv4( nic, sin_target );
+		netdev = ibft_fill_nic_ipv4( nic, route4 );
 	else
-		netdev = ibft_fill_nic_ipv6( nic, sin6_target );
+		netdev = ibft_fill_nic_ipv6( nic, route6, router6 );
 
 	/* Extract values from net-device configuration */
 	nic->vlan = cpu_to_le16 ( vlan_tag ( netdev ) );
-	DBG ( "iBFT NIC VLAN = %02x\n", le16_to_cpu ( nic->vlan ) );
+	DBG ( "iBFT NIC[%d] VLAN = %02x\n",
+	      nic->header.index, le16_to_cpu ( nic->vlan ) );
 	ll_protocol = netdev->ll_protocol;
 	if ( ( rc = ll_protocol->eth_addr ( netdev->ll_addr,
 					    nic->mac_address ) ) != 0 ) {
 		DBG ( "Could not determine iBFT MAC: %s\n", strerror ( rc ) );
 		return rc;
 	}
-	DBG ( "iBFT NIC MAC = %s\n", eth_ntoa ( nic->mac_address ) );
+	DBG ( "iBFT NIC[%d] MAC = %s\n",
+	      nic->header.index, eth_ntoa ( nic->mac_address ) );
 	nic->pci_bus_dev_func = cpu_to_le16 ( netdev->dev->desc.location );
-	DBG ( "iBFT NIC PCI = %04x\n", le16_to_cpu ( nic->pci_bus_dev_func ) );
+	DBG ( "iBFT NIC[%d] PCI = %04x\n",
+	      nic->header.index, le16_to_cpu ( nic->pci_bus_dev_func ) );
 
 	if ( ( rc = ibft_set_string_setting ( NULL, strings, &nic->hostname,
 					      &hostname_setting ) ) != 0 )
 		return rc;
-	DBG ( "iBFT NIC hostname = %s\n",
+	DBG ( "iBFT NIC[%d] hostname = %s\n",
+	      nic->header.index,
 	      ibft_string ( strings, &nic->hostname ) );
 
 	return 0;
@@ -459,12 +504,14 @@ static int ibft_fill_target_chap ( struct ibft_target *target,
 	if ( ( rc = ibft_set_string ( strings, &target->chap_name,
 				      iscsi->initiator_username ) ) != 0 )
 		return rc;
-	DBG ( "iBFT target username = %s\n",
+	DBG ( "iBFT target[%d] username = %s\n",
+	      target->header.index,
 	      ibft_string ( strings, &target->chap_name ) );
 	if ( ( rc = ibft_set_string ( strings, &target->chap_secret,
 				      iscsi->initiator_password ) ) != 0 )
 		return rc;
-	DBG ( "iBFT target password = <redacted>\n" );
+	DBG ( "iBFT target[%d] password = <redacted>\n",
+		target->header.index );
 
 	return 0;
 }
@@ -494,12 +541,14 @@ static int ibft_fill_target_reverse_chap ( struct ibft_target *target,
 	if ( ( rc = ibft_set_string ( strings, &target->reverse_chap_name,
 				      iscsi->target_username ) ) != 0 )
 		return rc;
-	DBG ( "iBFT target reverse username = %s\n",
+	DBG ( "iBFT target[%d] reverse username = %s\n",
+	      target->header.index,
 	      ibft_string ( strings, &target->chap_name ) );
 	if ( ( rc = ibft_set_string ( strings, &target->reverse_chap_secret,
 				      iscsi->target_password ) ) != 0 )
 		return rc;
-	DBG ( "iBFT target reverse password = <redacted>\n" );
+	DBG ( "iBFT target[%d] reverse password = <redacted>\n",
+		target->header.index );
 
 	return 0;
 }
@@ -514,15 +563,29 @@ static int ibft_fill_target_reverse_chap ( struct ibft_target *target,
  */
 static int ibft_fill_target ( struct ibft_target *target,
 			      struct ibft_strings *strings,
-			      struct iscsi_session *iscsi ) {
+			      struct iscsi_session *iscsi,
+			      int target_index, int nic_index ) {
 	struct sockaddr_in *sin_target =
 		( struct sockaddr_in * ) &iscsi->target_sockaddr;
 	struct sockaddr_in6 *sin6_target =
 		( struct sockaddr_in6 * ) &iscsi->target_sockaddr;
 	int rc;
 
-	if (sin6_target->sin6_family != AF_INET6 &&
-	    sin_target->sin_family != AF_INET) {
+	if (sin_target->sin_family == AF_INET) {
+		if (target->header.flags & IBFT_FL_TARGET_BLOCK_VALID) {
+			struct ibft_ipaddr tmp;
+			ibft_set_ipaddr ( &tmp, sin_target->sin_addr );
+			if ( memcmp( &target->ip_address, &tmp, sizeof(tmp) ))
+				return -EBUSY;
+		}
+	} else if (sin6_target->sin6_family == AF_INET6) {
+		if (target->header.flags & IBFT_FL_TARGET_BLOCK_VALID) {
+			struct ibft_ipaddr tmp;
+			ibft_set_ip6addr ( &tmp, sin6_target->sin6_addr );
+			if ( memcmp( &target->ip_address, &tmp, sizeof(tmp) ))
+				return -EBUSY;
+		}
+	} else {
 		DBG ( "iBFT invalid IP address type %d\n",
 		      sin6_target->sin6_family );
 		return -EPROTONOSUPPORT;
@@ -530,31 +593,34 @@ static int ibft_fill_target ( struct ibft_target *target,
 	/* Fill in common header */
 	target->header.structure_id = IBFT_STRUCTURE_ID_TARGET;
 	target->header.version = 1;
+	target->header.index = target_index;
 	target->header.length = cpu_to_le16 ( sizeof ( *target ) );
 	target->header.flags = ( IBFT_FL_TARGET_BLOCK_VALID |
 				 IBFT_FL_TARGET_FIRMWARE_BOOT_SELECTED );
 
+	target->nic_association = nic_index;
 	/* Fill in Target values */
 	if (sin_target->sin_family == AF_INET) {
 		ibft_set_ipaddr ( &target->ip_address, sin_target->sin_addr );
-		DBG ( "iBFT target IP = %s\n",
+		DBG ( "iBFT target[%d] IP = %s\n", target_index,
 		      ibft_ipaddr ( &target->ip_address ) );
 		target->socket = cpu_to_le16 ( ntohs ( sin_target->sin_port ) );
-		DBG ( "iBFT target port = %d\n", target->socket );
+		DBG ( "iBFT target[%d] port = %d\n", target_index,
+		      target->socket );
 	} else {
 		ibft_set_ip6addr ( &target->ip_address, sin6_target->sin6_addr );
-		DBG ( "iBFT target IP = %s\n",
+		DBG ( "iBFT target[%d] IP = %s\n", target_index,
 		      ibft_ipaddr ( &target->ip_address ) );
 		target->socket = cpu_to_le16 ( ntohs ( sin6_target->sin6_port ) );
-		DBG ( "iBFT target port = %d\n", target->socket );
+		DBG ( "iBFT target[%d] port = %d\n", target_index, target->socket );
 	}
 	memcpy ( &target->boot_lun, &iscsi->lun, sizeof ( target->boot_lun ) );
-	DBG ( "iBFT target boot LUN = " SCSI_LUN_FORMAT "\n",
-	      SCSI_LUN_DATA ( target->boot_lun ) );
+	DBG ( "iBFT target[%d] boot LUN = " SCSI_LUN_FORMAT "\n",
+	      target_index, SCSI_LUN_DATA ( target->boot_lun ) );
 	if ( ( rc = ibft_set_string ( strings, &target->target_name,
 				      iscsi->target_iqn ) ) != 0 )
 		return rc;
-	DBG ( "iBFT target name = %s\n",
+	DBG ( "iBFT target[%d] name = %s\n", target_index,
 	      ibft_string ( strings, &target->target_name ) );
 	if ( ( rc = ibft_fill_target_chap ( target, strings, iscsi ) ) != 0 )
 		return rc;
@@ -583,9 +649,11 @@ int ibft_describe ( struct iscsi_session *iscsi,
 		.offset = offsetof ( typeof ( *ibft ), strings ),
 		.len = len,
 	};
+	int nic_index = 0;
 	int rc;
 
 	/* Fill in ACPI header */
+	DBG ( "iBFT table %p\n", ibft);
 	ibft->table.acpi.signature = cpu_to_le32 ( IBFT_SIG );
 	ibft->table.acpi.length = cpu_to_le32 ( len );
 	ibft->table.acpi.revision = 1;
@@ -598,20 +666,33 @@ int ibft_describe ( struct iscsi_session *iscsi,
 	ibft->table.control.initiator =
 		cpu_to_le16 ( offsetof ( typeof ( *ibft ), initiator ) );
 	ibft->table.control.nic_0 =
-		cpu_to_le16 ( offsetof ( typeof ( *ibft ), nic ) );
+		cpu_to_le16 ( offsetof ( typeof ( *ibft ), nic0 ) );
 	ibft->table.control.target_0 =
-		cpu_to_le16 ( offsetof ( typeof ( *ibft ), target ) );
+		cpu_to_le16 ( offsetof ( typeof ( *ibft ), target0 ) );
+	ibft->table.control.nic_1 =
+		cpu_to_le16 ( offsetof ( typeof ( *ibft ), nic1 ) );
+	ibft->table.control.target_1 =
+		cpu_to_le16 ( offsetof ( typeof ( *ibft ), target1 ) );
 
-	/* Fill in NIC, Initiator and Target blocks */
-	if ( ( rc = ibft_fill_nic ( &ibft->nic, &strings,
-				    iscsi ) ) != 0 )
-		return rc;
+	/* Fill in Initiator block */
 	if ( ( rc = ibft_fill_initiator ( &ibft->initiator, &strings,
 					  iscsi ) ) != 0 )
 		return rc;
-	if ( ( rc = ibft_fill_target ( &ibft->target, &strings,
-				       iscsi ) ) != 0 )
+	/* Fill in NIC blocks */
+	rc = ibft_fill_nic ( &ibft->nic0, &strings, iscsi, nic_index );
+	if ( rc == -EBUSY ) {
+		nic_index++;
+		rc = ibft_fill_nic( &ibft->nic1, &strings, iscsi, nic_index );
+	}
+	if ( rc != 0 )
 		return rc;
 
-	return 0;
+	/* Fill in target blocks */
+	rc = ibft_fill_target ( &ibft->target0, &strings, iscsi,
+				0, nic_index );
+	if ( rc == -EBUSY ) {
+		rc = ibft_fill_target ( &ibft->target1, &strings,
+					iscsi, 1, nic_index );
+	}
+	return rc;
 }
-- 
1.8.4.5



More information about the ipxe-devel mailing list