The Plugins

The two plugins implement the services whose configuration is shown in Configuring the Service Sets and Services.

Each plugin exists as a dynamic object, containing three components: entry point, control event handler and data event handler.

Both plugins handle the same set of events; the only difference is the action taken in response to data packet events (see Plugin Actions).

Calling the Entry Function

The plugin entry point is specified in the XML configuration file, which the example provides at sandbox/src/etc/equilibrium2-services.xml. After installation, the system places this file in /opt/sdk/pkg/<package-name>.xml on the PIC.

<pkg-config>
    <!-- Package configuration header - one per config file -->
    <header>
       <!-- config file syntax version -->
       <version>1.0</version>
       <!-- unique services package (container) name -->
       <name>sync-equilibrium2-services</name>
    </header>
 
    <!-- List of plugins -->
    <plug-in>
       <!-- unique plugin package name -->
       <name>sync-equilibrium2-classify</name>
       <!-- plugin shared object full name (with path) -->
       <path>/opt/sdk/lib/libequilibrium2-classify.so.1</path>
       <!-- plugin entry point, this function is called when
            plugin src is loaded -->
       <entry>equilibrium2_classify_entry</entry>
    </plug-in>

    <plug-in>
       <!-- unique plugin package name -->
       <name>sync-equilibrium2-balance</name>
       <!-- plugin shared object full name (with path) -->
       <path>/opt/sdk/lib/libequilibrium2-balance.so.1</path>
       <!-- plugin entry point, this function is called when
            plugin src is loaded -->
       <entry>equilibrium2_balance_entry</entry>
    </plug-in>
</pkg-config>

Calling the Control and Data Handlers

The code that tells the system to call the control and data handlers is supplied in each plugin's entry point, where the plugin registers with the system, by setting the spp_control_evh and spp_data_evh parameters. The entry function is called when the service is loaded as a dynamic object by the management daemon. It registers the control event handler, data event handler and some other plugin information to the services plugin management daemon (mspmand,)and then gets a plugin ID.

For example:

int
equilibrium2_balance_entry (void)
{
    msvcs_plugin_params_t params;

    strlcpy(params.spp_name, EQ2_BALANCE_SVC_NAME, sizeof(params.spp_name));
    params.spp_data_evh = equilibrium2_balance_data_hdlr;
    params.spp_control_evh = equilibrium2_balance_ctrl_hdlr;
    params.spp_plugin_app_id = BALANCE_PLUGIN;
    params.spp_class = MSVCS_PLUGIN_CLASS_EXTERNAL;
    balance_pid = msvcs_plugin_register(&params);

    if (balance_pid < 0) {
        msp_log(LOG_ERR, "%s: Register service ERROR!", __func__);
    } else {
        msp_log(LOG_INFO, "%s: Service was registered.", __func__);
    }
    return balance_pid;
}

Control Operations

The code for the control operations is in the file equilibrium2-plugin-name_ctrl.c. The plugins process two control events: initialization, and the availability of a configuration blob. The initialization event is received once, at startup; the control event handler initializes the environment when it receives this event.

The configuration blob event is received whenever a configuration blob arrives for this service. The service can receive two types of configuration blobs, and can perform two operations as follows:

During this transit period, when the the old policy is still being used and the new policy has just arrived, the data event handler refuses all new sessions (because the new policy is not active yet.) Once all the existing sessions are closed, the old policy is removed from the policy database and the new policy is activated.

Data Operations

The code for the control operations is in the file equilibrium2-plugin-name_data.c.

Each plugin has a data event handler that applies an action to incoming packets:

The plugins process the following data events:

For example, the following code in the balance plugin decides what to do based on the data event that was received. The code in the classify plugin is identical.

