static int32 emf_iflist_add(emf_struct_t *emf, emf_info_t *emfi, struct net_device *if_ptr) { emf_iflist_t *ptr, *prev; OSL_LOCK(emf->lock); if (emf_iflist_find(emf, emfi, if_ptr, &prev) == NULL) { ptr = MALLOC(emfi->osh, sizeof(emf_iflist_t)); if (ptr == NULL) { EMF_ERROR("Unable to allocate iflist entry\n"); OSL_UNLOCK(emf->lock); return (FAILURE); } /* Initialize the iflist entry */ ptr->if_ptr = if_ptr; /* Add the entry to iflist for this EMF instance */ ptr->next = emfi->iflist_head; emfi->iflist_head = ptr; OSL_UNLOCK(emf->lock); return (SUCCESS); } OSL_UNLOCK(emf->lock); return (FAILURE); }
static emf_info_t * emf_instance_find_by_ifptr(emf_struct_t *emf, struct net_device *if_ptr) { emf_iflist_t *ptr; emf_info_t *emfi; ASSERT(if_ptr != NULL); OSL_LOCK(emf->lock); for (emfi = emf->list_head; emfi != NULL; emfi = emfi->next) { for (ptr = emfi->iflist_head; ptr != NULL; ptr = ptr->next) { if (ptr->if_ptr == if_ptr) { OSL_UNLOCK(emf->lock); return (emfi); } } } OSL_UNLOCK(emf->lock); return (NULL); }
static int32 emf_iflist_del(emf_struct_t *emf, emf_info_t *emfi, struct net_device *if_ptr) { emf_iflist_t *ptr, *prev; OSL_LOCK(emf->lock); if ((ptr = emf_iflist_find(emf, emfi, if_ptr, &prev)) != NULL) { /* Delete the entry from iflist */ if (prev != NULL) prev->next = ptr->next; else emfi->iflist_head = ptr->next; MFREE(emfi->osh, ptr, sizeof(emf_iflist_t)); OSL_UNLOCK(emf->lock); return (SUCCESS); } OSL_UNLOCK(emf->lock); return (FAILURE); }
static emf_iflist_t * emf_iflist_find(emf_struct_t *emf, emf_info_t *emfi, struct net_device *if_ptr, emf_iflist_t **prev) { emf_iflist_t *ptr; ASSERT(if_ptr != NULL); OSL_LOCK(emf->lock); *prev = NULL; for (ptr = emfi->iflist_head; ptr != NULL; *prev = ptr, ptr = ptr->next) { if (ptr->if_ptr == if_ptr) { OSL_UNLOCK(emf->lock); return (ptr); } } OSL_UNLOCK(emf->lock); return (NULL); }
/* * Description: This function is called when user disables EMF on a bridge * interface. It unregisters the Netfilter hook functions, * calls the common code cleanup routine and releases all the * resources allocated during instance creation. * * Input: emf - EMF module global data pointer * emf_info - EMF instance data pointer */ static int32 emf_instance_del(emf_struct_t *emf, emf_info_t *emfi) { bool found = FALSE; osl_t *osh; emf_info_t *ptr, *prev; #ifdef CONFIG_PROC_FS uint8 proc_name[64]; #endif /* CONFIG_PROC_FS */ /* Interfaces attached to the EMF instance should be deleted first */ emf_iflist_clear(emf, emfi); /* Delete the EMF instance */ prev = NULL; for (ptr = emf->list_head; ptr != NULL; prev = ptr, ptr = ptr->next) { if (ptr == emfi) { found = TRUE; if (prev != NULL) prev->next = ptr->next; else emf->list_head = NULL; break; } } if (!found) { EMF_ERROR("EMF instance not found\n"); return (FAILURE); } emf->inst_count--; /* Free the EMF instance */ OSL_UNLOCK(emf->lock); emf_hooks_unregister(ptr); OSL_LOCK(emf->lock); emfc_exit(ptr->emfci); #ifdef CONFIG_PROC_FS sprintf(proc_name, "net/emf_stats_%s", emfi->inst_id); remove_proc_entry(proc_name, 0); sprintf(proc_name, "net/emfdb_%s", emfi->inst_id); remove_proc_entry(proc_name, 0); #endif /* CONFIG_PROC_FS */ osh = ptr->osh; MFREE(emfi->osh, ptr, sizeof(emf_info_t)); osl_detach(osh); return (SUCCESS); }
static emf_info_t * emf_instance_find_by_brptr(emf_struct_t *emf, struct net_device *br_ptr) { emf_info_t *emfi; ASSERT(br_ptr != NULL); OSL_LOCK(emf->lock); for (emfi = emf->list_head; emfi != NULL; emfi = emfi->next) { if (br_ptr == emfi->br_dev) { OSL_UNLOCK(emf->lock); return (emfi); } } OSL_UNLOCK(emf->lock); return (NULL); }
static igs_info_t * igs_instance_find(int8 *inst_id) { igs_info_t *igs_info; ASSERT(inst_id != NULL); OSL_LOCK(igs.lock); for (igs_info = igs.list_head; igs_info != NULL; igs_info = igs_info->next) { if (strcmp(igs_info->inst_id, inst_id) == 0) { OSL_UNLOCK(igs.lock); return (igs_info); } } OSL_UNLOCK(igs.lock); return (NULL); }
static int32 igs_instance_del(igs_info_t *igs_info) { bool found = FALSE; osl_t *osh; igs_info_t *ptr, *prev; uint8 proc_name[64]; OSL_LOCK(igs.lock); /* Delete the IGS instance */ prev = NULL; for (ptr = igs.list_head; ptr != NULL; prev = ptr, ptr = ptr->next) { if (ptr == igs_info) { found = TRUE; if (prev != NULL) prev->next = ptr->next; else igs.list_head = igs.list_head->next; break; } } OSL_UNLOCK(igs.lock); if (!found) { IGS_ERROR("IGS instance not found\n"); return (FAILURE); } igs.inst_count--; /* Free the IGS instance */ igsc_exit(igs_info->igsc_info); #ifdef CONFIG_PROC_FS sprintf(proc_name, "emf/igs_stats_%s", igs_info->inst_id); remove_proc_entry(proc_name, 0); sprintf(proc_name, "emf/igsdb_%s", igs_info->inst_id); remove_proc_entry(proc_name, 0); #endif /* CONFIG_PROC_FS */ osh = igs_info->osh; MFREE(igs_info->osh, igs_info, sizeof(igs_info_t)); osl_detach(osh); return (SUCCESS); }
static void igs_instances_clear(void) { igs_info_t *ptr, *tmp; OSL_LOCK(igs.lock); ptr = igs.list_head; while (ptr != NULL) { tmp = ptr->next; igs_instance_del(ptr); ptr = tmp; } OSL_UNLOCK(igs.lock); return; }
static void emf_iflist_clear(emf_struct_t *emf, emf_info_t *emfi) { emf_iflist_t *ptr, *next = NULL; OSL_LOCK(emf->lock); ptr = emfi->iflist_head; while (ptr != NULL) { next = ptr->next; MFREE(emfi->osh, ptr, sizeof(emf_iflist_t)); ptr = next; } emfi->iflist_head = NULL; OSL_UNLOCK(emf->lock); return; }
static void emf_instances_clear(emf_struct_t *emf) { emf_info_t *ptr, *tmp; OSL_LOCK(emf->lock); ptr = emf->list_head; while (ptr != NULL) { tmp = ptr->next; emf_instance_del(emf, ptr); ptr = tmp; } emf->list_head = NULL; OSL_UNLOCK(emf->lock); return; }
/* * Description: This function is called when user application enables snooping * on a bridge interface. It primarily allocates memory for IGS * instance data and calls common code initialization function. */ static igs_info_t * igs_instance_add(int8 *inst_id, struct net_device *br_ptr) { igs_info_t *igs_info; osl_t *osh; uint8 proc_name[64]; igsc_wrapper_t igsl; if (igs.inst_count > IGS_MAX_INST) { IGS_ERROR("Max instance limit %d exceeded\n", IGS_MAX_INST); return (NULL); } igs.inst_count++; IGS_INFO("Creating IGS instance for %s\n", inst_id); osh = osl_attach(NULL, PCI_BUS, FALSE); ASSERT(osh); /* Allocate os specfic IGS info object */ igs_info = MALLOC(osh, sizeof(igs_info_t)); if (igs_info == NULL) { IGS_ERROR("Out of memory allocating igs_info\n"); osl_detach(osh); return (NULL); } igs_info->osh = osh; /* Save the IGS instance identifier */ strncpy(igs_info->inst_id, inst_id, IFNAMSIZ); igs_info->inst_id[IFNAMSIZ - 1] = 0; /* Save the device pointer */ igs_info->br_dev = br_ptr; /* Fill in linux specific wrapper functions*/ igsl.igs_broadcast = (igs_broadcast_fn_ptr)igs_broadcast; /* Initialize IGSC layer */ if ((igs_info->igsc_info = igsc_init(inst_id, (void *)igs_info, osh, &igsl)) == NULL) { IGS_ERROR("IGSC init failed\n"); MFREE(osh, igs_info, sizeof(igs_info_t)); osl_detach(osh); return (NULL); } #ifdef CONFIG_PROC_FS sprintf(proc_name, "net/igs_stats_%s", inst_id); create_proc_read_entry(proc_name, 0, 0, igs_stats_get, igs_info); sprintf(proc_name, "net/igsdb_%s", inst_id); create_proc_read_entry(proc_name, 0, 0, igs_sdb_list, igs_info); #endif /* CONFIG_PROC_FS */ IGS_INFO("Created IGSC instance for %s\n", inst_id); /* Add to global IGS instance list */ OSL_LOCK(igs.lock); igs_info->next = igs.list_head; igs.list_head = igs_info; OSL_UNLOCK(igs.lock); return (igs_info); }
/* * Description: This function handles the OS specific processing * required for configuration commands. * * Input: data - Configuration command parameters */ void emf_cfg_request_process(emf_cfg_request_t *cfg) { emf_info_t *emfi; emf_cfg_mfdb_t *mfdb; emf_cfg_uffp_t *uffp; emf_cfg_rtport_t *rtport; emf_cfg_if_t *if_cfg; emf_iflist_t *iflist_prev, *ifl_ptr; struct net_device *if_ptr, *br_ptr; BUG_ON(cfg == NULL); /* Validate the instance identifier */ br_ptr = emf_if_name_validate(cfg->inst_id); if (br_ptr == NULL) { cfg->status = EMFCFG_STATUS_FAILURE; cfg->size = sprintf(cfg->arg, "Unknown instance identifier %s\n", cfg->inst_id); return; } /* Locate the EMF instance */ emfi = emf_instance_find_by_brptr(emf, br_ptr); if ((emfi == NULL) && (cfg->command_id != EMFCFG_CMD_BR_ADD)) { cfg->status = EMFCFG_STATUS_FAILURE; cfg->size = sprintf(cfg->arg, "Invalid instance identifier %s\n", cfg->inst_id); return; } /* Convert the interface name in arguments to interface pointer */ switch (cfg->command_id) { case EMFCFG_CMD_MFDB_ADD: case EMFCFG_CMD_MFDB_DEL: mfdb = (emf_cfg_mfdb_t *)cfg->arg; mfdb->if_ptr = emf_if_name_validate(mfdb->if_name); if (mfdb->if_ptr == NULL) { cfg->status = EMFCFG_STATUS_FAILURE; cfg->size = sprintf(cfg->arg, "Invalid interface specified " "during MFDB entry add/delete\n"); return; } OSL_LOCK(emf->lock); /* The interfaces specified should be in the iflist */ ifl_ptr = emf_iflist_find(emf, emfi, mfdb->if_ptr, &iflist_prev); OSL_UNLOCK(emf->lock); if ((strncmp(mfdb->if_name, "wds", 3) != 0) && ifl_ptr == NULL) { cfg->status = EMFCFG_STATUS_FAILURE; cfg->size = sprintf(cfg->arg, "Interface not part of bridge %s\n", br_ptr->name); } else { emfc_cfg_request_process(emfi->emfci, cfg); } break; case EMFCFG_CMD_IF_ADD: case EMFCFG_CMD_IF_DEL: /* Add/Del the interface to/from the global list */ if_cfg = (emf_cfg_if_t *)cfg->arg; if_ptr = emf_if_name_validate(if_cfg->if_name); if (if_ptr == NULL) { cfg->status = EMFCFG_STATUS_FAILURE; cfg->size = sprintf(cfg->arg, "Invalid interface specified\n"); return; } if (cfg->command_id == EMFCFG_CMD_IF_ADD) { if (emf_iflist_add(emf, emfi, if_ptr) != SUCCESS) { cfg->status = EMFCFG_STATUS_FAILURE; cfg->size = sprintf(cfg->arg, "Interface add failed\n"); return; } if (emfc_iflist_add(emfi->emfci, if_ptr) != SUCCESS) { emf_iflist_del(emf, emfi, if_ptr); cfg->status = EMFCFG_STATUS_FAILURE; cfg->size = sprintf(cfg->arg, "Interface add failed\n"); return; } } if (cfg->command_id == EMFCFG_CMD_IF_DEL) { if ((emf_iflist_del(emf, emfi, if_ptr) != SUCCESS) || (emfc_iflist_del(emfi->emfci, if_ptr) != SUCCESS)) { cfg->status = EMFCFG_STATUS_FAILURE; cfg->size = sprintf(cfg->arg, "Interface delete failed\n"); return; } } cfg->status = EMFCFG_STATUS_SUCCESS; break; case EMFCFG_CMD_IF_LIST: if (emf_iflist_list(emfi, (emf_cfg_if_list_t *)cfg->arg, cfg->size) != SUCCESS) { cfg->status = EMFCFG_STATUS_FAILURE; cfg->size += sprintf(cfg->arg, "EMF if list get failed\n"); break; } cfg->status = EMFCFG_STATUS_SUCCESS; break; case EMFCFG_CMD_BR_ADD: if (emfi != NULL) { cfg->status = EMFCFG_STATUS_FAILURE; cfg->size = sprintf(cfg->arg, "EMF already configured for %s\n", cfg->inst_id); return; } /* Create a new EMF instance corresponding to the bridge * interface. */ emfi = emf_instance_add(emf, cfg->inst_id, br_ptr); if (emfi == NULL) { cfg->status = EMFCFG_STATUS_FAILURE; cfg->size = sprintf(cfg->arg, "EMF add on %s failed\n", cfg->inst_id); return; } cfg->status = EMFCFG_STATUS_SUCCESS; break; case EMFCFG_CMD_BR_DEL: OSL_LOCK(emf->lock); /* Delete and free the EMF instance */ if (emf_instance_del(emf, emfi) != SUCCESS) { cfg->status = EMFCFG_STATUS_FAILURE; cfg->size = sprintf(cfg->arg, "EMF delete on %s failed\n", cfg->inst_id); } else { cfg->status = EMFCFG_STATUS_SUCCESS; } OSL_UNLOCK(emf->lock); break; case EMFCFG_CMD_UFFP_ADD: case EMFCFG_CMD_UFFP_DEL: uffp = (emf_cfg_uffp_t *)cfg->arg; if_ptr = uffp->if_ptr = emf_if_name_validate(uffp->if_name); /* FALLTHRU */ case EMFCFG_CMD_RTPORT_ADD: case EMFCFG_CMD_RTPORT_DEL: rtport = (emf_cfg_rtport_t *)cfg->arg; if_ptr = rtport->if_ptr = emf_if_name_validate(rtport->if_name); if (if_ptr == NULL) { cfg->status = EMFCFG_STATUS_FAILURE; cfg->size = sprintf(cfg->arg, "Invalid iface specified for deletion\n"); return; } OSL_LOCK(emf->lock); ifl_ptr = emf_iflist_find(emf, emfi, if_ptr, &iflist_prev); OSL_UNLOCK(emf->lock); if (ifl_ptr == NULL) { cfg->status = EMFCFG_STATUS_FAILURE; cfg->size = sprintf(cfg->arg, "Interface not part of bridge %s\n", br_ptr->name); } else { emfc_cfg_request_process(emfi->emfci, cfg); } break; default: emfc_cfg_request_process(emfi->emfci, cfg); break; } return; }