static void vr_flow_flush(void *arg) { struct vrouter *router; struct vr_flow_entry *fe; struct vr_forwarding_md fmd; struct vr_flow_md *flmd = (struct vr_flow_md *)arg; router = flmd->flmd_router; if (!router) return; fe = vr_get_flow_entry(router, flmd->flmd_index); if (!fe) return; vr_init_forwarding_md(&fmd); vr_flow_set_forwarding_md(router, fe, flmd->flmd_index, &fmd); vr_flush_entry(router, fe, flmd, &fmd); if (!(flmd->flmd_flags & VR_FLOW_FLAG_ACTIVE)) { vr_reset_flow_entry(router, fe, flmd->flmd_index); } return; }
static void vr_flow_table_reset(struct vrouter *router) { unsigned int start, end, i; struct vr_flow_entry *fe; struct vr_forwarding_md fmd; struct vr_flow_md flmd; start = end = 0; if (router->vr_flow_table) end = vr_btable_entries(router->vr_flow_table); if (router->vr_oflow_table) { if (!end) start = vr_flow_entries; end += vr_btable_entries(router->vr_oflow_table); } if (end) { vr_init_forwarding_md(&fmd); flmd.flmd_action = VR_FLOW_ACTION_DROP; for (i = start; i < end; i++) { fe = vr_get_flow_entry(router, i); if (fe) { flmd.flmd_index = i; flmd.flmd_flags = fe->fe_flags; fe->fe_action = VR_FLOW_ACTION_DROP; vr_flush_entry(router, fe, &flmd, &fmd); vr_reset_flow_entry(router, fe, i); } } } vr_flow_table_info_reset(router); return; }
static struct vr_flow_entry * vr_find_free_entry(struct vrouter *router, struct vr_flow *key, uint8_t type, bool need_hold, unsigned int *fe_index) { unsigned int i, index, hash; struct vr_flow_entry *tmp_fe, *fe = NULL; *fe_index = 0; hash = vr_hash(key, key->flow_key_len, 0); index = (hash % vr_flow_entries) & ~(VR_FLOW_ENTRIES_PER_BUCKET - 1); for (i = 0; i < VR_FLOW_ENTRIES_PER_BUCKET; i++) { tmp_fe = vr_flow_table_entry_get(router, index); if (tmp_fe && !(tmp_fe->fe_flags & VR_FLOW_FLAG_ACTIVE)) { if (vr_set_flow_active(tmp_fe)) { vr_init_flow_entry(tmp_fe); fe = tmp_fe; break; } } index++; } if (!fe) { index = hash % vr_oflow_entries; for (i = 0; i < vr_oflow_entries; i++) { tmp_fe = vr_oflow_table_entry_get(router, index); if (tmp_fe && !(tmp_fe->fe_flags & VR_FLOW_FLAG_ACTIVE)) { if (vr_set_flow_active(tmp_fe)) { vr_init_flow_entry(tmp_fe); fe = tmp_fe; break; } } index = (index + 1) % vr_oflow_entries; } if (fe) *fe_index += vr_flow_entries; } if (fe) { *fe_index += index; if (need_hold) { fe->fe_hold_list = vr_zalloc(sizeof(struct vr_flow_queue)); if (!fe->fe_hold_list) { vr_reset_flow_entry(router, fe, *fe_index); fe = NULL; } else { fe->fe_hold_list->vfq_index = *fe_index; } } if (fe) { fe->fe_type = type; fe->fe_key.flow_key_len = key->flow_key_len; memcpy(&fe->fe_key, key, key->flow_key_len); } } return fe; }