equilibrium2-balance_data.c

Go to the documentation of this file.
00001 /*
00002  * $Id: equilibrium2-balance_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-balance.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 
00130 static svr_addr_t *
00131 get_svr_addr (char *name)
00132 {
00133     svr_group_t *group;
00134     svr_addr_t *addr;
00135     svr_addr_t *min_addr = NULL;
00136     uint32_t min_count;
00137 
00138     LIST_FOREACH(group, svr_group_head, entry) {
00139         if (strcmp(group->group_name, name) != 0) {
00140             continue;
00141         }
00142 
00143         /* Preset the maximum value of uint32_t to get the minimum count. */
00144         min_count = 0xFFFFFFFF;
00145         min_addr = NULL;
00146         LIST_FOREACH(addr, &group->group_addr_head, entry) {
00147             if (addr->addr_ssn_count < min_count) {
00148                 min_count = addr->addr_ssn_count;
00149                 min_addr = addr;
00150             }
00151         }
00152         if (min_addr) {
00153             min_addr->addr_ssn_count++;
00154         }
00155         break;
00156     }
00157     return min_addr;
00158 }
00159 
00167 static int
00168 take_action (void)
00169 {
00170     ssn_f_action_t *f_action = NULL;
00171     ssn_r_action_t *r_action = NULL;
00172     struct jbuf *jb = (struct jbuf *)data_ctx->sc_pkt;
00173     struct ip *ip_hdr = jbuf_to_d(jb, struct ip *);
00174     struct tcphdr *tcp_hdr;
00175 
00176     tcp_hdr = (struct tcphdr *)(jbuf_to_d(jb, char *) + ip_hdr->ip_hl * 4);
00177 
00178     /* Get session action. */
00179     msvcs_session_get_ext_handle((msvcs_session_t *)data_ctx->sc_session,
00180             (uint8_t)balance_pid, (void **)&f_action, (void **)&r_action);
00181 
00182     if (jbuf_to_svcs_hdr(jb, struct jbuf_svcs_hdr).jb_svcs_hdr_flags &
00183             JBUF_SVCS_FLAG_DIR_FORWARD) {
00184         if (f_action) {
00185             msp_log(LOG_INFO, "%s: Forward action %x -> %x", __func__,
00186                     ip_hdr->ip_dst.s_addr, f_action->svr_addr->addr);
00187             ip_hdr->ip_dst.s_addr = f_action->svr_addr->addr;
00188 
00189             /* Recalculate IP header checksum. */
00190             ip_hdr->ip_sum = 0;
00191             ip_hdr->ip_sum = ip_cksum(ip_hdr, ip_hdr->ip_hl * 4);
00192 
00193             /* Recalculate TCP checksum. */
00194             tcp_hdr->th_sum = 0;
00195             tcp_hdr->th_sum = tcp_cksum(ip_hdr->ip_len - ip_hdr->ip_hl * 4,
00196                     &ip_hdr->ip_src.s_addr, &ip_hdr->ip_dst.s_addr, tcp_hdr);
00197         } else {
00198             msp_log(LOG_INFO, "%s: No action for forward flow!", __func__);
00199         }
00200     } else {
00201         if (r_action) {
00202             msp_log(LOG_INFO, "%s: Reverse action %x -> %x", __func__,
00203                     ip_hdr->ip_src.s_addr, r_action->addr);
00204             ip_hdr->ip_src.s_addr = r_action->addr;
00205 
00206             /* Recalculate IP header checksum. */
00207             ip_hdr->ip_sum = 0;
00208             ip_hdr->ip_sum = ip_cksum(ip_hdr, ip_hdr->ip_hl * 4);
00209 
00210             /* Recalculate TCP checksum. */
00211             tcp_hdr->th_sum = 0;
00212             tcp_hdr->th_sum = tcp_cksum(ip_hdr->ip_len - ip_hdr->ip_hl * 4,
00213                     &ip_hdr->ip_src.s_addr, &ip_hdr->ip_dst.s_addr, tcp_hdr);
00214         } else {
00215             msp_log(LOG_INFO, "%s: No action for reversed flow!", __func__);
00216         }
00217     }
00218 
00219     return MSVCS_ST_PKT_FORWARD;
00220 }
00221 
00229 static int
00230 first_pkt_proc (void)
00231 {
00232     struct jbuf *jb = (struct jbuf *)data_ctx->sc_pkt;
00233     struct ip *ip_hdr;
00234     blob_svc_set_t *policy;
00235     blob_rule_t *rule;
00236     blob_term_t *term;
00237     svr_addr_t *addr = NULL;
00238     ssn_f_action_t *f_action;
00239     ssn_r_action_t *r_action;
00240     sp_svc_set_t *ss;
00241     int i, j;
00242 
00243     ip_hdr = jbuf_to_d(jb, struct ip *);
00244 
00245     /* Lock service-set till the end of first packet process,
00246      * cause session counter may be updated at the end.
00247      */
00248     msp_spinlock_lock(&svc_set_lock);
00249 
00250     /* If there is an inactive service-set policy, don't accept any new
00251      * session.
00252      */     
00253     if (get_svc_set(data_ctx->sc_sset_id, FALSE)) {
00254         msp_log(LOG_INFO, "%s: Inactive policy exists!", __func__);
00255         goto discard;
00256     }
00257 
00258     /* Get the active service-set policy. */
00259     ss = get_svc_set(data_ctx->sc_sset_id, TRUE);
00260     if (ss == NULL) {
00261         msp_log(LOG_ERR, "%s: No service set!", __func__);
00262         goto discard;
00263     }   
00264  
00265     policy = ss->ss_policy;
00266     if (policy == NULL) {
00267         msp_log(LOG_ERR, "%s: No policy!", __func__);
00268         goto discard;
00269     }
00270 
00271     /* Go through all rules to this service set and create action list.
00272      * Only one rule/action is supported for now.
00273      */
00274     rule = policy->ss_rule;
00275     for (i = 0; i < policy->ss_rule_count; i++) {
00276         term = rule->rule_term;
00277         for (j = 0; j < rule->rule_term_count; j++) {
00278             if (term->term_match_id == TERM_FROM_SVC_GATE) {
00279                 if (ip_hdr->ip_dst.s_addr == term->term_match_addr) {
00280                     msp_spinlock_lock(&svr_group_lock);
00281                     addr = get_svr_addr(term->term_act_group_name);
00282                     msp_spinlock_unlock(&svr_group_lock);
00283                     break;
00284                 }
00285             }
00286             term++;
00287         }
00288         rule = (blob_rule_t *)term;
00289     }
00290 
00291     /* Create action and attach it to the session. */
00292     if (addr) {
00293         /* Only one action (rule) for each direction is supported for now. */
00294         f_action = msp_shm_alloc(data_ctx->sc_shm, sizeof(ssn_f_action_t));
00295         INSIST_ERR(f_action != NULL);
00296 
00297         /* Change destination address to service gate address. */
00298         f_action->svr_addr = addr;
00299 
00300         r_action = msp_shm_alloc(data_ctx->sc_shm, sizeof(ssn_r_action_t));
00301         INSIST_ERR(r_action != NULL);
00302 
00303         /* Save the destination address as reverse path source address. */
00304         r_action->addr = ip_hdr->ip_dst.s_addr;
00305 
00306         msvcs_session_set_ext_handle((msvcs_session_t *)data_ctx->sc_session,
00307                 (uint8_t)balance_pid, f_action, r_action);
00308         ss->ss_ssn_count++;
00309         msp_log(LOG_INFO, "%s: Forward action %x is created.", __func__, addr);
00310         msp_log(LOG_INFO, "%s: Reverse action %x is created.", __func__,
00311                 ip_hdr->ip_dst.s_addr);
00312     }
00313     msp_spinlock_unlock(&svc_set_lock);
00314     return MSVCS_ST_PKT_FORWARD;
00315 
00316 discard:
00317     msp_spinlock_unlock(&svc_set_lock);
00318     return MSVCS_ST_PKT_DISCARD;
00319 }
00320 
00325 static void
00326 session_close (void)
00327 {
00328     ssn_f_action_t *f_action = NULL;
00329     ssn_r_action_t *r_action = NULL;
00330     sp_svc_set_t *ss;
00331     msp_policy_db_params_t policy_db_params;
00332 
00333     /* Get and free attached actions. */
00334     msvcs_session_get_ext_handle((msvcs_session_t *)data_ctx->sc_session,
00335             (uint8_t)balance_pid, (void **)&f_action, (void **)&r_action);
00336 
00337     msp_spinlock_lock(&svr_group_lock);
00338     f_action->svr_addr->addr_ssn_count--;
00339     msp_spinlock_unlock(&svr_group_lock);
00340     msp_shm_free(data_ctx->sc_shm, f_action);
00341     msp_shm_free(data_ctx->sc_shm, r_action);
00342 
00343     msp_spinlock_lock(&svc_set_lock);
00344 
00345     /* Get inactive service-set. */
00346     ss = get_svc_set(data_ctx->sc_sset_id, FALSE);
00347     if (ss == NULL) {
00348         /* No inactive service-set, get active service-set and decrement
00349          * session counter.
00350          */
00351         ss = get_svc_set(data_ctx->sc_sset_id, TRUE);
00352         if (ss == NULL) {
00353             msp_log(LOG_ERR, "%s: No active service-set!", __func__);
00354             return;
00355         }
00356         ss->ss_ssn_count--;
00357         goto done;
00358     }
00359 
00360     /* Inactive service-set exists, this session must belong to it. */
00361     ss->ss_ssn_count--;
00362     if (ss->ss_ssn_count == 0) {
00363 
00364         /* No session is using this service-set, detach policy from
00365          * policy-db, free policy and delete service-set.
00366          */
00367         bzero(&policy_db_params, sizeof(msp_policy_db_params_t));
00368         policy_db_params.handle = ctrl_ctx->policy_db_handle;
00369         policy_db_params.svc_set_id = ss->ss_policy->ss_svc_id;
00370         policy_db_params.svc_id = ss->ss_policy->ss_svc_id;
00371         policy_db_params.plugin_id = balance_pid;
00372         strlcpy(policy_db_params.plugin_name, EQ2_BALANCE_SVC_NAME,
00373                 sizeof(policy_db_params.plugin_name));
00374         policy_db_params.policy_op = MSP_POLICY_DB_POLICY_DEL;
00375         policy_db_params.op.del_params.gen_num = ss->ss_policy->ss_gen_num;
00376         if (msp_policy_db_op(&policy_db_params) != MSP_OK) {
00377             msp_log(LOG_ERR, "%s: Policy operation %d ERROR!",
00378                     __func__, policy_db_params.policy_op);
00379         }
00380         del_svc_set(ss);
00381 
00382         /* Check active service-set. */
00383         ss = get_svc_set(data_ctx->sc_sset_id, TRUE);
00384         if (ss == NULL) {
00385             goto done;
00386         }
00387 
00388         /* Active service-set exists, add policy to policy-db,
00389          * then packet handler will accept new session and apply new policy.
00390          */
00391         bzero(&policy_db_params, sizeof(msp_policy_db_params_t));
00392         policy_db_params.handle = ctrl_ctx->policy_db_handle;
00393         policy_db_params.svc_set_id = ss->ss_policy->ss_svc_id;
00394         policy_db_params.svc_id = ss->ss_policy->ss_svc_id;
00395         policy_db_params.plugin_id = balance_pid;
00396         strlcpy(policy_db_params.plugin_name, EQ2_CLASSIFY_SVC_NAME,
00397                 sizeof(policy_db_params.plugin_name));
00398         policy_db_params.policy_op = MSP_POLICY_DB_POLICY_ADD;
00399         policy_db_params.op.add_params.gen_num = ss->ss_policy->ss_gen_num;
00400         policy_db_params.op.add_params.policy = ss->ss_policy;
00401         if (msp_policy_db_op(&policy_db_params) != MSP_OK) {
00402             msp_log(LOG_ERR, "%s: Policy operation %d ERROR!",
00403                     __func__, policy_db_params.policy_op);
00404             del_svc_set(ss);
00405         }
00406     }
00407 
00408 done:
00409     msp_spinlock_unlock(&svc_set_lock);
00410     return;
00411 }
00412 
00426 int
00427 equilibrium2_balance_data_hdlr (msvcs_data_context_t *ctx,
00428         msvcs_data_event_t ev)
00429 {
00430     msvcs_pub_data_req_t pub_data_req;
00431     int param;
00432     int data;
00433 
00434     data_ctx = ctx;
00435 
00436     switch (ev) {
00437     case MSVCS_DATA_EV_SM_INIT:
00438         msp_log(LOG_INFO, "%s: MSVCS_DATA_EV_SM_INIT", __func__);
00439         break;
00440 
00441     case MSVCS_DATA_EV_INIT:
00442         msp_log(LOG_INFO, "%s: MSVCS_DATA_EV_INIT", __func__);
00443         break;
00444 
00445     case MSVCS_DATA_EV_FIRST_PKT_PROC:
00446         msp_log(LOG_INFO, "%s: MSVCS_DATA_EV_FIRST_PKT_PROC", __func__);
00447         param = EQ2_LUCKY_NUM;
00448         data = 0;
00449         pub_data_req.data_id = EQ2_CLASSIFY_PUB_DATA_LUCKY_NUM;
00450         pub_data_req.err = -1;
00451         pub_data_req.param = &param;
00452         pub_data_req.data = &data;
00453         msvcs_plugin_public_data_get(EQ2_CLASSIFY_SVC_NAME, &pub_data_req);
00454         msp_log(LOG_INFO, "%02d %s: data %d error %d", msvcs_state_get_cpuid(),
00455                 __func__, data, pub_data_req.err);
00456 
00457         first_pkt_proc();
00458         return take_action();
00459         break;
00460 
00461     case MSVCS_DATA_EV_PKT_PROC:
00462         msp_log(LOG_INFO, "%s: MSVCS_DATA_EV_PKT_PROC", __func__);
00463         return take_action();
00464         break;
00465 
00466     case MSVCS_DATA_EV_SESSION_OPEN:
00467         msp_log(LOG_INFO, "%s: MSVCS_DATA_EV_SESSION_OPEN", __func__);
00468         break;
00469 
00470     case MSVCS_DATA_EV_SESSION_CLOSE:
00471         msp_log(LOG_INFO, "%s: MSVCS_DATA_EV_SESSION_CLOSE", __func__);
00472         session_close();
00473         break;
00474 
00475     case MSVCS_DATA_EV_SESSION_DESTROY:
00476         msp_log(LOG_INFO, "%s: MSVCS_DATA_EV_SESSION_DESTROY", __func__);
00477         break;
00478 
00479     default:
00480         if (MSVCS_EV_GET_EVENT_CLASS(ev) == classify_ev_class) {
00481             if (MSVCS_EV_GET_EVENT_TYPE(ev) == EV_CLASSIFY_FIRST_PACKET) {
00482                 msp_log(LOG_INFO, "%02d %s: Event EV_CLASSIFY_FIRST_PACKET %s",
00483                         msvcs_state_get_cpuid(), __func__, ctx->plugin_data);
00484             }
00485         } else {
00486             msp_log(LOG_ERR, "%02d %s: Unknown event 0x%08x!",
00487                     msvcs_state_get_cpuid(), __func__, ev);
00488         }
00489     }
00490     return MSVCS_ST_OK;
00491 }
00492 

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-balance 1.0 by Doxygen 1.5.1