Beispiel #1
0
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);
}
Beispiel #2
0
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);
}
Beispiel #3
0
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);
}
Beispiel #4
0
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);
}
Beispiel #5
0
/*
 * 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);
}
Beispiel #6
0
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);
}
Beispiel #7
0
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);
}
Beispiel #8
0
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);
}
Beispiel #9
0
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;
}
Beispiel #10
0
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;
}
Beispiel #11
0
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;
}
Beispiel #12
0
/*
 * 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);
}
Beispiel #13
0
/*
 * 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;
}