[PATCH] PPP prototype
From: Beilei Xing <hidden>
Date: 2017-03-03 07:27:28
Subsystem:
networking drivers, the rest · Maintainers:
Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
From: Qi Zhang <redacted> Signed-off-by: Qi Zhang <redacted> --- app/test-pmd/cmdline.c | 57 ++++++++++++ app/test-pmd/config.c | 114 +++++++++++++++++++++++ app/test-pmd/testpmd.h | 3 + drivers/net/i40e/base/i40e_adminq_cmd.h | 33 +++++++ drivers/net/i40e/base/i40e_common.c | 160 +++++++++++++++++++++++++++++++- drivers/net/i40e/base/i40e_prototype.h | 12 +++ drivers/net/i40e/base/i40e_type.h | 69 ++++++++++++++ drivers/net/i40e/i40e_ethdev.c | 55 +++++++++++ drivers/net/i40e/rte_pmd_i40e.h | 1 + 9 files changed, 503 insertions(+), 1 deletion(-)
diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 43fc636..0d62a07 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c@@ -12395,6 +12395,62 @@ cmdline_parse_inst_t cmd_set_vf_vlan_tag = { }, }; +/* Write Pipeline Personalization Profile */ +struct cmd_write_ppp_result { + cmdline_fixed_string_t write; + cmdline_fixed_string_t ppp; + uint8_t port_id; + char filename[]; +}; + +cmdline_parse_token_string_t cmd_write_ppp_write = + TOKEN_STRING_INITIALIZER(struct cmd_write_ppp_result, write, "write"); +cmdline_parse_token_string_t cmd_write_ppp_ppp = + TOKEN_STRING_INITIALIZER(struct cmd_write_ppp_result, ppp, "ppp"); +cmdline_parse_token_num_t cmd_write_ppp_port_id = + TOKEN_NUM_INITIALIZER(struct cmd_write_ppp_result, port_id, UINT8); +cmdline_parse_token_string_t cmd_write_ppp_filename = + TOKEN_STRING_INITIALIZER(struct cmd_write_ppp_result, filename, NULL); + +static void +cmd_write_ppp_parsed( + void *parsed_result, + __attribute__((unused)) struct cmdline *cl, + __attribute__((unused)) void *data) +{ + struct cmd_write_ppp_result *res = parsed_result; + uint8_t *buff; + int ret = -ENOTSUP; + + if (res->port_id > nb_ports) { + printf("Invalid port, range is [0, %d]\n", nb_ports - 1); + return; + } + + buff = open_package_file(res->filename); + if (!buff) + return; + + ret = i40e_process_package(res->port_id, buff); + if (ret < 0) + printf("Failed to write profile.\n"); + + close_package_file(buff); +} + +cmdline_parse_inst_t cmd_write_ppp = { + .f = cmd_write_ppp_parsed, + .data = NULL, + .help_str = "write ppp <port_id> <profile_name>", + .tokens = { + (void *)&cmd_write_ppp_write, + (void *)&cmd_write_ppp_ppp, + (void *)&cmd_write_ppp_port_id, + (void *)&cmd_write_ppp_filename, + NULL, + }, +}; + /* ******************************************************************************** */ /* list of instructions */
@@ -12570,6 +12626,7 @@ cmdline_parse_ctx_t main_ctx[] = { (cmdline_parse_inst_t *)&cmd_set_vf_allmulti, (cmdline_parse_inst_t *)&cmd_set_vf_broadcast, (cmdline_parse_inst_t *)&cmd_set_vf_vlan_tag, + (cmdline_parse_inst_t *)&cmd_write_ppp, NULL, };
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index 80491fc..6dbb683 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c@@ -100,6 +100,11 @@ #include "testpmd.h" +#include <sys/stat.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> + static char *flowtype_to_str(uint16_t flow_type); static const struct {
@@ -3245,3 +3250,112 @@ port_dcb_info_display(uint8_t port_id) printf("\t%4d", dcb_info.tc_queue.tc_txq[0][i].nb_queue); printf("\n"); } + +uint8_t * +open_package_file(const char *file_path) +{ + FILE *fh = fopen(file_path, "rb"); + uint32_t pkg_size; + uint8_t *buf = NULL; + int ret = 0; + + if (fh == NULL) { + printf("%s: Failed to open %s\n", __func__, file_path); + return buf; + } + + ret = fseek(fh, 0, SEEK_END); + if (ret < 0) { + fclose(fh); + printf("%s: File operations failed\n", __func__); + return buf; + } + + pkg_size = ftell(fh); + + buf = (uint8_t *)malloc(pkg_size); + if (!buf) { + fclose(fh); + printf("%s: Failed to malloc memory\n", __func__); + return buf; + } + + ret = fseek(fh, 0, SEEK_SET); + if (ret < 0) { + fclose(fh); + printf("%s: File operations failed\n", __func__); + close_package_file(buf); + return NULL; + } + fread(buf, 1, pkg_size, fh); + + for(uint32_t i = 0; i < pkg_size; i++) { + if (!(i % 16)) + printf(" "); + printf(" 0x%02X,", buf[i]); + if (!((i + 1) % 16)) + printf("\n"); + } + + fclose(fh); + + return buf; +} + +/* uint8_t * */ +/* open_package_file(const char *file_path) */ +/* { */ +/* int fd = STDOUT_FILENO; */ +/* struct stat stf; */ +/* uint8_t *buf = NULL; */ + +/* if (stat(file_path, &stf) == -1) { */ +/* dprintf(fd, "unable to access '%s'\n", file_path); */ +/* return NULL; */ +/* } */ + +/* if ((stf.st_mode & S_IFMT) != S_IFREG) { */ +/* dprintf(fd, "'%s' is not a file\n", file_path); */ +/* return NULL; */ +/* } */ + +/* buf = (uint8_t *)malloc(stf.st_size); */ +/* if (!buf) { */ +/* dprintf(fd, "not enough memory to load %u bytes\n", (uint32_t)stf.st_size); */ +/* return NULL; */ +/* } */ + +/* int file = open(file_path, O_RDONLY, S_IRUSR); */ +/* if (file < 0) { */ +/* dprintf(fd, "unable to open '%s'\n", file_path); */ +/* return NULL; */ +/* } */ + +/* if (read(file, buf, stf.st_size) != stf.st_size) { */ +/* free((void *)buf); */ +/* dprintf(fd, "unable to read '%s'\n", file_path); */ +/* return NULL; */ +/* } */ +/* close(file); */ + +/* for(uint32_t i = 0; i < stf.st_size; i++) { */ +/* if (!(i % 16)) */ +/* printf(" "); */ +/* printf(" 0x%02X,", buf[i]); */ +/* if (!((i + 1) % 16)) */ +/* printf("\n"); */ +/* } */ + +/* return buf; */ +/* } */ + +int +close_package_file(uint8_t *buf) +{ + if (buf) { + free((void *)buf); + return 0; + } + + return -1; +}
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index 8cf2860..2a7f683 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h@@ -622,6 +622,9 @@ void mcast_addr_add(uint8_t port_id, struct ether_addr *mc_addr); void mcast_addr_remove(uint8_t port_id, struct ether_addr *mc_addr); void port_dcb_info_display(uint8_t port_id); +uint8_t *open_package_file(const char *file_path); +int close_package_file(uint8_t *buf); + enum print_warning { ENABLED_WARN = 0, DISABLED_WARN
diff --git a/drivers/net/i40e/base/i40e_adminq_cmd.h b/drivers/net/i40e/base/i40e_adminq_cmd.h
index 67cef7c..593394a 100644
--- a/drivers/net/i40e/base/i40e_adminq_cmd.h
+++ b/drivers/net/i40e/base/i40e_adminq_cmd.h@@ -198,6 +198,10 @@ enum i40e_admin_queue_opc { i40e_aqc_opc_add_mirror_rule = 0x0260, i40e_aqc_opc_delete_mirror_rule = 0x0261, + /* Support Pipeline Personalization Profile */ + i40e_aqc_opc_write_personalization_profile = 0x0270, + i40e_aqc_opc_read_personalization_profile_list = 0x0271, + /* DCB commands */ i40e_aqc_opc_dcb_ignore_pfc = 0x0301, i40e_aqc_opc_dcb_updated = 0x0302,
@@ -1441,6 +1445,35 @@ struct i40e_aqc_add_delete_mirror_rule_completion { I40E_CHECK_CMD_LENGTH(i40e_aqc_add_delete_mirror_rule_completion); +/* Pipeline Personalization Profile */ +struct i40e_aqc_write_ppp { + u8 flags; +#define I40E_AQ_WR_PPP_ADD_TRACK_ID 0x01 +#define I40E_AQ_WR_PPP_REMOVE_TRACK_ID 0x02 + u8 reserved[3]; + __le32 profile_track_id; + __le32 addr_high; + __le32 addr_low; +}; + +I40E_CHECK_CMD_LENGTH(i40e_aqc_write_ppp); + +struct i40e_aqc_write_ppp_resp { + __le32 error_offset; + __le32 error_info; + __le32 addr_high; + __le32 addr_low; +}; + +struct i40e_aqc_read_ppp { + u8 flags; + u8 reserved[7]; + __le32 addr_high; + __le32 addr_low; +}; + +I40E_CHECK_CMD_LENGTH(i40e_aqc_read_ppp); + /* DCB 0x03xx*/ /* PFC Ignore (direct 0x0301)
diff --git a/drivers/net/i40e/base/i40e_common.c b/drivers/net/i40e/base/i40e_common.c
index b8d8165..4fb419c 100644
--- a/drivers/net/i40e/base/i40e_common.c
+++ b/drivers/net/i40e/base/i40e_common.c@@ -6997,4 +6997,162 @@ enum i40e_status_code i40e_aq_clear_all_wol_filters(struct i40e_hw *hw, status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); return status; -}
\ No newline at end of file
+}
+
+/**
+ * i40e_aq_write_ppp - Write pipeline personalization profile (ppp)
+ * @hw: pointer to the hw struct
+ * @buff: command buffer (size in bytes = buff_size)
+ * @buff_size: buffer size in bytes
+ * @track_id: package tracking id
+ * @cmd_details: pointer to command details structure or NULL
+ **/
+enum
+i40e_status_code i40e_aq_write_ppp(struct i40e_hw *hw, void *buff,
+ u16 buff_size, u32 track_id,
+ struct i40e_asq_cmd_details *cmd_details)
+{
+ struct i40e_aq_desc desc;
+ struct i40e_aqc_write_ppp *cmd =
+ (struct i40e_aqc_write_ppp *)&desc.params.raw;
+ struct i40e_aqc_write_ppp_resp *resp;
+ enum i40e_status_code status;
+
+ i40e_fill_default_direct_cmd_desc(&desc,
+ i40e_aqc_opc_write_personalization_profile);
+
+ desc.flags |= CPU_TO_LE16(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD);
+ if (buff_size > I40E_AQ_LARGE_BUF)
+ desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_LB);
+
+ desc.datalen = CPU_TO_LE16(buff_size);
+
+ cmd->profile_track_id = CPU_TO_LE32(track_id);
+
+ status = i40e_asq_send_command(hw, &desc, buff, buff_size, cmd_details);
+
+ return status;
+}
+
+/**
+ * i40e_aq_read_ppp - Read pipeline personalization profile (ppp)
+ * @hw: pointer to the hw struct
+ * @buff: command buffer (size in bytes = buff_size)
+ * @buff_size: buffer size in bytes
+ * @cmd_details: pointer to command details structure or NULL
+ **/
+enum
+i40e_status_code i40e_aq_read_ppp(struct i40e_hw *hw,
+ void *buff, u16 buff_size,
+ struct i40e_asq_cmd_details *cmd_details)
+{
+ struct i40e_aq_desc desc;
+ struct i40e_aqc_read_ppp *cmd =
+ (struct i40e_aqc_read_ppp *)&desc.params.raw;
+ enum i40e_status_code status;
+
+ i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_read_personalization_profile_list);
+
+ if (buff_size > I40E_AQ_LARGE_BUF)
+ desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_LB);
+ desc.datalen = CPU_TO_LE16(buff_size);
+
+ status = i40e_asq_send_command(hw, &desc, buff, buff_size, cmd_details);
+
+ return status;
+}
+
+/**
+ * i40e_find_segment_in_package
+ * @segment_type: the segment type to search for (i.e., SEGMENT_TYPE_I40E)
+ * @pkg_hdr: pointer to the package header to be searched
+ *
+ * This function searches a package file for a particular segment type. On
+ * success it returns a pointer to the segment header, otherwise it will
+ * return NULL.
+ */
+struct i40e_generic_seg_header *
+i40e_find_segment_in_package(u32 segment_type,
+ struct i40e_package_header *pkg_hdr)
+{
+ struct i40e_generic_seg_header *segment;
+ u32 i;
+
+ PMD_DRV_LOG(INFO, "i40e_find_segment_in_package");
+ PMD_DRV_LOG(INFO, "Package version: %d.%d.%d.%d",
+ pkg_hdr->version.major,
+ pkg_hdr->version.minor,
+ pkg_hdr->version.update,
+ pkg_hdr->version.draft);
+
+ /* Search all package segments for the requested segment type */
+ for (i = 0; i < pkg_hdr->segment_count; i++) {
+ segment =
+ (struct i40e_generic_seg_header *)((u8 *)pkg_hdr +
+ pkg_hdr->segment_offset[i]);
+
+ if (segment->type == segment_type)
+ return segment;
+ }
+
+ return NULL;
+}
+
+/**
+ * i40e_write_profile
+ * @hw: pointer to the hardware structure
+ * @profile: pointer to the profile segment of the package to be downloaded
+ * @track_id: package tracking id
+ *
+ * Handles the download of a complete package.
+ */
+enum i40e_status_code
+i40e_write_profile(struct i40e_hw *hw, struct i40e_profile_segment *profile,
+ u32 track_id)
+{
+ enum i40e_status_code status = I40E_SUCCESS;
+ struct i40e_section_table *sec_tbl;
+ struct i40e_profile_section_header *sec = NULL;
+ u32 dev_cnt;
+ u32 *nvm;
+ u32 section_size = 0;
+ u32 i;
+
+ PMD_DRV_LOG(INFO, "i40e_write_profile");
+ PMD_DRV_LOG(INFO, "Segment version: %d.%d.%d.%d",
+ profile->header.version.major,
+ profile->header.version.minor,
+ profile->header.version.update,
+ profile->header.version.draft);
+ PMD_DRV_LOG(INFO, "Seg: type 0x%X, size %d, name %s",
+ LE32_TO_CPU(profile->header.type),
+ LE32_TO_CPU(profile->header.size),
+ profile->header.name);
+
+ dev_cnt = profile->device_table_count;
+ nvm = (u32 *)&profile->device_table[dev_cnt];
+ sec_tbl = (struct i40e_section_table *)&nvm[nvm[0] + 1];
+
+ for (i = 0; i < sec_tbl->section_count; i++) {
+ sec = (struct i40e_profile_section_header *)((char *)profile +
+ sec_tbl->section_offset[i]);
+
+ /* Skip 'AQ', 'note' and 'name' sections */
+ if (sec->section.type != SECTION_TYPE_MMIO)
+ continue;
+
+ section_size = sec->section.size +
+ sizeof(struct i40e_profile_section_header);
+ break;
+ }
+
+ /* Write profile */
+ status = i40e_aq_write_ppp(hw, (void *)sec, section_size,
+ track_id, NULL);
+ if (status) {
+ PMD_DRV_LOG(ERR, "Failed to write profile!");
+ return status;
+ }
+
+ return status;
+}diff --git a/drivers/net/i40e/base/i40e_prototype.h b/drivers/net/i40e/base/i40e_prototype.h
index 109d3c5..4f7b63f 100644
--- a/drivers/net/i40e/base/i40e_prototype.h
+++ b/drivers/net/i40e/base/i40e_prototype.h@@ -555,4 +555,16 @@ enum i40e_status_code i40e_write_phy_register(struct i40e_hw *hw, u8 i40e_get_phy_address(struct i40e_hw *hw, u8 dev_num); enum i40e_status_code i40e_blink_phy_link_led(struct i40e_hw *hw, u32 time, u32 interval); +enum i40e_status_code i40e_aq_write_ppp(struct i40e_hw *hw, void *buff, + u16 buff_size, u32 track_id, + struct i40e_asq_cmd_details *cmd_details); +enum i40e_status_code i40e_aq_read_ppp(struct i40e_hw *hw, + void *buff, u16 buff_size, + struct i40e_asq_cmd_details *cmd_details); +struct i40e_generic_seg_header * +i40e_find_segment_in_package(u32 segment_type, + struct i40e_package_header *pkg_header); +enum i40e_status_code +i40e_write_profile(struct i40e_hw *hw, struct i40e_profile_segment *i40e_seg, + u32 track_id); #endif /* _I40E_PROTOTYPE_H_ */
diff --git a/drivers/net/i40e/base/i40e_type.h b/drivers/net/i40e/base/i40e_type.h
index 590d97c..dafb8d9 100644
--- a/drivers/net/i40e/base/i40e_type.h
+++ b/drivers/net/i40e/base/i40e_type.h@@ -1878,4 +1878,73 @@ struct i40e_lldp_variables { #define I40E_FLEX_56_MASK (0x1ULL << I40E_FLEX_56_SHIFT) #define I40E_FLEX_57_SHIFT 6 #define I40E_FLEX_57_MASK (0x1ULL << I40E_FLEX_57_SHIFT) + +/* Version format for PPP */ +struct i40e_ppp_version { + u8 major; + u8 minor; + u8 update; + u8 draft; +}; + +#define I40E_PPP_NAME_SIZE 32 + +/* Package header */ +struct i40e_package_header { + struct i40e_ppp_version version; + u32 segment_count; + u32 segment_offset[1]; +}; + +/* Generic segment header */ +struct i40e_generic_seg_header { + #define SEGMENT_TYPE_METADATA 0x00000001 + #define SEGMENT_TYPE_NOTES 0x00000002 + #define SEGMENT_TYPE_I40E 0x00000011 + #define SEGMENT_TYPE_X722 0x00000012 + u32 type; + struct i40e_ppp_version version; + u32 size; + char name[I40E_PPP_NAME_SIZE]; +}; + +struct i40e_metadata_segment { + struct i40e_generic_seg_header header; + struct i40e_ppp_version version; + uint32_t track_id; + char name[I40E_PPP_NAME_SIZE]; +}; + +struct i40e_device_id_entry { + u32 device_id; + u32 sub_device_id; +}; + +struct i40e_profile_segment { + struct i40e_generic_seg_header header; + struct i40e_ppp_version version; + char name[I40E_PPP_NAME_SIZE]; + u32 device_table_count; + struct i40e_device_id_entry device_table[1]; +}; + +struct i40e_section_table { + u32 section_count; + u32 section_offset[1]; +}; + +struct i40e_profile_section_header { + u16 tbl_size; + u16 data_end; + struct { + #define SECTION_TYPE_INFO 0x0000010 + #define SECTION_TYPE_MMIO 0x0000800 + #define SECTION_TYPE_AQ 0x0000801 + #define SECTION_TYPE_NOTE 0x8000000 + #define SECTION_TYPE_NAME 0x8000001 + u32 type; + u32 offset; + u32 size; + } section; +}; #endif /* _I40E_TYPE_H_ */
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 303027b..a467711 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c@@ -39,6 +39,10 @@ #include <stdarg.h> #include <inttypes.h> #include <assert.h> +#include <sys/stat.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> #include <rte_string_fns.h> #include <rte_pci.h>
@@ -11212,3 +11216,54 @@ rte_pmd_i40e_reset_vf_stats(uint8_t port, return 0; } + +/** + * i40e_process_package - Load package + * @port: port id + * @filename: file name of the package + **/ +int +i40e_process_package(uint8_t port, uint8_t *buff) +{ + struct rte_eth_dev *dev = &rte_eth_devices[port]; + struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); + struct i40e_package_header *pkg_hdr; + struct i40e_generic_seg_header *profile_seg_hdr; + struct i40e_generic_seg_header *metadata_seg_hdr; + uint32_t track_id; + enum i40e_status_code status; + + pkg_hdr = (struct i40e_package_header *)buff; + + if (!pkg_hdr) { + PMD_DRV_LOG(ERR, "Failed to fill the package structure"); + return -EINVAL; + } + + /* Find metadata segment */ + metadata_seg_hdr = i40e_find_segment_in_package(SEGMENT_TYPE_METADATA, + pkg_hdr); + if (!metadata_seg_hdr) { + PMD_DRV_LOG(ERR, "Failed to find metadata segment header"); + return -EINVAL; + } + track_id = ((struct i40e_metadata_segment *)metadata_seg_hdr)->track_id; + + /* Find profile segment */ + profile_seg_hdr = i40e_find_segment_in_package(SEGMENT_TYPE_I40E, + pkg_hdr); + if (!profile_seg_hdr) { + PMD_DRV_LOG(ERR, "Failed to find profile segment header"); + return -EINVAL; + } + + /* Write profile to HW */ + status = i40e_write_profile(hw, + (struct i40e_profile_segment *)profile_seg_hdr, + track_id); + + if (!status) + printf("Write profile successfully.\n"); + + return status; +}
diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
index a0ad88c..755a279 100644
--- a/drivers/net/i40e/rte_pmd_i40e.h
+++ b/drivers/net/i40e/rte_pmd_i40e.h@@ -332,4 +332,5 @@ int rte_pmd_i40e_get_vf_stats(uint8_t port, int rte_pmd_i40e_reset_vf_stats(uint8_t port, uint16_t vf_id); +int i40e_process_package(uint8_t port, uint8_t *buff); #endif /* _PMD_I40E_H_ */
--
2.7.4