static struct flow * match_flow_in_port(struct flowinfo *self, struct lagopus_packet *pkt, int32_t *pri) { struct flowinfo *flowinfo; struct ptree_node *node; struct flow *flow, *alt_flow; flow = NULL; node = ptree_node_lookup(self->ptree, (uint8_t *)&pkt->in_port->ofp_port.port_no, 32); if (node != NULL) { flowinfo = node->info; flow = flowinfo->match_func(flowinfo, pkt, pri); ptree_unlock_node(node); } alt_flow = self->misc->match_func(self->misc, pkt, pri); if (alt_flow != NULL) { flow = alt_flow; } return 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}, .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); } }