Applying Services to Sampled Packets

As background for this topic, you should understand service sets (see Services and Service Sets) and plugins (see Plugin Architecture and Plugin Functionality and Service Chaining).

Using services with sampled packets has many applications, among them measuring flow statistics at high link speeds that do not allow capturing all packets, custom traffic classification for security purposes, intrusion detection, and IPTV monitoring.

The steps to apply services to sampled packets using the SDK are:

  1. Configure a firewall filter with the sample action and attach it to an INGRESS interface. For details, see Configuration for Sampling-Style Service Sets.

  2. Configure a sampling service set to associate one or more plugins with sampled packets on the ms- interface. The service order section of the sampling service set determines the order in which the plugins service the sampled packets. For details, see Configuration for Sampling-Style Service Sets.

  3. By default, the system drops all the sampled packets after traversing the plugin chain. This prevents the sampled packets from going to the final destnation along with the transit packets.

    To send sampled traffic to the final destination, the plugin associated with the sampling configuration must explicitly call msp_send_packet(), passing the packet's jbuf as an argument, as follows:

    1. Copy the original jbuf by calling the jbuf_dup() function, or get a new local jbuf by calling jbuf_get() or jbuf_getchain().

    2. If needed, modify the local jbuf contents.

    3. Call msp_send_packet() with the local jbuf as an argument; handle any error conditions associated with the function.

    4. Return to the plugin, enabling the system to free the original jbuf.

msp_send_packet() is declared in your backing sandbox in the header file at sandbox/src/junos/lib/libmp-sdk/h/jnx/mpsdk.h.

The following test function in a plugin's data handling code processes event notifications for sampled packets. The code discards all ICMP packets, forwards all TCP packets so they are dropped by the infrastructure, and copies and transmits all UDP packets.

static int
sample_action(msvcs_data_context_t *sctx)
{
    struct ip *ip_hdr;
    jbuf_svc_set_info_t ss_info;
    struct jbuf *jb_to_send;
    int rc;
    struct jbuf *jb = (struct jbuf *)sctx->sc_pkt;

    jbuf_get_svc_set_info(jb, &ss_info);
    if (ss_info.mon_svc == 0) {
        /*
         * This is not a sampled packet, so we will
         * just discard it in the interest of testing.
         */
        syslog(LOG_INFO, "SAMPLING_TEST (%s) : Not a sampled packet\n", __func__);
        return MSVCS_ST_PKT_DISCARD;
    }

    /*
     * Discard all ICMP packets and forward all TCP packets so they are dropped by the
     * infrastructure. All UDP packets will be copied and transmitted
     * by calling msp_send_packet().
     */
    ip_hdr = jbuf_to_d(jb, struct ip *);
    if (ip_hdr->ip_p == IPPROTO_ICMP) {
        syslog(LOG_INFO, "SAMPLING_TEST (%s) : ICMP sampled packet\n", __func__);
        return MSVCS_ST_PKT_DISCARD;
    } else if (ip_hdr->ip_p == IPPROTO_TCP) {
        syslog(LOG_INFO, "SAMPLING_TEST (%s) : TCP sampled packet\n", __func__);
        return MSVCS_ST_OK;
    } else if (ip_hdr->ip_p == IPPROTO_UDP) {
        syslog(LOG_INFO, "SAMPLING_TEST (%s) : UDP sampled packet\n", __func__);
        jb_to_send = jbuf_dup(jb);
        if (jb_to_send == NULL) {
            syslog(LOG_ERR, "SAMPLING_TEST (%s) : Unable to "
                   "copy the jbuf\n", __func__);
            return MSVCS_ST_OK;
        }

        /*
         * Transmit the copied jbuf.
         * This copied jbuf may be tailored before transmitting.
         */
        rc = msp_send_packet((void *)jb_to_send);
        if (rc != MSP_OK) {
            /* Handle the error condition */
            syslog(LOG_ERR, "SAMPLING_TEST (%s) : msp_send_packet "
                   "failed (error = %d).\n", __func__, rc);
        } else {
            syslog(LOG_INFO, "SAMPLING_TEST (%s) : msp_send_packet was successful.\n", __func__);
        }

        /* return to infrastructure */
        return MSVCS_ST_OK;
    } else {
        syslog(LOG_INFO, "SAMPLING_TEST (%s) : Protocol = %d\n", __func__, ip_hdr->ip_p);
        return MSVCS_ST_OK;
    }
}

The function is called from the data event handler as follows in response to the MSVCS_DATA_EV_PKT_PROC and MSVCS_DATA_EV_FIRST_PKT_PROC events:

int
 jnx_msptest_plugin1_data_handler(msvcs_data_context_t *sctx, msvcs_data_event_t ev) 
 {
   void *plugin_ext;
   int   cpu_id = msvcs_state_get_cpuid();
     
   switch(ev) {
 
     /* Initialize any global state */
     case MSVCS_DATA_EV_SM_INIT:
          return jnx_msptest_plugin1_sm_init(sctx);
 
     /* Initialize any per thread state */
     case MSVCS_DATA_EV_INIT:
         break;
 
     case MSVCS_DATA_EV_PKT_PROC:
       return sample_action(sctx);
       return MSVCS_ST_PKT_FORWARD;

 
     case MSVCS_DATA_EV_FIRST_PKT_PROC:
       if (sample_action(sctx) == MSVCS_ST_PKT_DISCARD) {
             return MSVCS_ST_PKT_DISCARD;
       }
       
       /* Try to attach to the session */
 
        plugin_ext = msp_objcache_alloc(pstate.oc, 
                                        msvcs_state_get_cpuid(),
                                        sctx->sc_sset_id);

        if (plugin_ext) {
            if (msvcs_session_set_ext_handle(sctx->sc_session, 
                                             pstate.plugin_id,
                                             plugin_ext, NULL)) {
                msp_log(LOG_ERR, "failed to setup session extension\n");
            }
        } else {
            msp_log(LOG_ERR, "failed to allocate session extension\n");
        }

        msp_log(LOG_INFO, "setup session extension\n");

        return MSVCS_ST_PKT_FORWARD;
                                     
    case MSVCS_EV_SESSION_OPEN:
    case MSVCS_EV_SESSION_CLOSE:
        break;

    case MSVCS_EV_SESSION_DESTROY:

        if (msvcs_session_get_ext_handle(sctx->sc_session, 
                                         pstate.plugin_id,
                                         &plugin_ext, NULL)) {
            msp_log(LOG_ERR, "failed to get session extension\n");
        } else {
            msp_objcache_free(pstate.oc, plugin_ext, 
                              msvcs_state_get_cpuid(), 
                              sctx->sc_sset_id);
        }

        msp_log(LOG_INFO, "free session extension\n");
        
        break;
    }

    return MSVCS_ST_OK;
}
        
        

The following limitations apply to calling the msp_send_packet() function:


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