#pragma once #include #include #include #include #include #include struct mrb_metadata_route_ctx { uint8_t dir; uint8_t adapter_type; uint16_t traffic_link_id; uint16_t port_ingress; uint16_t port_egress; uint32_t hash_usr; union { struct { uint16_t ef_peer_index; uint16_t ef_link_id; }; struct { uint16_t vlan_tci; struct rte_ether_hdr eth_hdr; }; }; }; int buffer_metadata_get(marsio_buff_t * m, enum mr_buff_metadata_type type, void * data, unsigned int sz_data) { struct rte_mbuf * mbuf = (struct rte_mbuf *)m; struct mrb_metadata * mrb_metadata = (struct mrb_metadata *)mrbuf_cz_data(mbuf, MR_NODE_CTRLZONE_ID); switch (type) { case MR_BUFF_REHASH_INDEX: if (unlikely(sz_data < sizeof(uint32_t))) { return -ENOMEM; } *(uint32_t *)(data) = (uint32_t)mbuf->hash.usr; return sizeof(uint32_t); case MR_BUFF_ROUTE_CTX: { if (unlikely(sz_data < sizeof(struct mrb_metadata_route_ctx))) { return -ENOMEM; } struct mrb_metadata_route_ctx * route_ctx = (struct mrb_metadata_route_ctx *)data; if (route_ctx == NULL) { return -EINVAL; } route_ctx->dir = mrb_metadata->dir; route_ctx->adapter_type = mrb_metadata->adapter_type; route_ctx->port_ingress = mrb_metadata->port_ingress; route_ctx->port_egress = mrb_metadata->port_egress; route_ctx->traffic_link_id = mrb_metadata->traffic_link_id; route_ctx->hash_usr = mbuf->hash.usr; if (mrb_metadata->adapter_type == ADAPTER_TYPE_EF) { route_ctx->ef_peer_index = mrb_metadata->ef_peer_index; route_ctx->ef_link_id = mrb_metadata->ef_link_id; } else if (mrb_metadata->adapter_type == ADAPTER_TYPE_TERA) { const struct rte_ether_hdr * eth_hdr = rte_pktmbuf_mtod(mbuf, const struct rte_ether_hdr *); const struct rte_vlan_hdr * vlan_hdr = rte_pktmbuf_mtod_offset(mbuf, const struct rte_vlan_hdr *, sizeof(struct rte_ether_hdr)); route_ctx->vlan_tci = vlan_hdr->vlan_tci; rte_memcpy(&route_ctx->eth_hdr, eth_hdr, sizeof(struct rte_ether_hdr)); } return sizeof(struct mrb_metadata_route_ctx); } case MR_BUFF_DIR: { if (unlikely(sz_data < sizeof(unsigned int))) { return -ENOMEM; } *(unsigned int *)(data) = (unsigned int)mrb_metadata->dir; return sizeof(unsigned int); } case MR_BUFF_SESSION_ID: { if (unlikely(sz_data < sizeof(uint64_t))) { return -ENOMEM; } *(uint64_t *)(data) = (uint64_t)mrb_metadata->session_id; return sizeof(uint64_t); } case MR_BUFF_PAYLOAD_OFFSET: { if (unlikely(sz_data < sizeof(uint16_t))) { return -ENOMEM; } *(uint16_t *)(data) = (uint16_t)mrb_metadata->payload_offset; return sizeof(uint16_t); } case MR_BUFF_LINK_ID: { if (unlikely(sz_data < sizeof(uint16_t))) { return -ENOMEM; } *(uint16_t *)(data) = (uint16_t)mrb_metadata->traffic_link_id; return sizeof(uint16_t); } case MR_BUFF_USER_0: { if (unlikely(sz_data < sizeof(uint16_t))) { return -ENOMEM; } *(uint16_t *)(data) = (uint16_t)mrb_metadata->user_0; return sizeof(uint16_t); } default: return -ENOTSUP; } return 0; } int buffer_metadata_set(marsio_buff_t * m, enum mr_buff_metadata_type type, void * data, unsigned int sz_data) { struct rte_mbuf * mbuf = (struct rte_mbuf *)m; struct mrb_metadata * mrb_metadata = (struct mrb_metadata *)mrbuf_cz_data(mbuf, MR_NODE_CTRLZONE_ID); switch (type) { case MR_BUFF_REHASH_INDEX: if (unlikely(sz_data < sizeof(uint32_t))) { return -ENOMEM; } mbuf->hash.usr = *(uint32_t *)data; return 0; case MR_BUFF_METADATA_VLAN_TCI: { if (unlikely(sz_data < sizeof(uint16_t))) { return -ENOMEM; } /* we do not want to relay on the hardware offload capability */ struct rte_ether_hdr * ether_hdr = (struct rte_ether_hdr *)rte_pktmbuf_mtod(mbuf, struct rte_ether_hdr *); /* already has a vlan header */ if (ether_hdr->ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN)) { struct rte_vlan_hdr * vlan_hdr = (struct rte_vlan_hdr *)(ether_hdr + 1); vlan_hdr->vlan_tci = rte_cpu_to_be_16(*(uint16_t *)data); } else { mbuf->vlan_tci = *(uint16_t *)data; rte_vlan_insert(&mbuf); } return 0; } case MR_BUFF_ROUTE_CTX: { if (unlikely(sz_data < sizeof(struct mrb_metadata_route_ctx))) { return -ENOMEM; } struct mrb_metadata_route_ctx * route_ctx = (struct mrb_metadata_route_ctx *)data; assert(route_ctx != NULL); mrb_metadata->packet_create_from_nf = 1; mrb_metadata->dir = route_ctx->dir; mrb_metadata->adapter_type = route_ctx->adapter_type; mrb_metadata->traffic_link_id = route_ctx->traffic_link_id; mrb_metadata->port_ingress = route_ctx->port_ingress; mrb_metadata->port_egress = route_ctx->port_egress; mbuf->hash.usr = route_ctx->hash_usr; if (route_ctx->adapter_type == ADAPTER_TYPE_EF) { mrb_metadata->ef_peer_index = route_ctx->ef_peer_index; mrb_metadata->ef_link_id = route_ctx->ef_link_id; } else if (route_ctx->adapter_type == ADAPTER_TYPE_TERA) { /* Get original eth hdr */ struct rte_ether_hdr * ether_hdr = rte_pktmbuf_mtod(mbuf, struct rte_ether_hdr *); /* Already has a vlan header */ if (ether_hdr->ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN)) { struct rte_vlan_hdr * vlan_hdr = (struct rte_vlan_hdr *)(ether_hdr + 1); vlan_hdr->vlan_tci = route_ctx->vlan_tci; } else { mbuf->vlan_tci = route_ctx->vlan_tci; rte_vlan_insert(&mbuf); ether_hdr = rte_pktmbuf_mtod(mbuf, struct rte_ether_hdr *); } /* Update the mac addr */ rte_memcpy(ðer_hdr->src_addr, &route_ctx->eth_hdr.src_addr, sizeof(struct rte_ether_addr)); rte_memcpy(ðer_hdr->dst_addr, &route_ctx->eth_hdr.dst_addr, sizeof(struct rte_ether_addr)); } return 0; } case MR_BUFF_SESSION_ID: { mrb_metadata->session_id = *(uint64_t *)data; return 0; } case MR_BUFF_DIR: { mrb_metadata->dir = *(unsigned int *)data; return 0; } case MR_BUFF_PAYLOAD_OFFSET: { mrb_metadata->payload_offset = *(uint16_t *)data; return 0; } case MR_BUFF_USER_0: { mrb_metadata->user_0 = *(uint16_t *)data; return 0; } case MR_BUFF_LINK_ID: { mrb_metadata->traffic_link_id = *(uint16_t *)data; return 0; } default: return -ENOTSUP; } return 0; }