equilibrium2-classify_data.c

Go to the documentation of this file.
00001 /*
00002  * $Id: equilibrium2-classify_data.c 346460 2009-11-14 05:06:47Z ssiano $
00003  *
00004  * This code is provided as is by Juniper Networks SDK Developer Support.
00005  * It is provided with no warranties or guarantees, and Juniper Networks
00006  * will not provide support or maintenance of this code in any fashion.
00007  * The code is provided only to help a developer better understand how
00008  * the SDK can be used.
00009  *
00010  * Copyright (c) 2008, Juniper Networks, Inc.
00011  * All rights reserved.
00012  */
00013 
00020 #include <sync/equilibrium2.h>
00021 #include <sync/equilibrium2_svc.h>
00022 #include "equilibrium2-classify.h"
00023 
00024 #include <netinet/in_systm.h>
00025 #include <netinet/in.h>
00026 #include <netinet/ip.h>
00027 #include <netinet/tcp.h>
00028 #include <sys/jnx/jbuf.h>
00029 #include <jnx/mpsdk.h>
00030 #include <jnx/msp_objcache.h>
00031 #include <jnx/multi-svcs/msvcs_flow.h>
00032 #include <jnx/multi-svcs/msvcs_plugin.h>
00033 #include <jnx/multi-svcs/msvcs_session.h>
00034 
00035 static msvcs_data_context_t    *data_ctx; 
00049 static uint16_t
00050 ip_cksum (void *buf, int len)
00051 {
00052     uint8_t *p = buf;
00053     uint32_t sum = 0;
00054 
00055     while (len > 1) {
00056         sum += (*p << 8) + *(p + 1);
00057         len -= 2;
00058         p += 2;
00059     }
00060     if (len == 1) {
00061         sum += (*p << 8);
00062     }
00063     while (sum >> 16) {
00064         sum = (sum & 0xFFFF) + (sum >> 16);
00065     }
00066     sum = ~sum;
00067     return(htons((uint16_t)sum));
00068 }
00069 
00088 static uint16_t
00089 tcp_cksum (uint16_t len, void *src_addr, void *dst_addr, void *buf)
00090 {
00091     uint32_t sum = 0;
00092     uint8_t *p = NULL;
00093 
00094     p = (uint8_t *)src_addr;
00095     sum += (*p << 8) + *(p + 1);
00096     sum += (*(p + 2) << 8) + *(p + 3);
00097 
00098     p = (uint8_t *)dst_addr;
00099     sum += (*p << 8) + *(p + 1);
00100     sum += (*(p + 2) << 8) + *(p + 3);
00101 
00102     sum += IPPROTO_TCP + len;
00103 
00104     p = (uint8_t *)buf;
00105     while (len > 1) {
00106         sum += (*p << 8) + *(p + 1);
00107         len -= 2;
00108         p += 2;
00109     }
00110     if (len == 1) {
00111         sum += (*p << 8);
00112     }
00113     while (sum >> 16) {
00114         sum = (sum & 0xFFFF) + (sum >> 16);
00115     }
00116     sum = ~sum;
00117     return(htons((uint16_t)sum));
00118 }
00119 
00126 static int
00127 take_action (void)
00128 {
00129     ssn_f_action_t *f_action = NULL;
00130     ssn_r_action_t *r_action = NULL;
00131     struct jbuf *jb = (struct jbuf *)data_ctx->sc_pkt;
00132     struct ip *ip_hdr = jbuf_to_d(jb, struct ip *);
00133     struct tcphdr *tcp_hdr;
00134 
00135     tcp_hdr = (struct tcphdr *)(jbuf_to_d(jb, char *) + ip_hdr->ip_hl * 4);
00136 
00137     /* Get session action. */
00138     msvcs_session_get_ext_handle((msvcs_session_t *)data_ctx->sc_session,
00139             (uint8_t)classify_pid, (void **)&f_action, (void **)&r_action);
00140 
00141     if (jbuf_to_svcs_hdr(jb, struct jbuf_svcs_hdr).jb_svcs_hdr_flags &
00142             JBUF_SVCS_FLAG_DIR_FORWARD) {
00143         if (f_action) {
00144             msp_log(LOG_INFO, "%s: Forward action %x -> %x", __func__,
00145                     ip_hdr->ip_dst.s_addr, f_action->addr);
00146             ip_hdr->ip_dst.s_addr = f_action->addr;
00147 
00148             /* Recalculate IP header checksum. */
00149             ip_hdr->ip_sum = 0;
00150             ip_hdr->ip_sum = ip_cksum(ip_hdr, ip_hdr->ip_hl * 4);
00151 
00152             /* Recalculate TCP checksum. */
00153             tcp_hdr->th_sum = 0;
00154             tcp_hdr->th_sum = tcp_cksum(ip_hdr->ip_len - ip_hdr->ip_hl * 4,
00155                     &ip_hdr->ip_src.s_addr, &ip_hdr->ip_dst.s_addr, tcp_hdr);
00156         } else {
00157             msp_log(LOG_INFO, "%s: No action for forward flow!", __func__);
00158         }
00159     } else {
00160         if (r_action) {
00161             msp_log(LOG_INFO, "%s: Reverse action %x -> %x", __func__,
00162                     ip_hdr->ip_src.s_addr, r_action->addr);
00163             ip_hdr->ip_src.s_addr = r_action->addr;
00164 
00165             /* Recalculate IP header checksum. */
00166             ip_hdr->ip_sum = 0;
00167             ip_hdr->ip_sum = ip_cksum(ip_hdr, ip_hdr->ip_hl * 4);
00168 
00169             /* Recalculate TCP checksum. */
00170             tcp_hdr->th_sum = 0;
00171             tcp_hdr->th_sum = tcp_cksum(ip_hdr->ip_len - ip_hdr->ip_hl * 4,
00172                     &ip_hdr->ip_src.s_addr, &ip_hdr->ip_dst.s_addr, tcp_hdr);
00173         } else {
00174             msp_log(LOG_INFO, "%s: No action for reversed flow!", __func__);
00175         }
00176     }
00177 
00178     return MSVCS_ST_PKT_FORWARD;
00179 }
00180 
00187 static int
00188 first_pkt_proc (void)
00189 {
00190     struct jbuf *jb = (struct jbuf *)data_ctx->sc_pkt;
00191     struct ip *ip_hdr;
00192     struct tcphdr *tcp_hdr;
00193     blob_svc_set_t *policy;
00194     blob_rule_t *rule;
00195     blob_term_t *term;
00196     in_addr_t addr = INADDR_ANY;
00197     ssn_f_action_t *f_action;
00198     ssn_r_action_t *r_action;
00199     sp_svc_set_t *ss;
00200     int i, j;
00201 
00202     ip_hdr = jbuf_to_d(jb, struct ip *);
00203     if (ip_hdr->ip_p != IPPROTO_TCP) {
00204         msp_log(LOG_INFO, "%s: Not TCP packet!", __func__);
00205         return MSVCS_ST_PKT_FORWARD;
00206     }
00207     tcp_hdr = (struct tcphdr *)(jbuf_to_d(jb, char *) + ip_hdr->ip_hl * 4);
00208 
00209     /* Lock service-set till the end of first packet process,
00210      * cause session counter may be updated at the end.
00211      */
00212     msp_spinlock_lock(&svc_set_lock);
00213 
00214     /* If there is an inactive service-set policy, don't accept any new
00215      * session.
00216      */
00217     if (get_svc_set(data_ctx->sc_sset_id, false)) {
00218         msp_log(LOG_INFO, "%s: Inactive policy exists!", __func__);
00219         goto discard;
00220     }
00221 
00222     /* Get the active service-set policy. */
00223     ss = get_svc_set(data_ctx->sc_sset_id, true);
00224     if (ss == NULL) {
00225         msp_log(LOG_ERR, "%s: No service set!", __func__);
00226         goto discard;
00227     }
00228 
00229     policy = ss->ss_policy;
00230     if (policy == NULL) {
00231         msp_log(LOG_ERR, "%s: No policy!", __func__);
00232         goto discard;
00233     }
00234 
00235     /* Go through all rules to this service set and create action list.
00236      * Only one rule/action is supported for now.
00237      */
00238     rule = policy->ss_rule;
00239     for (i = 0; i < policy->ss_rule_count; i++) {
00240         msp_log(LOG_INFO, "%s: Checking rule %s.", __func__, rule->rule_name);
00241         term = rule->rule_term;
00242         for (j = 0; j < rule->rule_term_count; j++) {
00243             if (term->term_match_id == TERM_FROM_SVC_TYPE) {
00244                 if (tcp_hdr->th_dport == term->term_match_port) {
00245                     addr = term->term_act_addr;
00246                     break;
00247                 }
00248             }
00249             term++;
00250         }
00251         rule = (blob_rule_t *)term;
00252     }
00253 
00254     /* Create action and attach it to the session. */
00255     if (addr) {
00256         /* Only one action (rule) for each direction is supported for now. */
00257         f_action = msp_shm_alloc(data_ctx->sc_shm, sizeof(ssn_f_action_t));
00258         INSIST_ERR(f_action != NULL);
00259 
00260         /* Change destination address to service gate address. */
00261         r_action = msp_shm_alloc(data_ctx->sc_shm, sizeof(ssn_r_action_t));
00262         INSIST_ERR(r_action != NULL);
00263 
00264         /* Save the destination address as reverse path source address. */
00265         r_action->addr = ip_hdr->ip_dst.s_addr;
00266 
00267         msvcs_session_set_ext_handle((msvcs_session_t *)data_ctx->sc_session,
00268                 (uint8_t)classify_pid, f_action, r_action);
00269         ss->ss_ssn_count++;
00270         msp_log(LOG_INFO, "%s: Forward action %x is created.", __func__, addr);
00271         msp_log(LOG_INFO, "%s: Reverse action %x is created.", __func__,
00272                 ip_hdr->ip_dst.s_addr);
00273     }
00274     msp_spinlock_unlock(&svc_set_lock);
00275     return MSVCS_ST_PKT_FORWARD;
00276 
00277 discard:
00278     msp_spinlock_unlock(&svc_set_lock);
00279     return MSVCS_ST_PKT_DISCARD;
00280 }
00281 
00285 static void
00286 session_close (void)
00287 {
00288     ssn_f_action_t *f_action = NULL;
00289     ssn_r_action_t *r_action = NULL;
00290     sp_svc_set_t *ss;
00291     msp_policy_db_params_t policy_db_params;
00292 
00293     /* Get and free attached actions. */
00294     msvcs_session_get_ext_handle((msvcs_session_t *)data_ctx->sc_session,
00295             (uint8_t)classify_pid, (void **)&f_action, (void **)&r_action);
00296 
00297     free(f_action);
00298     free(r_action);
00299 
00300     msp_spinlock_lock(&svc_set_lock);
00301 
00302     /* Get inactive service-set. */
00303     ss = get_svc_set(data_ctx->sc_sset_id, false);
00304     if (ss == NULL) {
00305         /* No inactive service-set, get active service-set and decrement
00306          * session counter.
00307          */
00308         ss = get_svc_set(data_ctx->sc_sset_id, true);
00309         if (ss == NULL) {
00310             msp_log(LOG_ERR, "%s: No active service-set!", __func__);
00311             goto done;
00312         }
00313         ss->ss_ssn_count--;
00314         goto done;
00315     }
00316 
00317     /* Inactive service-set exists, this session must belong to it. */
00318     ss->ss_ssn_count--;
00319     if (ss->ss_ssn_count == 0) {
00320 
00321         /* No session is using this service-set, detach policy from
00322          * policy-db, free policy and delete service-set.
00323          */
00324         bzero(&policy_db_params, sizeof(msp_policy_db_params_t));
00325         policy_db_params.handle = ctrl_ctx->policy_db_handle;
00326         policy_db_params.svc_set_id = ss->ss_policy->ss_svc_id;
00327         policy_db_params.svc_id = ss->ss_policy->ss_svc_id;
00328         policy_db_params.plugin_id = classify_pid;
00329         strlcpy(policy_db_params.plugin_name, EQ2_CLASSIFY_SVC_NAME,
00330                 sizeof(policy_db_params.plugin_name));
00331         policy_db_params.policy_op = MSP_POLICY_DB_POLICY_DEL;
00332         policy_db_params.op.del_params.gen_num = ss->ss_policy->ss_gen_num;
00333         if (msp_policy_db_op(&policy_db_params) != MSP_OK) {
00334             msp_log(LOG_ERR, "%s: Policy operation %d ERROR!",
00335                     __func__, policy_db_params.policy_op);
00336         }
00337         del_svc_set(ss);
00338 
00339         /* Check active service-set. */
00340         ss = get_svc_set(data_ctx->sc_sset_id, true);
00341         if (ss == NULL) {
00342             goto done;
00343         }
00344 
00345         /* Active service-set exists, add policy to policy-db,
00346          * then packet handler will accept new session and apply new policy.
00347          */
00348         bzero(&policy_db_params, sizeof(msp_policy_db_params_t));
00349         policy_db_params.handle = ctrl_ctx->policy_db_handle;
00350         policy_db_params.svc_set_id = ss->ss_policy->ss_svc_id;
00351         policy_db_params.svc_id = ss->ss_policy->ss_svc_id;
00352         policy_db_params.plugin_id = classify_pid;
00353         strlcpy(policy_db_params.plugin_name, EQ2_CLASSIFY_SVC_NAME,
00354                 sizeof(policy_db_params.plugin_name));
00355         policy_db_params.policy_op = MSP_POLICY_DB_POLICY_ADD;
00356         policy_db_params.op.add_params.gen_num = ss->ss_policy->ss_gen_num;
00357         policy_db_params.op.add_params.policy = ss->ss_policy;
00358         if (msp_policy_db_op(&policy_db_params) != MSP_OK) {
00359             msp_log(LOG_ERR, "%s: Policy operation %d ERROR!",
00360                     __func__, policy_db_params.policy_op);
00361             del_svc_set(ss);
00362         }
00363     }
00364 
00365 done:
00366     msp_spinlock_unlock(&svc_set_lock);
00367     return;
00368 }
00369 
00382 int
00383 equilibrium2_classify_data_hdlr (msvcs_data_context_t *ctx,
00384         msvcs_data_event_t ev)
00385 {
00386     msvcs_data_event_t data_ev;
00387     msvcs_pub_data_req_t *pub_data_req;
00388 
00389     data_ctx = ctx;
00390 
00391     switch (ev) {
00392     case MSVCS_DATA_EV_SM_INIT:
00393         msp_log(LOG_INFO, "%s: MSVCS_DATA_EV_SM_INIT", __func__);
00394         break;
00395 
00396     case MSVCS_DATA_EV_INIT:
00397         msp_log(LOG_INFO, "%s: MSVCS_DATA_EV_INIT", __func__);
00398         break;
00399 
00400     case MSVCS_DATA_EV_FIRST_PKT_PROC:
00401         msp_log(LOG_INFO, "%s: MSVCS_DATA_EV_FIRST_PKT_PROC", __func__);
00402         data_ev = MSVCS_EV_SET_EVENT(classify_ev_class,
00403                 EV_CLASSIFY_FIRST_PACKET);
00404         msvcs_plugin_dispatch_data_event(data_ev, "first packet",
00405                 EQ2_BALANCE_SVC_NAME, MSVCS_EVENT_MODE_SYNC, classify_pid,
00406                 NULL, NULL);
00407         first_pkt_proc();
00408         return take_action();
00409         break;
00410 
00411     case MSVCS_DATA_EV_PKT_PROC:
00412         msp_log(LOG_INFO, "%s: MSVCS_DATA_EV_PKT_PROC", __func__);
00413         return take_action();
00414         break;
00415 
00416     case MSVCS_DATA_EV_SESSION_OPEN:
00417         msp_log(LOG_INFO, "%s: MSVCS_DATA_EV_SESSION_OPEN", __func__);
00418         break;
00419 
00420     case MSVCS_DATA_EV_SESSION_CLOSE:
00421         msp_log(LOG_INFO, "%s: MSVCS_DATA_EV_SESSION_CLOSE", __func__);
00422         session_close();
00423         break;
00424 
00425     case MSVCS_DATA_EV_SESSION_DESTROY:
00426         msp_log(LOG_INFO, "%s: MSVCS_DATA_EV_SESSION_DESTROY", __func__);
00427         break;
00428 
00429     case MSVCS_DATA_EV_REQ_PUB_DATA:
00430         pub_data_req = ctx->plugin_data;
00431 
00432         msp_log(LOG_INFO, "%02d %s: MSVCS_DATA_EV_REQ_PUB_DATA %d",
00433                 msvcs_state_get_cpuid(), __func__, pub_data_req->data_id);
00434         if (pub_data_req->data_id == EQ2_CLASSIFY_PUB_DATA_LUCKY_NUM) {
00435             pub_data_req->err = 0;
00436             *(int *)pub_data_req->data = *(int *)pub_data_req->param;
00437         }
00438         break;
00439 
00440     default:
00441         msp_log(LOG_ERR, "%s: Unknown event!", __func__);
00442     }
00443     return MSVCS_ST_OK;
00444 }
00445 

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:27:08 2010 for SDK Your Net Corporation Equilibrium II: equilibrium2-classify 1.0 by Doxygen 1.5.1