/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <ipp/ipp_config.h>
#include <inet/ipp_common.h>
/* DDI file for ipgpc ipp module */
/* protects against multiple configs */
ipgpc_create_action, /* ippo_action_create */
ipgpc_modify_action, /* ippo_action_modify */
ipgpc_destroy_action, /* ippo_action_destroy */
ipgpc_info, /* ippo_action_info */
ipgpc_invoke_action /* ippo_action_invoke */
};
extern struct mod_ops mod_ippops;
/*
* Module linkage information for the kernel.
*/
"IP Generic Packet Classifier (ipgpc) module 1.0",
};
(void *)&modlipp,
};
int
void)
{
int rc;
if (ipgpc_action_exist) {
return (EBUSY);
}
/* init mutexes */
/* clean up after fail */
}
return (rc);
}
int
void)
{
int rc;
if (ipgpc_action_exist) {
return (EBUSY);
}
return (rc);
}
/* destroy mutexes */
return (rc);
}
int
{
}
/*
* ipgpc_create_action(aid, nvlpp, flags)
*
* creates a single instance of ipgpc, if one does not exist. If an action
* instance already exists, fail with EBUSY
*
* if nvlpp contains the name IPP_ACTION_STATS_ENABLE, then process it and
* determine if global stats should be collected
*
* the ipgpc_config_lock is taken to block out any other creates or destroys
* the are issued while the create is taking place
*/
/* ARGSUSED */
static int
{
int rc;
/* only one ipgpc action instance can be loaded at once */
if (ipgpc_action_exist) {
return (EBUSY);
} else {
if (ipgpc_action_exist) {
return (EBUSY);
}
/* check for action param IPP_ACTION_STATS_ENABLE */
&stat)) != 0) {
} else {
}
ipgpc0dbg(("ipgpc_create_action: ipgpc_intialize " \
"error %d", rc));
return (rc);
}
return (0);
}
}
/*
* ipgpc_modify_action
*
* modify an instance of ipgpc
*
* nvlpp will contain the configuration type to switch off of. Use this
* to determine what modification should be made. If the modification fails,
* return the appropriate error.
*/
/* ARGSUSED */
static int
{
int rc = 0;
char *name;
!= 0) {
ipgpc0dbg(("ipgpc_modify_action: invalid configuration type"));
return (EINVAL);
}
switch (config_type) {
case IPP_SET: /* set an action parameter */
&stat)) != 0) {
ipgpc0dbg(("ipgpc_modify_action: invalid IPP_SET " \
"parameter"));
return (EINVAL);
} else {
}
break;
case CLASSIFIER_ADD_FILTER: /* add a filter */
ipgpc0dbg(("ipgpc_modify_action: invalid filter"));
break;
}
/* parse class name */
&name)) != 0) {
ipgpc0dbg(("ipgpc_modify_action: class name missing"));
break;
}
if (rc != 0) {
}
break;
case CLASSIFIER_ADD_CLASS: /* add a class */
ipgpc0dbg(("ipgpc_modify_action: invalid class"));
break;
}
break;
case CLASSIFIER_REMOVE_FILTER: /* remove a filter */
/* parse filter name */
&name)) != 0) {
ipgpc0dbg(("ipgpc_modify_action: filtername missing"));
break;
}
/* parse optional filter_instance */
&filter_instance) != 0) {
filter_instance = -1;
}
break;
case CLASSIFIER_REMOVE_CLASS: /* remove a class */
/* parse class name */
&name)) != 0) {
ipgpc0dbg(("ipgpc_modify_action: class name missing"));
break;
}
break;
case CLASSIFIER_MODIFY_FILTER: /* modify a filter */
break;
case CLASSIFIER_MODIFY_CLASS: /* modify a class */
break;
default: /* invalid config type */
ipgpc0dbg(("ipgpc_modify_action:invalid configuration type %u",
config_type));
return (EINVAL);
}
return (rc); /* nvlist is passed back NULL */
}
/*
* ipgpc_destroy_action(aid, flags)
*
* action destructor for ipgpc
*
* Destroys an instance of the ipgpc action, if one exists. The
* ipgpc_action_lock is taken to block out any other destroys or creates
* that might be issued while the action is being destroyed
*/
/* ARGSUSED */
static int
{
/* only destroy action if it exists */
if (ipgpc_action_exist == B_TRUE) {
if (ipgpc_action_exist == B_FALSE) {
return (EBUSY);
}
}
return (0);
}
/*
* ipgpc_info(aid, fn, arg)
*
* configuration quering function for ipgpc
*
* passes back the configuration of ipgpc through allocated nvlists
* all action paramaters, classes and filters are built into nvlists
* and passed to the function pointer fn with arg
*/
/* ARGSUSED */
static int
{
int rc;
/* set parameters */
return (rc);
}
/* set all classes */
return (rc);
}
/* set all filters */
return (rc);
}
return (0);
}
/*
* ipgpc_invoke_action(aid, packet)
*
* packet processing function for ipgpc
*
* given packet the selector information is parsed and the classify
* function is called with those selectors. The classify function will
* return either a class or NULL, which represents a memory error and
* ENOMEM is returned. If the class returned is not NULL, the class and next
* action, associated with that class, are added to packet
*/
/* ARGSUSED */
static int
{
int af;
int rc;
/* extract packet data */
/* If we don't get an M_DATA, then return an error */
} else {
ipgpc0dbg(("ipgpc_invoke_action: no data\n"));
return (EINVAL);
}
}
/*
* Translate the callout_pos into the direction the packet is traveling
*/
if (callout_pos != IPP_LOCAL_IN) {
if (callout_pos & IPP_LOCAL_OUT) {
} else if (callout_pos & IPP_FWD_IN) {
} else { /* IPP_FWD_OUT */
}
}
/* parse the packet from the message block */
/* Determine IP Header Version */
} else {
}
/* The ill_index could be 0 when called from forwarding (read) path */
if (ill_idx > 0)
/*
* Since all IPP actions in an IPMP group are performed
* relative to the IPMP group interface, if this is an
* underlying interface in an IPMP group, use the IPMP
* group interface's index.
*/
if (IS_UNDER_IPMP(ill))
else
/* Got the field from the ILL, go ahead and refrele */
} else {
/* unknown if_index */
}
if (ipgpc_debug > 5) {
/* print pkt under high debug level */
#ifdef IPGPC_DEBUG
#endif
}
if (ipgpc_debug > 3) {
}
/* classify this packet */
if (ipgpc_debug > 3) {
}
/* ipgpc_classify will only return NULL if a memory error occured */
return (ENOMEM);
}
/* print time to classify(..) */
out_class->next_action)) != 0) {
ipgpc0dbg(("ipgpc_invoke_action: ipp_packet_add_class " \
"failed with error %d", rc));
return (rc);
}
}