Jelajahi Sumber

qcacld-3.0: Send anycast addresses for NS offload

Propagation from qcacld-2.0 to qcacld-3.0

Current implementation has support for IPv6 addresses of type
unicast for NS offload to firmware.

As part of this change add anycast addresses for NS offload.

Change-Id: I1151c8af3bbc815216c4ffd9668dd0b6561f222e
CRs-Fixed: 954880
Sravan Kumar Kairam 8 tahun lalu
induk
melakukan
c0873589a4
3 mengubah file dengan 125 tambahan dan 58 penghapusan
  1. 122 58
      core/hdd/src/wlan_hdd_power.c
  2. 1 0
      core/mac/inc/sir_api.h
  3. 2 0
      core/mac/inc/sir_mac_prot_def.h

+ 122 - 58
core/hdd/src/wlan_hdd_power.c

@@ -286,6 +286,91 @@ int wlan_hdd_ipv6_changed(struct notifier_block *nb,
 	return ret;
 }
 
+/**
+ * hdd_fill_ipv6_uc_addr() - fill IPv6 unicast addresses
+ * @idev: pointer to net device
+ * @ipv6addr: destination array to fill IPv6 addresses
+ * @ipv6addr_type: IPv6 Address type
+ * @count: number of IPv6 addresses
+ *
+ * This is the IPv6 utility function to populate unicast addresses.
+ *
+ * Return: 0 on success, error number otherwise.
+ */
+static int hdd_fill_ipv6_uc_addr(struct inet6_dev *idev,
+				uint8_t ipv6_uc_addr[][SIR_MAC_IPV6_ADDR_LEN],
+				uint8_t *ipv6addr_type, uint32_t *count)
+{
+	struct inet6_ifaddr *ifa;
+	struct list_head *p;
+	uint32_t scope;
+
+	list_for_each(p, &idev->addr_list) {
+		if (*count >= SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA)
+			return -EINVAL;
+		ifa = list_entry(p, struct inet6_ifaddr, if_list);
+		if (ifa->flags & IFA_F_DADFAILED)
+			continue;
+		scope = ipv6_addr_src_scope(&ifa->addr);
+		switch (scope) {
+		case IPV6_ADDR_SCOPE_GLOBAL:
+		case IPV6_ADDR_SCOPE_LINKLOCAL:
+			qdf_mem_copy(ipv6_uc_addr[*count], &ifa->addr.s6_addr,
+				sizeof(ifa->addr.s6_addr));
+			ipv6addr_type[*count] = SIR_IPV6_ADDR_UC_TYPE;
+			hdd_info("Index %d scope = %s UC-Address: %pI6",
+				*count, (scope == IPV6_ADDR_SCOPE_LINKLOCAL) ?
+				"LINK LOCAL" : "GLOBAL", ipv6_uc_addr[*count]);
+			*count += 1;
+			break;
+		default:
+			hdd_err("The Scope %d is not supported", scope);
+		}
+	}
+	return 0;
+}
+
+/**
+ * hdd_fill_ipv6_ac_addr() - fill IPv6 anycast addresses
+ * @idev: pointer to net device
+ * @ipv6addr: destination array to fill IPv6 addresses
+ * @ipv6addr_type: IPv6 Address type
+ * @count: number of IPv6 addresses
+ *
+ * This is the IPv6 utility function to populate anycast addresses.
+ *
+ * Return: 0 on success, error number otherwise.
+ */
+static int hdd_fill_ipv6_ac_addr(struct inet6_dev *idev,
+				uint8_t ipv6_ac_addr[][SIR_MAC_IPV6_ADDR_LEN],
+				uint8_t *ipv6addr_type, uint32_t *count)
+{
+	struct ifacaddr6 *ifaca;
+	uint32_t scope;
+
+	for (ifaca = idev->ac_list; ifaca; ifaca = ifaca->aca_next) {
+		if (*count >= SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA)
+			return -EINVAL;
+		/* For anycast addr no DAD */
+		scope = ipv6_addr_src_scope(&ifaca->aca_addr);
+		switch (scope) {
+		case IPV6_ADDR_SCOPE_GLOBAL:
+		case IPV6_ADDR_SCOPE_LINKLOCAL:
+			qdf_mem_copy(ipv6_ac_addr[*count], &ifaca->aca_addr,
+				sizeof(ifaca->aca_addr));
+			ipv6addr_type[*count] = SIR_IPV6_ADDR_AC_TYPE;
+			hdd_info("Index %d scope = %s AC-Address: %pI6",
+				*count, (scope == IPV6_ADDR_SCOPE_LINKLOCAL) ?
+				"LINK LOCAL" : "GLOBAL", ipv6_ac_addr[*count]);
+			*count += 1;
+			break;
+		default:
+			hdd_err("The Scope %d is not supported", scope);
+		}
+	}
+	return 0;
+}
+
 /**
  * hdd_conf_ns_offload() - Configure NS offload
  * @pAdapter:   pointer to the adapter
@@ -298,18 +383,15 @@ int wlan_hdd_ipv6_changed(struct notifier_block *nb,
 static void hdd_conf_ns_offload(hdd_adapter_t *pAdapter, bool fenable)
 {
 	struct inet6_dev *in6_dev;
-	struct inet6_ifaddr *ifp;
-	struct list_head *p;
-	uint8_t
-		selfIPv6Addr[SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA]
-	[SIR_MAC_IPV6_ADDR_LEN] = { {0,} };
-	bool selfIPv6AddrValid[SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA] = { 0 };
+	uint8_t ipv6_addr[SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA]
+					[SIR_MAC_IPV6_ADDR_LEN] = { {0,} };
+	uint8_t ipv6_addr_type[SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA] = { 0 };
 	tSirHostOffloadReq offLoadRequest;
 	hdd_context_t *pHddCtx;
 
-	int i = 0;
+	int i = 0, ret;
 	QDF_STATUS returnStatus;
-	uint32_t count = 0, scope;
+	uint32_t count = 0;
 
 	ENTER();
 	hdd_notice(" fenable = %d", fenable);
@@ -330,38 +412,26 @@ static void hdd_conf_ns_offload(hdd_adapter_t *pAdapter, bool fenable)
 	if (fenable) {
 		in6_dev = __in6_dev_get(pAdapter->dev);
 		if (NULL != in6_dev) {
-			/* read_lock_bh(&in6_dev->lock); */
-			list_for_each(p, &in6_dev->addr_list) {
-				if (count >=
-					SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA) {
-					hdd_err("Reached max supported NS Offload addresses");
-					break;
-				}
-				ifp =
-					list_entry(p, struct inet6_ifaddr, if_list);
-				scope = ipv6_addr_src_scope(&ifp->addr);
-
-				switch (scope) {
-				case IPV6_ADDR_SCOPE_GLOBAL:
-				case IPV6_ADDR_SCOPE_LINKLOCAL:
-					qdf_mem_copy(&selfIPv6Addr[count],
-						&ifp->addr.s6_addr,
-						sizeof(ifp->addr.s6_addr));
-					selfIPv6AddrValid[count] =
-						SIR_IPV6_ADDR_VALID;
-					hdd_info("Index %d scope = %s Address : %pI6",
-					  count,
-					  (scope == IPV6_ADDR_SCOPE_LINKLOCAL) ?
-					  "LINK LOCAL" : "GLOBAL",
-					  selfIPv6Addr[count]);
-					count += 1;
-					break;
-				default:
-					hdd_err("The Scope %d is not supported",
-						scope);
-				}
+			/* Unicast Addresses */
+			ret = hdd_fill_ipv6_uc_addr(in6_dev, ipv6_addr,
+						ipv6_addr_type, &count);
+
+			if (0 > ret) {
+				hdd_notice(
+				"Reached max supported addresses and not enabling NS offload");
+				return;
+			}
+
+			/* Anycast Addresses */
+			ret = hdd_fill_ipv6_ac_addr(in6_dev, ipv6_addr,
+						ipv6_addr_type, &count);
+
+			if (0 > ret) {
+				hdd_notice(
+				"Reached max supported addresses and not enabling NS offload");
+				return;
 			}
-			/* read_unlock_bh(&in6_dev->lock); */
+
 			qdf_mem_zero(&offLoadRequest, sizeof(offLoadRequest));
 			for (i = 0; i < count; i++) {
 				/* Filling up the request structure
@@ -379,30 +449,21 @@ static void hdd_conf_ns_offload(hdd_adapter_t *pAdapter, bool fenable)
 				offLoadRequest.nsOffloadInfo.selfIPv6Addr[i][11] = 0x01;
 				offLoadRequest.nsOffloadInfo.selfIPv6Addr[i][12] = 0xFF;
 				offLoadRequest.nsOffloadInfo.selfIPv6Addr[i][13] =
-					selfIPv6Addr[i][13];
+							ipv6_addr[i][13];
 				offLoadRequest.nsOffloadInfo.selfIPv6Addr[i][14] =
-					selfIPv6Addr[i][14];
+							ipv6_addr[i][14];
 				offLoadRequest.nsOffloadInfo.selfIPv6Addr[i][15] =
-					selfIPv6Addr[i][15];
+							ipv6_addr[i][15];
 				offLoadRequest.nsOffloadInfo.slotIdx = i;
-				qdf_mem_copy(&offLoadRequest.nsOffloadInfo.targetIPv6Addr[i],
-					&selfIPv6Addr[i][0], SIR_MAC_IPV6_ADDR_LEN);
+				qdf_mem_copy(&offLoadRequest.nsOffloadInfo.
+					targetIPv6Addr[i], &ipv6_addr[i][0],
+					SIR_MAC_IPV6_ADDR_LEN);
 
 				offLoadRequest.nsOffloadInfo.targetIPv6AddrValid[i] =
-					SIR_IPV6_ADDR_VALID;
-
-				hdd_info("configuredMcastBcastFilter: %d",
-					pHddCtx->configuredMcastBcastFilter);
-
-				if ((true == pHddCtx->sus_res_mcastbcast_filter_valid)
-					&& ((HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST ==
-					pHddCtx->sus_res_mcastbcast_filter) ||
-					(HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST ==
-					pHddCtx->sus_res_mcastbcast_filter))) {
-					hdd_info("Set offLoadRequest with SIR_OFFLOAD_NS_AND_MCAST_FILTER_ENABLE");
-					offLoadRequest.enableOrDisable =
-						SIR_OFFLOAD_NS_AND_MCAST_FILTER_ENABLE;
-				}
+							SIR_IPV6_ADDR_VALID;
+				offLoadRequest.nsOffloadInfo.
+						target_ipv6_addr_ac_type[i] =
+							ipv6_addr_type[i];
 
 				qdf_mem_copy(&offLoadRequest.params.hostIpv6Addr,
 					&offLoadRequest.nsOffloadInfo.targetIPv6Addr[i],
@@ -412,6 +473,9 @@ static void hdd_conf_ns_offload(hdd_adapter_t *pAdapter, bool fenable)
 					&offLoadRequest.nsOffloadInfo.selfIPv6Addr[i],
 					&offLoadRequest.nsOffloadInfo.targetIPv6Addr[i], i);
 			}
+
+			hdd_info("configuredMcastBcastFilter: %d",
+				pHddCtx->configuredMcastBcastFilter);
 			hdd_wlan_offload_event(SIR_IPV6_NS_OFFLOAD,
 				SIR_OFFLOAD_ENABLE);
 			offLoadRequest.offloadType =  SIR_IPV6_NS_OFFLOAD;

+ 1 - 0
core/mac/inc/sir_api.h

@@ -2612,6 +2612,7 @@ typedef struct sSirNsOffloadReq {
 	struct qdf_mac_addr self_macaddr;
 	uint8_t srcIPv6AddrValid;
 	uint8_t targetIPv6AddrValid[SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA];
+	uint8_t target_ipv6_addr_ac_type[SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA];
 	uint8_t slotIdx;
 } tSirNsOffloadReq, *tpSirNsOffloadReq;
 #endif /* WLAN_NS_OFFLOAD */

+ 2 - 0
core/mac/inc/sir_mac_prot_def.h

@@ -497,6 +497,8 @@
 #define SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA   16
 #define SIR_MAC_IPV6_ADDR_LEN               16
 #define SIR_IPV6_ADDR_VALID                 1
+#define SIR_IPV6_ADDR_UC_TYPE               0
+#define SIR_IPV6_ADDR_AC_TYPE               1
 #endif /* WLAN_NS_OFFLOAD */
 
 /* ----------------------------------------------------------------------------- */