#include #include #include "tuple.h" #include "uthash.h" #include "log_internal.h" #include "packet_helper.h" #include "packet_internal.h" #include "stellar/exdata.h" #define PACKET_LOG_ERROR(format, ...) STELLAR_LOG_ERROR(__thread_local_logger, "packet", format, ##__VA_ARGS__) /****************************************************************************** * metadata utils ******************************************************************************/ void packet_set_route_ctx(struct packet *pkt, const struct route_ctx *ctx) { pkt->meta.route_ctx = *ctx; } const struct route_ctx *packet_get_route_ctx(const struct packet *pkt) { return &pkt->meta.route_ctx; } void packet_set_sids(struct packet *pkt, const struct sids *sids) { pkt->meta.sids = *sids; } const struct sids *packet_get_sids(const struct packet *pkt) { return &pkt->meta.sids; } void packet_prepend_sids(struct packet *pkt, const struct sids *sids) { if (pkt->meta.sids.used + sids->used > MAX_SIDS) { PACKET_LOG_ERROR("sids overflow"); return; } else { for (int i = pkt->meta.sids.used - 1; i >= 0; i--) { pkt->meta.sids.sid[i + sids->used] = pkt->meta.sids.sid[i]; } for (int i = 0; i < sids->used; i++) { pkt->meta.sids.sid[i] = sids->sid[i]; } pkt->meta.sids.used += sids->used; } } void packet_set_session_id(struct packet *pkt, uint64_t id) { pkt->meta.session_id = id; } uint64_t packet_get_session_id(const struct packet *pkt) { return pkt->meta.session_id; } void packet_set_domain(struct packet *pkt, uint64_t domain) { pkt->meta.domain = domain; } uint64_t packet_get_domain(const struct packet *pkt) { return pkt->meta.domain; } void packet_set_link_id(struct packet *pkt, uint16_t id) { pkt->meta.link_id = id; } uint16_t packet_get_link_id(const struct packet *pkt) { return pkt->meta.link_id; } void packet_set_direction(struct packet *pkt, enum packet_direction dir) { pkt->meta.direction = dir; } enum packet_direction packet_get_direction(const struct packet *pkt) { return pkt->meta.direction; } void packet_set_timeval(struct packet *pkt, const struct timeval *tv) { pkt->meta.tv = *tv; } const struct timeval *packet_get_timeval(const struct packet *pkt) { return &pkt->meta.tv; } /****************************************************************************** * tuple uitls ******************************************************************************/ // return 0 : found // return -1 : not found int packet_get_innermost_tuple2(const struct packet *pkt, struct tuple2 *tuple) { memset(tuple, 0, sizeof(struct tuple2)); const struct layer_internal *layer = NULL; for (int8_t i = pkt->layers_used - 1; i >= 0; i--) { layer = &pkt->layers[i]; if (layer->proto == LAYER_PROTO_IPV4) { const struct ip *ip4_hdr = (const struct ip *)layer->hdr_ptr; tuple->addr_family = AF_INET; tuple->src_addr.v4 = ip4_hdr_get_src_in_addr(ip4_hdr); tuple->dst_addr.v4 = ip4_hdr_get_dst_in_addr(ip4_hdr); return 0; } if (layer->proto == LAYER_PROTO_IPV6) { const struct ip6_hdr *ip6_hdr = (const struct ip6_hdr *)layer->hdr_ptr; tuple->addr_family = AF_INET6; tuple->src_addr.v6 = ip6_hdr_get_src_in6_addr(ip6_hdr); tuple->dst_addr.v6 = ip6_hdr_get_dst_in6_addr(ip6_hdr); return 0; } } return -1; } // return 0 : found // return -1 : not found int packet_get_outermost_tuple2(const struct packet *pkt, struct tuple2 *tuple) { memset(tuple, 0, sizeof(struct tuple2)); const struct layer_internal *layer = NULL; for (int8_t i = 0; i < pkt->layers_used; i++) { layer = &pkt->layers[i]; if (layer->proto == LAYER_PROTO_IPV4) { const struct ip *ip4_hdr = (const struct ip *)layer->hdr_ptr; tuple->addr_family = AF_INET; tuple->src_addr.v4 = ip4_hdr_get_src_in_addr(ip4_hdr); tuple->dst_addr.v4 = ip4_hdr_get_dst_in_addr(ip4_hdr); return 0; } if (layer->proto == LAYER_PROTO_IPV6) { const struct ip6_hdr *ip6_hdr = (const struct ip6_hdr *)layer->hdr_ptr; tuple->addr_family = AF_INET6; tuple->src_addr.v6 = ip6_hdr_get_src_in6_addr(ip6_hdr); tuple->dst_addr.v6 = ip6_hdr_get_dst_in6_addr(ip6_hdr); return 0; } } return -1; } // return 0 : found // return -1 : not found int packet_get_innermost_tuple4(const struct packet *pkt, struct tuple4 *tuple) { memset(tuple, 0, sizeof(struct tuple4)); const struct layer_internal *layer_l3 = NULL; const struct layer_internal *layer_l4 = NULL; const struct layer_internal *layer = NULL; for (int8_t i = pkt->layers_used - 1; i >= 0; i--) { layer = &pkt->layers[i]; // first get L4 layer if (layer->proto == LAYER_PROTO_UDP) { const struct udphdr *udp_hdr = (const struct udphdr *)layer->hdr_ptr; tuple->src_port = udp_hdr->uh_sport; tuple->dst_port = udp_hdr->uh_dport; layer_l4 = layer; continue; } if (layer->proto == LAYER_PROTO_TCP) { const struct tcphdr *tcp_hdr = (const struct tcphdr *)layer->hdr_ptr; tuple->src_port = tcp_hdr->th_sport; tuple->dst_port = tcp_hdr->th_dport; layer_l4 = layer; continue; } // second get L3 layer if (layer->proto == LAYER_PROTO_IPV4) { const struct ip *ip4_hdr = (const struct ip *)layer->hdr_ptr; tuple->addr_family = AF_INET; tuple->src_addr.v4 = ip4_hdr_get_src_in_addr(ip4_hdr); tuple->dst_addr.v4 = ip4_hdr_get_dst_in_addr(ip4_hdr); layer_l3 = layer; break; } if (layer->proto == LAYER_PROTO_IPV6) { const struct ip6_hdr *ip6_hdr = (const struct ip6_hdr *)layer->hdr_ptr; tuple->addr_family = AF_INET6; tuple->src_addr.v6 = ip6_hdr_get_src_in6_addr(ip6_hdr); tuple->dst_addr.v6 = ip6_hdr_get_dst_in6_addr(ip6_hdr); layer_l3 = layer; break; } } if (layer_l3 && layer_l4 && layer_l4 - layer_l3 == 1) { return 0; } else { return -1; } } // return 0 : found // return -1 : not found int packet_get_outermost_tuple4(const struct packet *pkt, struct tuple4 *tuple) { memset(tuple, 0, sizeof(struct tuple4)); const struct layer_internal *layer_l3 = NULL; const struct layer_internal *layer_l4 = NULL; const struct layer_internal *layer = NULL; for (int8_t i = 0; i < pkt->layers_used; i++) { layer = &pkt->layers[i]; // first get L3 layer if (layer->proto == LAYER_PROTO_IPV4) { const struct ip *ip4_hdr = (const struct ip *)layer->hdr_ptr; tuple->addr_family = AF_INET; tuple->src_addr.v4 = ip4_hdr_get_src_in_addr(ip4_hdr); tuple->dst_addr.v4 = ip4_hdr_get_dst_in_addr(ip4_hdr); layer_l3 = layer; continue; } if (layer->proto == LAYER_PROTO_IPV6) { const struct ip6_hdr *ip6_hdr = (const struct ip6_hdr *)layer->hdr_ptr; tuple->addr_family = AF_INET6; tuple->src_addr.v6 = ip6_hdr_get_src_in6_addr(ip6_hdr); tuple->dst_addr.v6 = ip6_hdr_get_dst_in6_addr(ip6_hdr); layer_l3 = layer; continue; } // second get L4 layer if (layer->proto == LAYER_PROTO_UDP) { const struct udphdr *udp_hdr = (const struct udphdr *)layer->hdr_ptr; tuple->src_port = udp_hdr->uh_sport; tuple->dst_port = udp_hdr->uh_dport; layer_l4 = layer; break; } if (layer->proto == LAYER_PROTO_TCP) { const struct tcphdr *tcp_hdr = (const struct tcphdr *)layer->hdr_ptr; tuple->src_port = tcp_hdr->th_sport; tuple->dst_port = tcp_hdr->th_dport; layer_l4 = layer; break; } } if (layer_l3 && layer_l4 && layer_l4 - layer_l3 == 1) { return 0; } else { return -1; } } // return 0 : found // return -1 : not found int packet_get_innermost_tuple6(const struct packet *pkt, struct tuple6 *tuple) { memset(tuple, 0, sizeof(struct tuple6)); const struct layer_internal *layer_l3 = NULL; const struct layer_internal *layer_l4 = NULL; const struct layer_internal *layer = NULL; for (int8_t i = pkt->layers_used - 1; i >= 0; i--) { layer = &pkt->layers[i]; // first get L4 layer if (layer->proto == LAYER_PROTO_UDP) { const struct udphdr *udp_hdr = (const struct udphdr *)layer->hdr_ptr; tuple->ip_proto = IPPROTO_UDP; tuple->src_port = udp_hdr->uh_sport; tuple->dst_port = udp_hdr->uh_dport; layer_l4 = layer; continue; } if (layer->proto == LAYER_PROTO_TCP) { const struct tcphdr *tcp_hdr = (const struct tcphdr *)layer->hdr_ptr; tuple->ip_proto = IPPROTO_TCP; tuple->src_port = tcp_hdr->th_sport; tuple->dst_port = tcp_hdr->th_dport; layer_l4 = layer; continue; } // second get L3 layer if (layer->proto == LAYER_PROTO_IPV4) { const struct ip *ip4_hdr = (const struct ip *)layer->hdr_ptr; tuple->addr_family = AF_INET; tuple->src_addr.v4 = ip4_hdr_get_src_in_addr(ip4_hdr); tuple->dst_addr.v4 = ip4_hdr_get_dst_in_addr(ip4_hdr); layer_l3 = layer; break; } if (layer->proto == LAYER_PROTO_IPV6) { const struct ip6_hdr *ip6_hdr = (const struct ip6_hdr *)layer->hdr_ptr; tuple->addr_family = AF_INET6; tuple->src_addr.v6 = ip6_hdr_get_src_in6_addr(ip6_hdr); tuple->dst_addr.v6 = ip6_hdr_get_dst_in6_addr(ip6_hdr); layer_l3 = layer; break; } } if (layer_l3 && layer_l4 && layer_l4 - layer_l3 == 1) { tuple->domain = packet_get_domain(pkt); return 0; } else { return -1; } } // return 0 : found // return -1 : not found int packet_get_outermost_tuple6(const struct packet *pkt, struct tuple6 *tuple) { memset(tuple, 0, sizeof(struct tuple6)); const struct layer_internal *layer_l3 = NULL; const struct layer_internal *layer_l4 = NULL; const struct layer_internal *layer = NULL; for (int8_t i = 0; i < pkt->layers_used; i++) { layer = &pkt->layers[i]; // first get L3 layer if (layer->proto == LAYER_PROTO_IPV4) { const struct ip *ip4_hdr = (const struct ip *)layer->hdr_ptr; tuple->addr_family = AF_INET; tuple->src_addr.v4 = ip4_hdr_get_src_in_addr(ip4_hdr); tuple->dst_addr.v4 = ip4_hdr_get_dst_in_addr(ip4_hdr); layer_l3 = layer; continue; } if (layer->proto == LAYER_PROTO_IPV6) { const struct ip6_hdr *ip6_hdr = (const struct ip6_hdr *)layer->hdr_ptr; tuple->addr_family = AF_INET6; tuple->src_addr.v6 = ip6_hdr_get_src_in6_addr(ip6_hdr); tuple->dst_addr.v6 = ip6_hdr_get_dst_in6_addr(ip6_hdr); layer_l3 = layer; continue; } // second get L4 layer if (layer->proto == LAYER_PROTO_UDP) { const struct udphdr *udp_hdr = (const struct udphdr *)layer->hdr_ptr; tuple->ip_proto = IPPROTO_UDP; tuple->src_port = udp_hdr->uh_sport; tuple->dst_port = udp_hdr->uh_dport; layer_l4 = layer; break; } if (layer->proto == LAYER_PROTO_TCP) { const struct tcphdr *tcp_hdr = (const struct tcphdr *)layer->hdr_ptr; tuple->ip_proto = IPPROTO_TCP; tuple->src_port = tcp_hdr->th_sport; tuple->dst_port = tcp_hdr->th_dport; layer_l4 = layer; break; } } if (layer_l3 && layer_l4 && layer_l4 - layer_l3 == 1) { tuple->domain = packet_get_domain(pkt); return 0; } else { return -1; } } /****************************************************************************** * layer uitls ******************************************************************************/ int packet_get_layer_count(const struct packet *pkt) { return pkt->layers_used; } const struct layer *packet_get_layer_by_idx(const struct packet *pkt, int idx) { const struct layer_internal *layer = packet_get_layer(pkt, idx); if (layer == NULL) { return NULL; } else { return (const struct layer *)layer; } } const struct layer_internal *packet_get_layer(const struct packet *pkt, int idx) { if (idx < 0 || idx >= pkt->layers_used) { return NULL; } return &pkt->layers[idx]; } const struct layer_internal *packet_get_innermost_layer(const struct packet *pkt, enum layer_proto proto) { const struct layer_internal *layer = NULL; for (int8_t i = pkt->layers_used - 1; i >= 0; i--) { layer = &pkt->layers[i]; if (layer->proto == proto) { return layer; } } return NULL; } const struct layer_internal *packet_get_outermost_layer(const struct packet *pkt, enum layer_proto proto) { const struct layer_internal *layer = NULL; for (int8_t i = 0; i < pkt->layers_used; i++) { layer = &pkt->layers[i]; if (layer->proto == proto) { return layer; } } return NULL; } /****************************************************************************** * tunnel uitls ******************************************************************************/ struct tunnel_detector { enum tunnel_type type; int contain_layers; int (*identify_func)(const struct layer_internal *curr, const struct layer_internal *next1, const struct layer_internal *next2); }; static int is_ipv4_tunnel(const struct layer_internal *curr, const struct layer_internal *next1, const struct layer_internal *next2 __attribute__((unused))) { if (curr && curr->proto == LAYER_PROTO_IPV4 && next1 && (next1->proto == LAYER_PROTO_IPV4 || next1->proto == LAYER_PROTO_IPV6)) { return 1; } return 0; } static int is_ipv6_tunnel(const struct layer_internal *curr, const struct layer_internal *next1, const struct layer_internal *next2 __attribute__((unused))) { if (curr && curr->proto == LAYER_PROTO_IPV6 && next1 && (next1->proto == LAYER_PROTO_IPV4 || next1->proto == LAYER_PROTO_IPV6)) { return 1; } return 0; } static int is_gre_tunnel(const struct layer_internal *curr, const struct layer_internal *next1, const struct layer_internal *next2 __attribute__((unused))) { if (curr && (curr->proto == LAYER_PROTO_IPV4 || curr->proto == LAYER_PROTO_IPV6) && next1 && next1->proto == LAYER_PROTO_GRE) { return 1; } return 0; } static int is_gtp_tunnel(const struct layer_internal *curr, const struct layer_internal *next1, const struct layer_internal *next2) { if (curr && (curr->proto == LAYER_PROTO_IPV4 || curr->proto == LAYER_PROTO_IPV6) && next1 && next1->proto == LAYER_PROTO_UDP && next2 && next2->proto == LAYER_PROTO_GTP_U) { return 1; } return 0; } static int is_vxlan_tunnel(const struct layer_internal *curr, const struct layer_internal *next1, const struct layer_internal *next2) { if (curr && (curr->proto == LAYER_PROTO_IPV4 || curr->proto == LAYER_PROTO_IPV6) && next1 && next1->proto == LAYER_PROTO_UDP && next2 && next2->proto == LAYER_PROTO_VXLAN) { return 1; } return 0; } static int is_l2tp_tunnel(const struct layer_internal *curr, const struct layer_internal *next1, const struct layer_internal *next2) { if (curr && (curr->proto == LAYER_PROTO_IPV4 || curr->proto == LAYER_PROTO_IPV6) && next1 && next1->proto == LAYER_PROTO_UDP && next2 && next2->proto == LAYER_PROTO_L2TP) { return 1; } return 0; } static int is_teredo_tunnel(const struct layer_internal *curr, const struct layer_internal *next1, const struct layer_internal *next2) { if (curr && curr->proto == LAYER_PROTO_IPV4 && next1 && next1->proto == LAYER_PROTO_UDP && next2 && next2->proto == LAYER_PROTO_IPV6) { return 1; } return 0; } static struct tunnel_detector detectors[] = { {TUNNEL_IPV4, 1, is_ipv4_tunnel}, {TUNNEL_IPV6, 1, is_ipv6_tunnel}, {TUNNEL_GRE, 2, is_gre_tunnel}, {TUNNEL_GTP, 3, is_gtp_tunnel}, {TUNNEL_VXLAN, 3, is_vxlan_tunnel}, {TUNNEL_L2TP, 3, is_l2tp_tunnel}, {TUNNEL_TEREDO, 2, is_teredo_tunnel}, }; // return index of detectors static int detect_tunnel(const struct layer_internal *curr, const struct layer_internal *next1, const struct layer_internal *next2) { for (int i = 0; i < (int)(sizeof(detectors) / sizeof(detectors[0])); i++) { if (detectors[i].identify_func(curr, next1, next2)) { return i; } } return -1; } int packet_get_tunnel_count(const struct packet *pkt) { int count = 0; int used = packet_get_layer_count(pkt); const struct layer_internal *curr = NULL; const struct layer_internal *next1 = NULL; const struct layer_internal *next2 = NULL; for (int i = 0; i < used; i++) { curr = packet_get_layer(pkt, i); next1 = packet_get_layer(pkt, i + 1); next2 = packet_get_layer(pkt, i + 2); if (detect_tunnel(curr, next1, next2) >= 0) { count++; } } return count; } // return 0: success  // return -1: failed int packet_get_tunnel_by_idx(const struct packet *pkt, int idx, struct tunnel *out) { int ret = -1; int count = 0; int used = packet_get_layer_count(pkt); const struct layer_internal *curr = NULL; const struct layer_internal *next1 = NULL; const struct layer_internal *next2 = NULL; memset(out, 0, sizeof(struct tunnel)); for (int i = 0; i < used; i++) { curr = packet_get_layer(pkt, i); next1 = packet_get_layer(pkt, i + 1); next2 = packet_get_layer(pkt, i + 2); ret = detect_tunnel(curr, next1, next2); if (ret >= 0 && count++ == idx) { struct tunnel_detector *hit = &detectors[ret]; out->type = hit->type; out->layer_count = hit->contain_layers; if (out->layer_count >= 1) out->layers[0] = (const struct layer *)curr; if (out->layer_count >= 2) out->layers[1] = (const struct layer *)next1; if (out->layer_count >= 3) out->layers[2] = (const struct layer *)next2; return 0; } } return -1; } /****************************************************************************** * load balance uitls ******************************************************************************/ uint64_t packet_ldbc_hash(const struct packet *pkt, enum packet_load_balance_method method, enum packet_direction direction) { uint64_t temp = 0; uint64_t hash_value = 1; int inner_addr_len = 0; int outer_addr_len = 0; const char *inner_src_addr = NULL; const char *inner_dst_addr = NULL; const char *outer_src_addr = NULL; const char *outer_dst_addr = NULL; struct tuple2 inner_addr; struct tuple2 outer_addr; if (pkt == NULL) { return hash_value; } if (packet_get_innermost_tuple2(pkt, &inner_addr) == -1) { return hash_value; } if (packet_get_outermost_tuple2(pkt, &outer_addr) == -1) { return hash_value; } if (inner_addr.addr_family == AF_INET) { inner_src_addr = (const char *)&inner_addr.src_addr.v4; inner_dst_addr = (const char *)&inner_addr.dst_addr.v4; inner_addr_len = sizeof(struct in_addr); } else { inner_src_addr = (const char *)&inner_addr.src_addr.v6; inner_dst_addr = (const char *)&inner_addr.dst_addr.v6; inner_addr_len = sizeof(struct in6_addr); } if (outer_addr.addr_family == AF_INET) { outer_src_addr = (const char *)&outer_addr.src_addr.v4; outer_dst_addr = (const char *)&outer_addr.dst_addr.v4; outer_addr_len = sizeof(struct in_addr); } else { outer_src_addr = (const char *)&outer_addr.src_addr.v6; outer_dst_addr = (const char *)&outer_addr.dst_addr.v6; outer_addr_len = sizeof(struct in6_addr); } switch (method) { case PKT_LDBC_METH_OUTERMOST_INT_IP: if (direction == PACKET_DIRECTION_INCOMING) { // direction 1: E2I HASH_VALUE(outer_dst_addr, outer_addr_len, hash_value); } else { // direction 0: I2E HASH_VALUE(outer_src_addr, outer_addr_len, hash_value); } break; case PKT_LDBC_METH_OUTERMOST_EXT_IP: if (direction == PACKET_DIRECTION_INCOMING) { // direction 1: E2I HASH_VALUE(outer_src_addr, outer_addr_len, hash_value); } else { // direction 0: I2E HASH_VALUE(outer_dst_addr, outer_addr_len, hash_value); } break; case PKT_LDBC_METH_OUTERMOST_INT_EXT_IP: HASH_VALUE(outer_src_addr, outer_addr_len, hash_value); HASH_VALUE(outer_dst_addr, outer_addr_len, temp); hash_value = hash_value ^ temp; break; case PKT_LDBC_METH_INNERMOST_INT_IP: if (direction == PACKET_DIRECTION_INCOMING) { // direction 1: E2I HASH_VALUE(inner_dst_addr, inner_addr_len, hash_value); } else { // direction 0: I2E HASH_VALUE(inner_src_addr, inner_addr_len, hash_value); } break; case PKT_LDBC_METH_INNERMOST_EXT_IP: if (direction == PACKET_DIRECTION_INCOMING) { // direction 1: E2I HASH_VALUE(inner_src_addr, inner_addr_len, hash_value); } else { // direction 0: I2E HASH_VALUE(inner_dst_addr, inner_addr_len, hash_value); } break; default: return hash_value; } return hash_value; } /****************************************************************************** * other uitls ******************************************************************************/ struct packet *packet_new(uint16_t pkt_len) { struct packet *pkt = (struct packet *)calloc(1, sizeof(struct packet) + pkt_len); if (pkt == NULL) { return NULL; } pkt->data_len = pkt_len; pkt->data_ptr = (const char *)pkt + sizeof(struct packet); pkt->need_free = 1; return pkt; } struct packet *packet_dup(const struct packet *pkt) { if (pkt == NULL) { return NULL; } struct packet *dup_pkt = packet_new(pkt->data_len); if (dup_pkt == NULL) { return NULL; } dup_pkt->layers_used = pkt->layers_used; dup_pkt->layers_size = pkt->layers_size; memcpy((char *)dup_pkt->data_ptr, pkt->data_ptr, pkt->data_len); dup_pkt->data_len = pkt->data_len; packet_set_action(dup_pkt, PACKET_ACTION_DROP); for (int8_t i = 0; i < pkt->layers_used; i++) { dup_pkt->layers[i].proto = pkt->layers[i].proto; dup_pkt->layers[i].hdr_ptr = dup_pkt->data_ptr + pkt->layers[i].hdr_offset; dup_pkt->layers[i].pld_ptr = dup_pkt->data_ptr + pkt->layers[i].hdr_offset + pkt->layers[i].hdr_len; dup_pkt->layers[i].hdr_offset = pkt->layers[i].hdr_offset; dup_pkt->layers[i].hdr_len = pkt->layers[i].hdr_len; dup_pkt->layers[i].pld_len = pkt->layers[i].pld_len; } // update frag_layer if (pkt->frag_layer) { dup_pkt->frag_layer = &dup_pkt->layers[pkt->frag_layer - pkt->layers]; } memcpy(&dup_pkt->meta, &pkt->meta, sizeof(struct metadata)); struct packet_origin origin = { .type = ORIGIN_TYPE_USER, .ctx = NULL, .cb = NULL, .args = NULL, .thr_idx = -1, }; packet_set_origin(dup_pkt, &origin); return dup_pkt; } void packet_free(struct packet *pkt) { if (pkt) { if (packet_is_claim(pkt)) { PACKET_LOG_ERROR("packet has been claimed and cannot be released, please check the module arrangement order"); assert(0); return; } if (pkt->origin.cb) { pkt->origin.cb(pkt, pkt->origin.args); } if (pkt->need_free) { free((void *)pkt); } } } int packet_is_fragment(const struct packet *pkt) { return (pkt->frag_layer) ? 1 : 0; } int packet_is_defraged(const struct packet *pkt) { return pkt->is_defraged; } void packet_set_defraged(struct packet *pkt) { pkt->is_defraged = 1; TAILQ_INIT(&pkt->frag_list); } void packet_push_frag(struct packet *pkt, struct packet *frag) { if (!packet_is_defraged(pkt)) { assert(0); return; } TAILQ_INSERT_TAIL(&pkt->frag_list, frag, frag_tqe); } struct packet *packet_pop_frag(struct packet *pkt) { if (!packet_is_defraged(pkt)) { assert(0); return NULL; } struct packet *frag = TAILQ_FIRST(&pkt->frag_list); if (frag) { TAILQ_REMOVE(&pkt->frag_list, frag, frag_tqe); } return frag; } const char *packet_get_raw_data(const struct packet *pkt) { return pkt->data_ptr; } uint16_t packet_get_raw_len(const struct packet *pkt) { return pkt->data_len; } const char *packet_get_payload_data(const struct packet *pkt) { if (pkt == NULL || pkt->layers_used == 0) { return NULL; } if (pkt->layers[pkt->layers_used - 1].pld_len) { return pkt->layers[pkt->layers_used - 1].pld_ptr; } else { return NULL; } } uint16_t packet_get_payload_len(const struct packet *pkt) { if (pkt == NULL || pkt->layers_used == 0) { return 0; } return pkt->layers[pkt->layers_used - 1].pld_len; } void packet_set_exdata(struct packet *pkt, int idx, void *ex_ptr) { struct exdata_runtime *exdata_rt = (struct exdata_runtime *)pkt->user_data; assert(exdata_rt); exdata_set(exdata_rt, idx, ex_ptr); } void *packet_get_exdata(const struct packet *pkt, int idx) { struct exdata_runtime *exdata_rt = (struct exdata_runtime *)pkt->user_data; assert(exdata_rt); return exdata_get(exdata_rt, idx); } void packet_tag_set(struct packet *pkt, uint64_t key_bits, uint64_t val_bits) { pkt->tag_key_bits |= key_bits; pkt->tag_val_bits |= val_bits; } void packet_tag_get(const struct packet *pkt, uint64_t *key_bits, uint64_t *val_bits) { *key_bits = pkt->tag_key_bits; *val_bits = pkt->tag_val_bits; } void packet_set_user_data(struct packet *pkt, void *data) { pkt->user_data = data; } void *packet_get_user_data(struct packet *pkt) { return pkt->user_data; } void packet_set_origin(struct packet *pkt, struct packet_origin *origin) { pkt->origin = *origin; } struct packet_origin *packet_get_origin(struct packet *pkt) { return &pkt->origin; } void packet_set_claim(struct packet *pkt, bool claim) { pkt->is_claim = claim; } bool packet_is_claim(const struct packet *pkt) { return pkt->is_claim; } enum packet_type packet_get_type(const struct packet *pkt) { return pkt->type; } void packet_set_type(struct packet *pkt, enum packet_type type) { pkt->type = type; } void packet_set_action(struct packet *pkt, enum packet_action action) { pkt->action = action; } enum packet_action packet_get_action(const struct packet *pkt) { return pkt->action; }