ped_ssd.c

Go to the documentation of this file.
00001 /*
00002  * $Id: ped_ssd.c 366303 2010-03-05 13:14:01Z taoliu $
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) 2007-2008, Juniper Networks, Inc.
00011  * All rights reserved.
00012  */
00013 
00022 #include <sync/common.h>
00023 #include <jnx/ssd_ipc.h>
00024 #include <jnx/ssd_ipc_msg.h>
00025 #include <limits.h>
00026 #include "ped_ssd.h"
00027 
00028 #include PE_OUT_H
00029 #include PE_SEQUENCE_H
00030 
00031 /*
00032  * README:
00033  * 
00034  * Interacting with SSD to add/remove route involves FIVE 
00035  * setup steps noted in the code below as STEP #0 - 4
00036  */
00037 
00038 
00039 /*** Constants ***/
00040 
00041 #define RT_TBL_NAME         "inet.0" 
00042 
00043 
00046 #define REQUESTS_BUFFER_SIZE 64
00047 
00052 #define UNCONFIRMED_CONTEXT  REQUESTS_BUFFER_SIZE
00053 
00057 #define MAX_UNCONFIRMED_CONTEXT  UINT_MAX
00058 
00062 #define RETRY_CONNECT 60
00063 
00064 /*** Data structures ***/
00065 
00066 
00067 static boolean ssd_ready = FALSE;   
00068 static int ssd_server_fd = -1;      
00069 static int client_id = 0;           
00070 static uint32_t rt_tbl_id = 0;     
00071 static evTimerID  timer_id;          
00072 
00073 // Need these forward declarations for ssd_client_ft, the function table:
00074 
00075 static int ssd_client_connection(int fd);
00076 static void ssd_client_connection_close(int fd, int cause);
00077 static void ssd_client_msg(int fd, struct ssd_ipc_msg *cmsg);
00078 
00082 static struct ssd_ipc_ft ssd_client_ft = {
00083     ssd_client_connection,           // init connection handler
00084     ssd_client_connection_close,     // close connection handler
00085     ssd_client_msg                   // message handler
00086 };
00087 
00088 extern evContext ped_ctx;   
00089 
00094 typedef struct {
00095     ssd_reply_notification_handler reply_handler; 
00096     void * user_data;   
00097 } ssd_request_t;
00098 
00099 static ssd_request_t ssd_requests[REQUESTS_BUFFER_SIZE]; 
00100 static uint32_t next_buffer = 0; 
00101 static uint32_t next_unconfirmed = UNCONFIRMED_CONTEXT; 
00102 static int outstanding_requests = 0; 
00103 
00104 
00105 /*** STATIC/INTERNAL Functions ***/
00106 
00107 
00127 static void
00128 connect_ssd(evContext ctx __unused,
00129             void * uap  __unused,
00130             struct timespec due __unused,
00131             struct timespec inter __unused)
00132 {
00133     int rt_table_id;
00134 
00135     if(ssd_server_fd >= 0) {
00136         return;
00137     }
00138 
00139     // STEP #0 
00140 
00141     rt_table_id = ssd_get_routing_instance();
00142     ssd_server_fd = ssd_ipc_connect_rt_tbl(NULL, &ssd_client_ft,
00143                                      rt_table_id, ped_ctx);
00144     
00145     if (ssd_server_fd < 0) {
00146         ERRMSG(PED, TRACE_LOG_ERR,
00147                 "%s: Opening socket to SSD failed! Will retry.", __func__);
00148         return;
00149     }
00150     
00151     evClearTimer(ped_ctx, timer_id);
00152     
00153     junos_trace(PED_TRACEFLAG_ROUTING, "%s: Connected to SSD", __func__);
00154 }
00155 
00156 
00161 static int
00162 ssd_client_connection(int fd)
00163 {
00164     // STEP #0 (finished)
00165     
00166     if(ssd_get_client_id(fd, 0) < 0) {  // STEP #1
00167         ERRMSG(PED, TRACE_LOG_ERR,
00168             "%s: Error requesting client ID from SSD %m",
00169             __func__);
00170         
00171         return -1;
00172     }
00173 
00174     junos_trace(PED_TRACEFLAG_ROUTING,
00175             "%s: SSD connected.", __func__);
00176     
00177     return SUCCESS;
00178 }
00179 
00180 
00190 static void
00191 ssd_client_connection_close(int fd __unused, int cause __unused)
00192 {
00193     ssd_server_fd = -1;
00194     ssd_ready = FALSE;
00195     
00196     /* TRY: RE-CONNECT
00197      * Set the SSD connect retry timer:
00198      * immediate one-shot event now, and periodocally afterward every 
00199      * RETRY_CONNECT seconds
00200      * 
00201      * calls connect_ssd()
00202      */
00203     if(evSetTimer(ped_ctx, connect_ssd, NULL, evNowTime(),
00204         evConsTime(RETRY_CONNECT, 0), &timer_id)) {
00205 
00206         ERRMSG(PED, TRACE_LOG_ERR,
00207                 "%s: evSetTimer() FAILED! Will not be able to connect "
00208                 "to the SSD", __func__);
00209     }
00210     
00211     junos_trace(PED_TRACEFLAG_ROUTING,
00212             "%s: SSD disconnected.", __func__);
00213 
00214     junos_trace(PED_TRACEFLAG_ROUTING, 
00215         "PED's SSD module is NOT accepting "
00216         "route add/delete requests");
00217 }
00218 
00219 
00229 static void
00230 ssd_client_msg (int fd, struct ssd_ipc_msg * cmsg)
00231 {
00232     char * rt_tb_name = NULL;
00233     unsigned int context;
00234     
00235     switch (cmsg->ssd_ipc_cmd) {
00236 
00237     case SSD_SESSION_ID_REPLY:
00238     
00239         if(SSD_SESSION_ID_REPLY_CHECK_STATUS(cmsg)) {
00240             
00241             client_id = SSD_SESSION_ID_REPLY_GET_CLIENT_ID(cmsg); // STEP #1 (finished)
00242             
00243             junos_trace(PED_TRACEFLAG_ROUTING, 
00244                     "%s: Received client id from SSD : %u",
00245                     __func__, client_id);
00246             
00247             // Requesting route service setup...
00248             
00249             if(ssd_setup_route_service(fd) < 0) {  // STEP #2
00250                 ERRMSG(PED, TRACE_LOG_ERR, "%s: Error requesting route "
00251                     "service setup from SSD %m", __func__);
00252             }
00253         } else {
00254             ERRMSG(PED, TRACE_LOG_ERR,
00255                 "%s: Error getting client ID from SSD", __func__);
00256         }
00257         break;
00258         
00259     case SSD_ROUTE_SERVICE_REPLY:
00260     
00261         if(SSD_ROUTE_SERVICE_REPLY_CHECK_STATUS(cmsg)) {
00262             
00263             rt_tb_name = strdup(RT_TBL_NAME); // STEP #2 (finished)
00264             INSIST(rt_tb_name != NULL); // errno=ENOMEM if this fails
00265             
00266             junos_trace(PED_TRACEFLAG_ROUTING,
00267                 "%s: Route service has been setup properly",
00268                  __func__);
00269                  
00270             // Requesting for a route table id...
00271             
00272             if(ssd_request_route_table_lookup(
00273                 fd, rt_tb_name, 0) < 0) {  // STEP #3
00274 
00275                 ERRMSG(PED, TRACE_LOG_ERR, "%s: Error requesting route "
00276                     "table lookup from SSD %m", __func__);
00277             }
00278         } else {
00279             ERRMSG(PED, TRACE_LOG_ERR,
00280                 "%s: Error setting up route service with SSD", __func__);
00281         }
00282         break;
00283         
00284     case SSD_ROUTE_TABLE_LOOKUP_REPLY:
00285     
00286         if(SSD_ROUTE_TABLE_LOOKUP_REPLY_CHECK_STATUS(cmsg)) {
00287             
00288             rt_tbl_id = SSD_ROUTE_TABLE_LOOKUP_REPLY_GET_RTTID(cmsg); // STEP #3 (finished)
00289             
00290             junos_trace(PED_TRACEFLAG_ROUTING, 
00291                 "%s: Route table is found id %u",
00292                 __func__, rt_tbl_id);
00293             
00294             // Our SSD module is ready to accept route add/delete requests
00295             
00296             ssd_ready = TRUE;                     // STEP #4
00297             
00298             junos_trace(PED_TRACEFLAG_ROUTING, 
00299                 "PED's SSD module is ready to accept "
00300                 "route add/delete requests");
00301         } else {
00302             ERRMSG(PED, TRACE_LOG_ERR, 
00303                 "%s: Error getting route table from SSD %d",
00304                 __func__, SSD_ROUTE_TABLE_LOOKUP_REPLY_GET_ERROR_CODE(cmsg));
00305         }
00306         break;
00307         
00308     case SSD_ROUTE_ADD_REPLY:
00309 
00310         context = SSD_ROUTE_ADD_REPLY_GET_CLIENT_CTX(cmsg);
00311         
00312         // we only have issued contexts in this range
00313         INSIST(context < REQUESTS_BUFFER_SIZE);
00314                 
00315         if(SSD_ROUTE_ADD_REPLY_CHECK_STATUS(cmsg)) {
00316             junos_trace(PED_TRACEFLAG_ROUTING, 
00317                     "%s: Route add success", __func__);
00318                     
00319             ssd_requests[context].reply_handler(
00320                 ADD_SUCCESS, ssd_requests[context].user_data);
00321             
00322         } else {
00323             junos_trace(PED_TRACEFLAG_ROUTING, 
00324                     "%s: Route add failed", __func__);
00325                     
00326             ssd_requests[context].reply_handler(
00327                 ADD_FAILED, ssd_requests[context].user_data);
00328         }
00329         
00330         // free up this request buffer
00331         ssd_requests[context].reply_handler = NULL;
00332         ssd_requests[context].user_data = NULL;
00333         --outstanding_requests;
00334         
00335         break;
00336         
00337     case SSD_ROUTE_DELETE_REPLY:
00338     
00339         context = SSD_ROUTE_DELETE_REPLY_GET_CLIENT_CTX(cmsg);
00340     
00341         if(SSD_ROUTE_DELETE_REPLY_CHECK_STATUS(cmsg)) {
00342 
00343             if(context < REQUESTS_BUFFER_SIZE) { // gotta confirm
00344                 
00345                 junos_trace(PED_TRACEFLAG_ROUTING, "%s: Route delete success "
00346                     "(with confirmation)", __func__);
00347                 
00348                 // call confirmation handler
00349                 ssd_requests[context].reply_handler(
00350                     DELETE_SUCCESS, ssd_requests[context].user_data);
00351                     
00352                 // free up this request buffer
00353                 ssd_requests[context].reply_handler = NULL;
00354                 ssd_requests[context].user_data = NULL;
00355                 --outstanding_requests;
00356                 
00357             } else {
00358                 junos_trace(PED_TRACEFLAG_ROUTING, "%s: Route delete success "
00359                     "(without confirmation)", __func__);                
00360             }
00361         } else {
00362             if(context < REQUESTS_BUFFER_SIZE) { // gotta confirm
00363                 
00364                 junos_trace(PED_TRACEFLAG_ROUTING, "%s: Route delete failed "
00365                     "(with confirmation)", __func__);                
00366                 
00367                 // call confirmation handler
00368                 ssd_requests[context].reply_handler(
00369                     DELETE_FAILED, ssd_requests[context].user_data);
00370                     
00371                 // free up this request buffer
00372                 ssd_requests[context].reply_handler = NULL;
00373                 ssd_requests[context].user_data = NULL;
00374                 --outstanding_requests;
00375                 
00376             } else {
00377                 ERRMSG(PED, TRACE_LOG_ERR, 
00378                     "%s: Route delete failed (without confirmation)."
00379                     "WARNING: dangling route.", __func__);
00380             }
00381         }
00382         
00383         break;
00384         
00385     case SSD_ROUTE_SERVICE_CLEAN_UP_REPLY:
00386         // only issued clean-up while shutting down anyway
00387         break;
00388         
00389     default:
00390     
00391         ERRMSG(PED, TRACE_LOG_ERR, "%s: Unknown message type %d",
00392             __func__, cmsg->ssd_ipc_args[0]);
00393             
00394     }
00395 }
00396 
00397 
00410 static int
00411 ssd_client_ifa_handler(kcom_ifa_t * msg, void * user_info )
00412 {
00413     policy_route_msg_t *route = (policy_route_msg_t *)user_info;
00414     ssd_sockaddr_un route_addr;
00415     ssd_sockaddr_un route_nh;
00416     ssd_sockaddr_un route_local;
00417     struct ssd_route_parms rtp;
00418     struct in_addr  addr;
00419 
00420     // Initialize the information for route add
00421     
00422     bzero(&route_addr, sizeof(route_addr));
00423     ssd_setsocktype(&route_addr, SSD_GF_INET);
00424     route_addr.in.gin_addr = route->route_addr;
00425 
00426     bzero(&route_nh, sizeof(route_nh));
00427     ssd_setsocktype(&route_nh, SSD_GF_INET);
00428     route_nh.in.gin_addr = route->nh_addr;
00429 
00430     bzero(&route_local, sizeof(route_local));
00431     ssd_setsocktype(&route_local, SSD_GF_INET);
00432     route_local.in.gin_addr = *(in_addr_t *)(msg->ifa_lprefix);
00433 
00434     // Setup route parameters for SSD
00435     
00436     bzero(&rtp, sizeof(rtp));
00437     rtp.rta_dest = &route_addr;
00438     rtp.rta_prefixlen = route->route_addr_prefix;
00439     
00440     if(route->preferences) {
00441         rtp.rta_preferences.rtm_val[0] = route->preferences;
00442         rtp.rta_preferences.rtm_type[0] = SSD_RTM_VALUE_PRESENT;
00443     }
00444     
00445     if(route->metrics) {
00446         rtp.rta_metrics.rtm_val[0] = route->metrics;
00447         rtp.rta_metrics.rtm_type[0] = SSD_RTM_VALUE_PRESENT;
00448     }
00449     
00450     
00451     rtp.rta_rtt = rt_tbl_id;
00452     rtp.rta_nhtype = route->nh_type;
00453     if(route->nh_addr) {
00454         rtp.rta_n_gw = 1;
00455         rtp.rta_gateway[0].rtg_gwaddr = &route_nh;
00456         rtp.rta_gateway[0].rtg_ifl = msg->ifa_index;
00457         rtp.rta_gateway[0].rtg_lcladdr = &route_local;
00458     }
00459 
00460     addr.s_addr = route->route_addr;
00461     
00462     junos_trace(PED_TRACEFLAG_ROUTING,
00463             "%s: route address: %s/%d", __func__,
00464             inet_ntoa(addr), route->route_addr_prefix);
00465 
00466     addr.s_addr = *(in_addr_t *)(msg->ifa_lprefix);
00467     
00468     junos_trace(PED_TRACEFLAG_ROUTING,
00469             "%s: local address: %s, ifl: %d", __func__,
00470             inet_ntoa(addr), msg->ifa_index);
00471             
00472     addr.s_addr = route->nh_addr;
00473     
00474     junos_trace(PED_TRACEFLAG_ROUTING,
00475             "%s: nh: %s, m: %d, p: %d", __func__,
00476             inet_ntoa(addr), route->metrics, route->preferences);
00477 
00478     // Add the route
00479     if(ssd_request_route_add(ssd_server_fd, &rtp, next_buffer) < 0) {
00480 
00481         ERRMSG(PED, TRACE_LOG_ERR,
00482             "%s: Error requesting route add from SSD: %m", __func__);
00483         
00484         junos_kcom_msg_free(msg);
00485         
00486         return 1; // not SUCCESS
00487     }
00488     
00489     junos_kcom_msg_free(msg);
00490     
00491     return SUCCESS;
00492 }
00493 
00494 
00495 /*** GLOBAL/EXTERNAL Functions ***/
00496 
00497 
00501 void
00502 ped_ssd_init(void)
00503 {
00504     int i = 0;
00505     
00506     ssd_server_fd = -1;
00507     client_id = 0;
00508     rt_tbl_id = 0;
00509     next_buffer = 0;
00510     next_unconfirmed = UNCONFIRMED_CONTEXT;
00511     outstanding_requests = 0;
00512     
00513     for(; i < REQUESTS_BUFFER_SIZE; ++i) {
00514         ssd_requests[i].reply_handler = NULL;
00515         ssd_requests[i].user_data = NULL;        
00516     }
00517     
00518     /*
00519      * Set the SSD connect retry timer:
00520      * immediate one-shot event now, and periodocally afterward every 
00521      * RETRY_CONNECT seconds
00522      * 
00523      * calls connect_ssd()
00524      */
00525     if(evSetTimer(ped_ctx, connect_ssd, NULL, evNowTime(),
00526         evConsTime(RETRY_CONNECT, 0), &timer_id)) {
00527 
00528         ERRMSG(PED, TRACE_LOG_ERR,
00529                 "%s: evSetTimer() FAILED! Will not be able to connect "
00530                 "to the SSD", __func__);
00531     }
00532 }
00533 
00534 
00538 void
00539 ped_ssd_shutdown(void)
00540 {
00541     if(ssd_server_fd != -1) {
00542         ssd_ipc_close(ssd_server_fd);
00543     }
00544 }
00545 
00546 
00553 boolean
00554 get_ssd_ready(void)
00555 {
00556     return ssd_ready;
00557 }
00558 
00559 
00567 boolean
00568 get_ssd_idle(void)
00569 {
00570     return outstanding_requests < 1; // should be zero obviously
00571 }
00572 
00573 
00590 boolean
00591 ssd_client_add_route_request(
00592         policy_route_msg_t *route,
00593         ssd_reply_notification_handler func,
00594         void * user_data)
00595 {
00596     kcom_ifl_t ifl;
00597     char * dot;
00598     if_subunit_t unit = -1;
00599     long tmp;
00600     int rc;
00601     
00602     INSIST(route != NULL);
00603     INSIST(ssd_ready);
00604     INSIST(func != NULL); // adding requires confirmation in our app
00605     
00606     // check if there anything still in this spot of the buffers
00607     if(ssd_requests[next_buffer].reply_handler != NULL) {
00608         
00609         // yes there is
00610         
00611         ERRMSG(PED, TRACE_LOG_WARNING,
00612                 "%s: Warning: PED's ssd module has run "
00613                 "out of space to hold more requests! Either it "
00614                 "is being flooded or SSD responses are very delayed!",
00615                 __func__);
00616                 
00617         return FALSE;
00618     }
00619     
00620     // Add this request in the circular buffer of requests
00621     ssd_requests[next_buffer].reply_handler = func;
00622     ssd_requests[next_buffer].user_data = user_data;
00623 
00624     junos_trace(PED_TRACEFLAG_ROUTING,
00625             "%s: Adding route", __func__);
00626 
00627     // Remove unit number from interface name.
00628     
00629     if((dot = strchr(route->ifname, '.')) != NULL) {
00630         *dot = '\0'; // now terminate here
00631         unit = ((tmp = atol(++dot)) < 1) ? 0 : (if_subunit_t)tmp; // set unit
00632     } else {
00633         unit = 0;
00634     }
00635 
00636     if(junos_kcom_ifl_get_by_name(route->ifname, unit, &ifl)) { // KCOM problem
00637         
00638         ERRMSG(PED, TRACE_LOG_ERR,
00639                 "%s: Get ifl by name FAILED!", __func__);
00640 
00641         ssd_requests[next_buffer].reply_handler = NULL;
00642         ssd_requests[next_buffer].user_data = NULL;
00643 
00644         return FALSE;
00645     }
00646 
00647     if((rc = junos_kcom_ifa_get_all(ssd_client_ifa_handler,
00648                 ifl.ifl_index, route->af, route)) > SUCCESS) {
00649         
00650         ssd_requests[next_buffer].reply_handler = NULL;
00651         ssd_requests[next_buffer].user_data = NULL;
00652 
00653         return FALSE;
00654         
00655     } else if(rc < SUCCESS) { // KCOM problem
00656         
00657         ssd_requests[next_buffer].reply_handler = NULL;
00658         ssd_requests[next_buffer].user_data = NULL;
00659         
00660         ERRMSG(PED, TRACE_LOG_ERR,
00661                 "%s: Could not go through IFAs to add route", __func__);
00662         
00663         return FALSE;        
00664     }
00665 
00666     ++next_buffer;
00667     ++outstanding_requests;
00668     
00669     if(next_buffer >= REQUESTS_BUFFER_SIZE) // wrap around
00670         next_buffer = 0;
00671 
00672     return TRUE;
00673 }
00674 
00675 
00699 boolean
00700 ssd_client_del_route_request(
00701         policy_route_msg_t *route,
00702         ssd_reply_notification_handler func,
00703         void * user_data)
00704 {
00705     ssd_sockaddr_un route_addr;
00706     struct ssd_rt_delete_parms rtp;
00707     struct in_addr  addr;
00708     
00709     INSIST(route != NULL);
00710     INSIST(ssd_ready);
00711     // if func is NULL then user_data must be:
00712     INSIST(func != NULL || user_data == NULL);
00713     
00714     
00715     addr.s_addr = route->route_addr;
00716     
00717     junos_trace(PED_TRACEFLAG_ROUTING,
00718             "%s: deleting route with address: %s/%d", __func__,
00719             inet_ntoa(addr), route->route_addr_prefix);
00720 
00721     bzero(&route_addr, sizeof(route_addr));
00722     ssd_setsocktype(&route_addr, SSD_GF_INET);
00723     route_addr.in.gin_addr = route->route_addr;
00724 
00725     rtp.rtd_dest = &route_addr;
00726     rtp.rtd_prefixlen = route->route_addr_prefix;
00727     rtp.rtd_rtt = rt_tbl_id;
00728     
00729     
00730     if(func != NULL) { //requesting confirmation
00731         
00732         // check if there anything still in this spot of the buffers    
00733         if(ssd_requests[next_buffer].reply_handler != NULL) {
00734         
00735             // yes there is
00736             
00737             ERRMSG(PED, TRACE_LOG_WARNING,
00738                 "%s: Warning: PED's ssd module has run "
00739                 "out of space to hold more requests! Either it "
00740                 "is being flooded or SSD responses are very delayed!",
00741                 __func__);
00742     
00743             return FALSE;
00744         }
00745         
00746         // Add this request in the circular buffer of requests
00747         ssd_requests[next_buffer].reply_handler = func;
00748         ssd_requests[next_buffer].user_data = user_data;
00749         
00750         // send request to libssd
00751         if(ssd_request_route_delete(ssd_server_fd, &rtp, next_buffer)) {
00752             
00753             ERRMSG(PED, TRACE_LOG_ERR,
00754                 "%s: Error requesting route delete from SSD: %m", __func__);
00755     
00756             ssd_requests[next_buffer].reply_handler = NULL;
00757             ssd_requests[next_buffer].user_data = NULL;
00758     
00759             return FALSE;
00760         }
00761     
00762         ++next_buffer;
00763         ++outstanding_requests;
00764         
00765         if(next_buffer >= REQUESTS_BUFFER_SIZE) // wrap around
00766             next_buffer = 0;
00767         
00768     } else {
00769         if(next_unconfirmed >= MAX_UNCONFIRMED_CONTEXT) {
00770             next_unconfirmed = UNCONFIRMED_CONTEXT; // wrap around range of type
00771         }
00772         
00773         if(ssd_request_route_delete(ssd_server_fd, &rtp, next_unconfirmed)) {
00774             
00775             ERRMSG(PED, TRACE_LOG_ERR,
00776                 "%s: Error requesting route delete from SSD: %m", __func__);
00777 
00778             return FALSE;
00779         }
00780     }
00781     
00782     return TRUE;
00783 }
00784 
00785 
00789 void
00790 clean_routes(void)
00791 {
00792     int rc;
00793     
00794     if(ssd_ready) {
00795         junos_trace(PED_TRACEFLAG_ROUTING,
00796             "%s: SSD module is shutting down", __func__);
00797         
00798         rc = ssd_clean_up_route_service(ssd_server_fd, MAX_UNCONFIRMED_CONTEXT);
00799         if(rc == -1) {
00800             ERRMSG(PED, TRACE_LOG_ERR,
00801                 "%s: Route service could not issue clean-up due to error: %m",
00802                 __func__);
00803         }
00804     }
00805 }

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:06 2010 for SDK Your Net Corporation Policy Manager Example: Policy Enforcement Daemon 1.0 by Doxygen 1.5.1