Date: Thu, 2 Aug 2018 10:26:01 GMT From: sduo@FreeBSD.org To: svn-soc-all@FreeBSD.org Subject: socsvn commit: r337279 - soc2018/sduo/head/sys/dev/vale_vlan Message-ID: <201808021026.w72AQ1P5065382@socsvn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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; }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201808021026.w72AQ1P5065382>