static lagopus_result_t del_flow_ipv4_dst_mask(struct flowinfo *self, struct flow *flow) { struct flowinfo *flowinfo; uint32_t ipv4_dst, mask; lagopus_result_t rv; unsigned int i; rv = get_match_ipv4_dst(&flow->match_list, &ipv4_dst, &mask); if (rv == LAGOPUS_RESULT_OK) { rv = LAGOPUS_RESULT_NOT_FOUND; for (i = 0; i < self->nnext; i++) { if (self->next[i]->userdata == mask) { flowinfo = self->next[i]; rv = LAGOPUS_RESULT_OK; break; } } if (rv == LAGOPUS_RESULT_NOT_FOUND) { return LAGOPUS_RESULT_NOT_FOUND; } rv = flowinfo->del_func(flowinfo, flow); if (flowinfo->nflow == 0) { flowinfo->destroy_func(flowinfo); self->nnext--; memmove(&self->next[i], &self->next[i + 1], (size_t)(self->nnext - i)); } } else { rv = self->misc->del_func(self->misc, flow); } if (rv == LAGOPUS_RESULT_OK) { self->nflow--; } return rv; }
static struct flow * find_flow_ipv4_dst(struct flowinfo *self, struct flow *flow) { struct flowinfo *flowinfo; uint32_t ipv4_dst, mask; lagopus_result_t rv; rv = get_match_ipv4_dst(&flow->match_list, &ipv4_dst, &mask); if (rv == LAGOPUS_RESULT_OK) { rv = lagopus_hashmap_find_no_lock(&self->hashmap, (void *)ipv4_dst, (void *)&flowinfo); if (rv != LAGOPUS_RESULT_OK) { return NULL; } return flowinfo->find_func(flowinfo, flow); } else { return self->misc->find_func(self->misc, flow); } }
static lagopus_result_t add_flow_ipv4_dst_mask(struct flowinfo *self, struct flow *flow) { struct flowinfo *flowinfo; uint32_t ipv4_dst, mask; lagopus_result_t rv; unsigned int i; rv = get_match_ipv4_dst(&flow->match_list, &ipv4_dst, &mask); if (rv == LAGOPUS_RESULT_OK) { rv = LAGOPUS_RESULT_NOT_FOUND; for (i = 0; i < self->nnext; i++) { if (self->next[i]->userdata == mask) { flowinfo = self->next[i]; rv = LAGOPUS_RESULT_OK; break; } } if (rv == LAGOPUS_RESULT_NOT_FOUND) { /* new node. */ flowinfo = new_flowinfo_ipv4_dst(); flowinfo->userdata = mask; self->next = realloc(self->next, (unsigned long)(self->nnext + 1) * sizeof(struct flowinfo *)); self->next[self->nnext] = flowinfo; self->nnext++; } rv = flowinfo->add_func(flowinfo, flow); } else { rv = self->misc->add_func(self->misc, flow); } if (rv == LAGOPUS_RESULT_OK) { self->nflow++; } return rv; }
static struct flow * match_flow_ipv4_dst_mask(struct flowinfo *self, struct lagopus_packet *pkt, int32_t *pri) { struct flowinfo *flowinfo; struct flow *flow[self->nnext], *matched, *alt_flow; struct flow mismatched = { .priority = 0, .flags = 0, .idle_timeout = 0, .hard_timeout = 0, .match_list = {NULL, NULL}, .instruction_list = {NULL, NULL}, .flow_type = 0, .field_bits = 0 }; unsigned int i; matched = &mismatched; //#pragma omp parallel for for (i = 0; i < self->nnext; i++) { flowinfo = self->next[i]; flow[i] = flowinfo->match_func(flowinfo, pkt, pri); } for (i = 0; i < self->nnext; i++) { if (flow[i] != NULL && flow[i]->priority > matched->priority) { matched = flow[i]; } } alt_flow = self->misc->match_func(self->misc, pkt, pri); if (alt_flow != NULL) { matched = alt_flow; } if (matched == &mismatched) { matched = NULL; } return matched; } static struct flow * find_flow_ipv4_dst_mask(struct flowinfo *self, struct flow *flow) { struct flowinfo *flowinfo; uint32_t ipv4_dst, mask; lagopus_result_t rv; unsigned int i; rv = get_match_ipv4_dst(&flow->match_list, &ipv4_dst, &mask); if (rv == LAGOPUS_RESULT_OK) { rv = LAGOPUS_RESULT_NOT_FOUND; for (i = 0; i < self->nnext; i++) { if (self->next[i]->userdata == mask) { flowinfo = self->next[i]; rv = LAGOPUS_RESULT_OK; break; } } if (rv == LAGOPUS_RESULT_NOT_FOUND) { return NULL; } } else { flowinfo = self->misc; } return flowinfo->find_func(flowinfo, flow); } static lagopus_result_t add_flow_ipv4_dst(struct flowinfo *self, struct flow *flow) { struct flowinfo *flowinfo; struct ptree_node *node; uint32_t ipv4_dst, mask; lagopus_result_t rv; rv = get_match_ipv4_dst(&flow->match_list, &ipv4_dst, &mask); if (rv == LAGOPUS_RESULT_OK) { node = ptree_node_get(self->ptree, (uint8_t *)&ipv4_dst, IPV4_DST_BITLEN); if (node->info == NULL) { /* new node. */ node->info = new_flowinfo_ipv4(); } flowinfo = node->info; rv = flowinfo->add_func(flowinfo, flow); } else { rv = self->misc->add_func(self->misc, flow); } if (rv == LAGOPUS_RESULT_OK) { self->nflow++; } return rv; } static lagopus_result_t del_flow_ipv4_dst(struct flowinfo *self, struct flow *flow) { struct flowinfo *flowinfo; struct ptree_node *node; uint32_t ipv4_dst, mask; lagopus_result_t rv; rv = get_match_ipv4_dst(&flow->match_list, &ipv4_dst, &mask); if (rv == LAGOPUS_RESULT_OK) { node = ptree_node_lookup(self->ptree, (uint8_t *)&ipv4_dst, IPV4_DST_BITLEN); if (node == NULL || node->info == NULL) { return LAGOPUS_RESULT_NOT_FOUND; } flowinfo = node->info; rv = flowinfo->del_func(flowinfo, flow); } else { rv = self->misc->del_func(self->misc, flow); } if (rv == LAGOPUS_RESULT_OK) { self->nflow--; } return rv; } static struct flow * match_flow_ipv4_dst(struct flowinfo *self, struct lagopus_packet *pkt, int32_t *pri) { struct flowinfo *flowinfo; struct ptree_node *node; uint32_t ipv4_dst; struct flow *flow; flow = NULL; ipv4_dst = (pkt->ipv4->ip_dst.s_addr & (uint32_t)self->userdata); node = ptree_node_lookup(self->ptree, (uint8_t *)&ipv4_dst, IPV4_DST_BITLEN); if (node != NULL) { flowinfo = node->info; flow = flowinfo->match_func(flowinfo, pkt, pri); ptree_unlock_node(node); } return flow; } static struct flow * find_flow_ipv4_dst(struct flowinfo *self, struct flow *flow) { struct flowinfo *flowinfo; struct ptree_node *node; uint32_t ipv4_dst, mask; lagopus_result_t rv; rv = get_match_ipv4_dst(&flow->match_list, &ipv4_dst, &mask); if (rv == LAGOPUS_RESULT_OK) { node = ptree_node_get(self->ptree, (uint8_t *)&ipv4_dst, IPV4_DST_BITLEN); if (node->info == NULL) { return NULL; } flowinfo = node->info; return flowinfo->find_func(flowinfo, flow); } else { return self->misc->find_func(self->misc, flow); } }
static struct flow * match_flow_ipv4_dst_mask(struct flowinfo *self, struct lagopus_packet *pkt, int32_t *pri) { struct flowinfo *flowinfo; struct flow *flow[self->nnext], *matched, *alt_flow; struct flow mismatched = { .priority = 0, .flags = 0, .idle_timeout = 0, .hard_timeout = 0, .match_list = {NULL, NULL}, .instruction_list = {NULL, NULL}, .field_bits = 0 }; unsigned int i; matched = &mismatched; //#pragma omp parallel for for (i = 0; i < self->nnext; i++) { flowinfo = self->next[i]; flow[i] = flowinfo->match_func(flowinfo, pkt, pri); } for (i = 0; i < self->nnext; i++) { if (flow[i] != NULL && flow[i]->priority > matched->priority) { matched = flow[i]; } } alt_flow = self->misc->match_func(self->misc, pkt, pri); if (alt_flow != NULL) { matched = alt_flow; } if (matched == &mismatched) { matched = NULL; } return matched; } static struct flow * find_flow_ipv4_dst_mask(struct flowinfo *self, struct flow *flow) { struct flowinfo *flowinfo; uint32_t ipv4_dst, mask; lagopus_result_t rv; unsigned int i; rv = get_match_ipv4_dst(&flow->match_list, &ipv4_dst, &mask); if (rv == LAGOPUS_RESULT_OK) { rv = LAGOPUS_RESULT_NOT_FOUND; for (i = 0; i < self->nnext; i++) { if (self->next[i]->userdata == mask) { flowinfo = self->next[i]; rv = LAGOPUS_RESULT_OK; break; } } if (rv == LAGOPUS_RESULT_NOT_FOUND) { return NULL; } } else { flowinfo = self->misc; } return flowinfo->find_func(flowinfo, flow); } static lagopus_result_t add_flow_ipv4_dst(struct flowinfo *self, struct flow *flow) { struct flowinfo *flowinfo; uint32_t ipv4_dst, mask; lagopus_result_t rv; rv = get_match_ipv4_dst(&flow->match_list, &ipv4_dst, &mask); if (rv == LAGOPUS_RESULT_OK) { rv = lagopus_hashmap_find_no_lock(&self->hashmap, (void *)ipv4_dst, (void *)&flowinfo); if (rv != LAGOPUS_RESULT_OK) { void *val; flowinfo = new_flowinfo_ipv4(); val = flowinfo; lagopus_hashmap_add_no_lock(&self->hashmap, (void *)ipv4_dst, (void *)&val, false); } rv = flowinfo->add_func(flowinfo, flow); if (rv == LAGOPUS_RESULT_OK) { self->nflow++; } } return rv; } static lagopus_result_t del_flow_ipv4_dst(struct flowinfo *self, struct flow *flow) { uint32_t ipv4_dst, mask; lagopus_result_t rv; rv = get_match_ipv4_dst(&flow->match_list, &ipv4_dst, &mask); if (rv == LAGOPUS_RESULT_OK) { struct flowinfo *flowinfo; rv = lagopus_hashmap_find_no_lock(&self->hashmap, (void *)ipv4_dst, (void *)&flowinfo); if (rv == LAGOPUS_RESULT_OK) { flowinfo->del_func(flowinfo, flow); } if (rv == LAGOPUS_RESULT_OK) { self->nflow--; } } return rv; }