int
equilibrium2_balance_data_hdlr (msvcs_data_context_t *ctx,
        msvcs_data_event_t ev)
{
    data_ctx = ctx;

    switch (ev) {
    case MSVCS_DATA_EV_SM_INIT:
        msp_log(LOG_INFO, "%s: MSVCS_DATA_EV_SM_INIT", __func__);
        break;

    case MSVCS_DATA_EV_INIT:
        msp_log(LOG_INFO, "%s: MSVCS_DATA_EV_INIT", __func__);
        break;

    case MSVCS_DATA_EV_FIRST_PKT_PROC:
        msp_log(LOG_INFO, "%s: MSVCS_DATA_EV_FIRST_PKT_PROC", __func__);
        first_pkt_proc();
        return take_action();
        break;

    case MSVCS_DATA_EV_PKT_PROC:
        msp_log(LOG_INFO, "%s: MSVCS_DATA_EV_PKT_PROC", __func__);
        return take_action();
        break;

    case MSVCS_DATA_EV_SESSION_OPEN:
        msp_log(LOG_INFO, "%s: MSVCS_DATA_EV_SESSION_OPEN", __func__);
        break;

    case MSVCS_DATA_EV_SESSION_CLOSE:
        msp_log(LOG_INFO, "%s: MSVCS_DATA_EV_SESSION_CLOSE", __func__);
        session_close();
        break;

    case MSVCS_DATA_EV_SESSION_DESTROY:
        msp_log(LOG_INFO, "%s: MSVCS_DATA_EV_SESSION_DESTROY", __func__);
        break;

    default:
        msp_log(LOG_ERR, "%s: Unknown event!", __func__);
    }
    return MSVCS_ST_OK;
}

Plugin Actions

A large part of the code in the two plugins is identical; the only differences come in the actions taken with respect to packets. In both, the function first_packet_proc() reads the configured service set rules, creates an action, and attaches it to the session:

/* Create action and attach it to the session. */
    if (addr) {
        /* Only one action (rule) is supported for now. */
        action = (ssn_action_t *)calloc(1, sizeof(ssn_action_t));
        INSIST_ERR(action != NULL);
        action->addr = addr;
        msvcs_session_set_ext_handle((msvcs_session_t *)data_ctx->sc_session,
                (uint8_t)classify_pid, action, action);
        ss->ss_ssn_count++;
    }
    msp_spinlock_unlock(&svc_set_lock);
    return MSVCS_ST_PKT_FORWARD;

The function take_action() then applies the action to a forward or reverse flow.

 static int
take_action (void)
{
    ssn_action_t *f_action = NULL;
    ssn_action_t *r_action = NULL;
    struct jbuf *jb = (struct jbuf *)data_ctx->sc_pkt;
    struct ip *ip_hdr = (struct ip *)jb->jb_data;

    /* Get session action. */
    msvcs_session_get_ext_handle((msvcs_session_t *)data_ctx->sc_session,
            (uint8_t)classify_pid, (void **)&f_action, (void **)&r_action);

    if (jb->jb_svcs_hdr.jb_svcs_hdr_flags & JBUF_SVCS_FLAG_DIR_FORWARD) {
        if (f_action) {
            ip_hdr->ip_dst.s_addr = f_action->addr;
        } else {
            msp_log(LOG_INFO, "%s: No forward action!", __FUNCTION__);
        }
    } else {
        if (r_action) {
            ip_hdr->ip_src.s_addr = r_action->addr;
        } else {
            msp_log(LOG_INFO, "%s: No reversed action!", __FUNCTION__);
        }
    }

    return MSVCS_ST_PKT_FORWARD;
}
 

2007-2009 Juniper Networks, Inc. All rights reserved. The information contained herein is confidential information of Juniper Networks, Inc., and may not be used, disclosed, distributed, modified, or copied without the prior written consent of Juniper Networks, Inc. in an express license. This information is subject to change by Juniper Networks, Inc. Juniper Networks, the Juniper Networks logo, and JUNOS are registered trademarks of Juniper Networks, Inc. in the United States and other countries. All other trademarks, service marks, registered trademarks, or registered service marks are the property of their respective owners.
Generated on Sun May 30 20:26:47 2010 for Juniper Networks Partner Solution Development Platform JUNOS SDK 10.2R1 by Doxygen 1.4.5