socsvn commit: r337279 - soc2018/sduo/head/sys/dev/vale_vlan

sduo at FreeBSD.org sduo at FreeBSD.org
Thu Aug 2 10:26:04 UTC 2018


Author: sduo
Date: Thu Aug  2 10:26:00 2018
New Revision: 337279
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=337279

Log:
  Updated vale_vlan files.

Modified:
  soc2018/sduo/head/sys/dev/vale_vlan/vale_vlan.c

Modified: soc2018/sduo/head/sys/dev/vale_vlan/vale_vlan.c
==============================================================================
--- soc2018/sduo/head/sys/dev/vale_vlan/vale_vlan.c	Thu Aug  2 10:14:21 2018	(r337278)
+++ soc2018/sduo/head/sys/dev/vale_vlan/vale_vlan.c	Thu Aug  2 10:26:00 2018	(r337279)
@@ -12,60 +12,90 @@
 tag_frame(struct nm_bdg_fwd *ft, struct netmap_vp_adapter *vpna,
 	  uint16_t vlan_id)
 {
-	struct nm_bdg_fwd *ft_end = ft + ft->ft_frags - 1;
-	struct nm_bdg_fwd *ft_cur = NULL;
-	uint8_t *buf		  = NULL;
-	uint32_t buf_size;
 	uint16_t be_tpid;
 	uint16_t be_tci; /* at the moment PCP and DEI are always set to 0 */
-	int n_bytes = 0;
+	char *buf;
 
-	buf_size = NETMAP_BUF_SIZE((struct netmap_adapter *)vpna);
-	if (ft_end->ft_len + TAG_LENGTH > buf_size) {
-		nm_prinf("Not enough space for the tag in the last fragment\n");
-		return EINVAL;
-	}
-	if (ft->ft_offset + TAG_END > ft->ft_len) {
+	if (ft->ft_virtio_offset + TAG_END > ft->ft_len) {
 		nm_prinf("Header split between two nm_bdg_fwd,"
 			 "at the moment not supported\n");
 		return EINVAL;
 	}
 
-	ft_end->ft_len += TAG_LENGTH;
-	for (ft_cur = ft_end; ft_cur != ft - 1; --ft_cur) {
-		uint8_t *start_addr = NULL;
-		uint8_t *dest_addr  = NULL;
-		uint16_t buf_len    = ft_cur->ft_len;
-		buf		    = ft_cur->ft_buf;
+	if (likely(ft->ft_head_space >= TAG_LENGTH)) {
+		/* Best case: the netmap slot has an offset >= TAG_LENGTH,
+		 * thus we can just move the virtio-net header + MAC addresses
+		 * back by TAG_LENGTH bytes
+		 */
+		if (ft->ft_flags & NS_INDIRECT) {
+			return EINVAL;
+		}
 
-		if (ft_cur->ft_flags & NS_INDIRECT) {
+		buf = (char *)ft->ft_buf - TAG_LENGTH;
+		memmove(buf, ft->ft_buf, TAG_START + ft->ft_virtio_offset);
+		ft->ft_head_space -= TAG_LENGTH;
+		ft->ft_len += TAG_LENGTH;
+		ft->ft_buf = buf;
+	} else {
+		/* Worst case: we need to move everything forward by
+		 * TAG_LENGTH bytes.
+		 */
+		struct nm_bdg_fwd *ft_end = ft + ft->ft_frags - 1;
+		uint32_t buf_size =
+			NETMAP_BUF_SIZE(&vpna->up, ft->ft_head_space);
+		struct nm_bdg_fwd *ft_cur;
+
+		if (ft_end->ft_len + ft_end->ft_head_space + TAG_LENGTH >
+		    buf_size) {
+			nm_prinf("Not enough space for the tag in the last "
+				 "fragment\n");
 			return EINVAL;
 		}
-		if (ft_cur != ft_end) {
-			/* copy 4 bytes from the end of the current buffer
-			 * to the beginning of the next buffer
+		ft_end->ft_len += TAG_LENGTH;
+
+		for (ft_cur = ft_end; ft_cur != ft - 1; --ft_cur) {
+			uint16_t buf_len = ft_cur->ft_len;
+			uint8_t *start_addr;
+			uint8_t *dest_addr;
+			int n_bytes;
+
+			if (ft_cur->ft_flags & NS_INDIRECT) {
+				return EINVAL;
+			}
+
+			buf = ft_cur->ft_buf;
+			if (ft_cur != ft_end) {
+				/* copy 4 bytes from the end of the current
+				 * buffer
+				 * to the beginning of the next buffer
+				 */
+				uint8_t *next_buf = (ft_cur + 1)->ft_buf;
+
+				start_addr = buf + buf_len - TAG_LENGTH;
+				dest_addr  = next_buf;
+				*(uint32_t *)dest_addr =
+					*(uint32_t *)start_addr;
+			}
+
+			start_addr = buf + ft_cur->ft_virtio_offset;
+			dest_addr  = start_addr + TAG_LENGTH;
+			/* we already added TAG_LENGTH to ft_end->ft_len,
+			 * therefore the
+			 * last fragment case is covered without any additional
+			 * check
 			 */
-			uint8_t *next_buf      = (ft_cur + 1)->ft_buf;
-			start_addr	     = buf + buf_len - TAG_LENGTH;
-			dest_addr	      = next_buf;
-			*(uint32_t *)dest_addr = *(uint32_t *)start_addr;
+			n_bytes =
+				buf_len - TAG_LENGTH - ft_cur->ft_virtio_offset;
+			memmove(dest_addr, start_addr, n_bytes);
 		}
-
-		start_addr = buf + ft_cur->ft_offset;
-		dest_addr  = start_addr + TAG_LENGTH;
-		/* we already added TAG_LENGTH to ft_end->ft_len, therefore the
-		 * last fragment case is covered without any additional check
-		 */
-		n_bytes = buf_len - TAG_LENGTH - ft_cur->ft_offset;
-		memmove(dest_addr, start_addr, n_bytes);
 	}
 
 	/* now we need to write the tag */
-	be_tpid					     = htobe16(0x8100);
-	be_tci					     = htobe16(vlan_id);
-	buf					     = ft->ft_buf;
-	*(uint16_t *)(buf + ft->ft_offset + TAG_PID) = be_tpid;
-	*(uint16_t *)(buf + ft->ft_offset + TAG_CI)  = be_tci;
+	be_tpid = htobe16(0x8100);
+	be_tci  = htobe16(vlan_id);
+	buf     = (char *)ft->ft_buf + ft->ft_virtio_offset;
+	*(uint16_t *)(buf + TAG_PID) = be_tpid;
+	*(uint16_t *)(buf + TAG_CI)  = be_tci;
 
 	return 0;
 }
@@ -74,28 +104,21 @@
 untag_frame(struct nm_bdg_fwd *ft, struct netmap_vp_adapter *vpna,
 	    uint16_t *vlan_id)
 {
-	struct nm_bdg_fwd *ft_end = ft + ft->ft_frags - 1;
-	struct nm_bdg_fwd *ft_cur = NULL;
-	uint8_t *buf		  = NULL;
 	uint16_t be_tpid;
 	uint16_t be_tci;
-	int n_bytes = 0;
+	char *buf;
 
-	if (ft->ft_offset + TAG_END > ft->ft_len) {
-		/* VLAN header not contained in the first fragment */
+	if (ft->ft_virtio_offset + TAG_END > ft->ft_len) {
+		/* VLAN header not contained in the first fragment. */
 		return EINVAL;
 	}
-	if (ft_end->ft_len < TAG_LENGTH) {
-		/* During the untagging we strip TAG_LENGTH bytes from the
-		 * frame, therefore in this case last fragment would become
-		 * empty and we would need to update fragmentation flags etc.
-		 * At the moment we don't handle this case.
-		 */
+	if (ft->ft_flags & NS_INDIRECT) {
+		/* At the moment indirect buffers are not supported. */
 		return EINVAL;
 	}
 
-	/* first we retrieve the informations we need */
-	buf     = (uint8_t *)ft->ft_buf + ft->ft_offset;
+	/* Retrieve informations from IEEE 802.1Q header */
+	buf     = (char *)ft->ft_buf + ft->ft_virtio_offset;
 	be_tpid = *(uint16_t *)(buf + TAG_PID);
 	if (be_tpid != htobe16(0x8100)) {
 		nm_prinf("Not an IEEE802.Q frame\n");
@@ -104,37 +127,12 @@
 	be_tci   = *(uint16_t *)(buf + TAG_CI);
 	*vlan_id = be16toh(be_tci) & 0x0FFF;
 
-	/* then we remove the tag */
-	for (ft_cur = ft; ft_cur != ft_end + 1; ++ft_cur) {
-		uint8_t *start_addr = NULL;
-		uint8_t *dest_addr  = NULL;
-		uint16_t buf_len    = ft_cur->ft_len;
-		buf		    = ft_cur->ft_buf;
-
-		if (ft_cur->ft_flags & NS_INDIRECT) {
-			/* we do not support indirect userspace buffers */
-			return EINVAL;
-		}
-		if (ft_cur != ft) {
-			/* copy 4 bytes from the start of the current buffer
-			 * to the end of the previous buffer
-			 */
-			struct nm_bdg_fwd *prev_ft = ft_cur - 1;
-			uint8_t *prev_buf	  = prev_ft->ft_buf;
-			uint16_t prev_buf_len      = prev_ft->ft_len;
-
-			start_addr = buf;
-			dest_addr  = prev_buf + prev_buf_len - TAG_LENGTH;
-			*(uint32_t *)dest_addr = *(uint32_t *)start_addr;
-		}
+	/* Remove IEEE 802.1Q header */
+	buf = (char *)ft->ft_buf + TAG_LENGTH;
+	memmove(buf, ft->ft_buf, ft->ft_virtio_offset + TAG_START);
+	ft->ft_buf = buf;
+	ft->ft_len -= TAG_LENGTH;
 
-		dest_addr  = buf + ft->ft_offset;
-		start_addr = dest_addr + TAG_LENGTH;
-		n_bytes    = buf_len - TAG_LENGTH - ft->ft_offset;
-		memmove(dest_addr, start_addr, n_bytes);
-	}
-
-	ft_end->ft_len -= TAG_LENGTH;
 	return 0;
 }
 
@@ -156,6 +154,9 @@
 {
 	int i;
 
+	//	nm_prinf("Initializing lookup data %p, NM_BDG_MAXPORTS = %d\n",
+	//			l_data, NM_BDG_MAXPORTS);
+
 	l_data->trunk_port = NM_BDG_NOPORT;
 	for (i = 0; i < NM_BDG_MAXPORTS; ++i) {
 		l_data->port_to_vlan_id[i] = 0x000;
@@ -191,7 +192,6 @@
 get_vlan_bdg_name(char *bridge_name, size_t len, const char *conf_name,
 		  uint16_t vlan_id)
 {
-
 	snprintf(bridge_name, len, "valeV%d%s:", vlan_id, conf_name);
 }
 
@@ -199,7 +199,6 @@
 get_ap_name(char *port_name, size_t len, const char *conf_name,
 	    uint16_t vlan_id)
 {
-
 	snprintf(port_name, len, "%sAP%d", conf_name, vlan_id);
 }
 
@@ -209,14 +208,12 @@
 static inline void
 get_tagging_bdg_name(char *bridge_name, size_t len, const char *conf_name)
 {
-
 	snprintf(bridge_name, len, "valeV%sTP:", conf_name);
 }
 
 static void
 initialize_conf(struct vale_vlan_conf *conf)
 {
-
 	initialize_lookup_data(&(conf->l_data));
 	conf->conf_name[0] = '\0';
 	bzero(conf->vlan_bdg_auth_tokens, sizeof(conf->vlan_bdg_auth_tokens));
@@ -237,6 +234,9 @@
 	int ret = 0;
 
 	bdg_name = netmap_bdg_name(vpna);
+	//	nm_prinf("vlan_lookup for %s:%s\n", bdg_name, vpna->up.name);
+	//	nm_prinf("lookup data = %p\n", lookup_data);
+	//	nm_prinf("vpna = %p, bdg_port = %u\n", vpna, bdg_port);
 
 	if (unlikely(ft->ft_flags & NS_INDIRECT)) {
 		/* we do not handle userspace indirect buffers */
@@ -244,6 +244,7 @@
 	}
 
 	if (bdg_port == l_data->trunk_port) {
+		//		nm_prinf("%s is a trunk port\n", vpna->up.name);
 		ret = untag_frame(ft, vpna, &vlan_id);
 		if (ret) {
 			return NM_BDG_NOPORT;
@@ -251,6 +252,8 @@
 
 		dest_port = l_data->vlan_id_to_port[vlan_id];
 	} else {
+		//		nm_prinf("%s is an access port\n",
+		// vpna->up.name);
 		vlan_id = l_data->port_to_vlan_id[bdg_port];
 		ret     = tag_frame(ft, vpna, vlan_id);
 		if (ret) {
@@ -271,6 +274,7 @@
 
 	nm_prinf("Trying to modify bdg %s for conf %s\n", bdg_name,
 		 conf->conf_name);
+	//	nm_prinf("lookup data = %p\n", &conf->l_data);
 	return netmap_bdg_regops(bdg_name, &vlan_ops, &conf->l_data,
 				 conf->mod_bdg_auth_token);
 }
@@ -346,7 +350,7 @@
 		nm_prerr("Error %d during bridge %s regops()\n", ret,
 			 tagging_bdg_name);
 		ret2 = netmap_vale_destroy(tagging_bdg_name,
-					  conf->mod_bdg_auth_token);
+					   conf->mod_bdg_auth_token);
 		if (ret2) {
 			/* cannot happen */
 			nm_prerr("Error %d during bridge %s destroy(), "
@@ -506,7 +510,7 @@
 	hdr.nr_name[sizeof(hdr.nr_name) - 1] = '\0';
 
 	bzero(&newif, sizeof(newif));
-	hdr.nr_body = (uintptr_t)&newif;
+	hdr.nr_body = (uint64_t)(uintptr_t)&newif;
 
 	ret = nm_vi_create(&hdr);
 	if (ret == 0) {
@@ -593,7 +597,7 @@
 	bzero(&hdr, sizeof(hdr));
 	hdr.nr_version = NM_API_VERSION;
 	hdr.nr_reqtype = NETMAP_REQ_VALE_ATTACH;
-	hdr.nr_body    = (uintptr_t)&nmr_att;
+	hdr.nr_body    = (uint64_t)(uintptr_t)&nmr_att;
 	snprintf(hdr.nr_name, sizeof(hdr.nr_name), "%s%s", bdg_name, port_name);
 
 	ret = nm_bdg_ctl_attach(&hdr, auth_token);
@@ -618,7 +622,7 @@
 	bzero(&hdr, sizeof(hdr));
 	hdr.nr_version = NM_API_VERSION;
 	hdr.nr_reqtype = NETMAP_REQ_VALE_DETACH;
-	hdr.nr_body    = (uintptr_t)&nmr_det;
+	hdr.nr_body    = (uint64_t)(uintptr_t)&nmr_det;
 	snprintf(hdr.nr_name, sizeof(hdr.nr_name), "%s%s", bdg_name, port_name);
 
 	ret = nm_bdg_ctl_detach(&hdr, auth_token);
@@ -1198,50 +1202,39 @@
 int
 vv_read(struct vale_vlan_dev *dev, uint8_t *buf, size_t *len)
 {
+	struct vale_vlan_conf *conf;
+	struct port_elem *p_elem;
+	size_t ret = 0;
 
 	if (dev->selected_conf == -1) {
 		return EINVAL;
 	}
 
-	if (dev->error_entry != -1) {
-		/* error read() */
-		if (*len != sizeof(dev->error_entry)) {
-			nm_prerr("After receiving an error from a write() call,"
-				 " read() must receive a int32_t pointer\n");
-			return EINVAL;
-		}
-
-		memcpy(buf, &dev->error_entry, sizeof(dev->error_entry));
-		*len		 = sizeof(dev->error_entry);
-		dev->error_entry = -1;
-	} else {
-		/* conf read() */
-		struct vale_vlan_conf *conf;
-		struct port_elem *p_elem;
-		size_t ret = 0;
-
-		if (*len % sizeof(struct port) != 0) {
-			nm_prerr("read() must receive an array of "
-				 "'struct vlan_conf_entry'\n");
-			return EINVAL;
-		}
+	if (*len % sizeof(struct port) != 0) {
+		nm_prerr("read() must receive an array of "
+			 "'struct vlan_conf_entry'\n");
+		return EINVAL;
+	}
 
-		conf = &vlan_confs[dev->selected_conf];
-		vv_list_foreach(p_elem, &conf->port_list, list)
-		{
-			if (*len < ret + sizeof(struct port)) {
-				*len = ret;
-				return 0;
-			}
-			memcpy(buf, &p_elem->port_desc,
-			       sizeof(p_elem->port_desc));
-			ret += sizeof(struct port);
-			buf += sizeof(struct port);
+	conf = &vlan_confs[dev->selected_conf];
+	vv_list_foreach(p_elem, &conf->port_list, list)
+	{
+		if (*len < ret + sizeof(struct port)) {
+			/* At the moment we don't keep track of what
+			 * we have read between multiple read() calls,
+			 * therefore a configuration must be read in
+			 * a single read() call.
+			 */
+			*len = ret;
+			return 0;
 		}
 
-		*len = ret;
+		memcpy(buf, &p_elem->port_desc, sizeof(p_elem->port_desc));
+		ret += sizeof(struct port);
+		buf += sizeof(struct port);
 	}
 
+	*len = ret;
 	return 0;
 }
 
@@ -1297,6 +1290,7 @@
 	default:
 		return EINVAL;
 	}
+
 	return 0;
 }
 


More information about the svn-soc-all mailing list