ped_service_route.c

Go to the documentation of this file.
00001 /*
00002  * $Id: ped_service_route.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 
00023 #include <sync/common.h>
00024 #include <jnx/ssd_ipc.h>
00025 #include <jnx/ssd_ipc_msg.h>
00026 #include "ped_service_route.h"
00027 
00028 #include PE_OUT_H
00029 #include PE_SEQUENCE_H
00030 
00031 /*
00032  * README:
00033  * 
00034  * Interacting with SSD to add/remove routes involves FIVE 
00035  * setup steps noted in the code below as STEP #0 - 4
00036  */
00037 
00038 
00039 /*** Constants ***/
00040 
00044 #define RT_TBL_NAME "inet.0"
00045 
00049 #define PFD_RT_TBL_NAME "pfd_forwarding.inet.0"
00050 
00054 #define RETRY_CONNECT 60
00055 
00056 #define DEFAULT_ROUTE_ADDRESS 0 
00057 #define DEFAULT_ROUTE_MASK    0 
00058 #define FULL_ROUTE_MASK      32 
00059 
00060 #define SERVICE_ROUTE_PREF   10 
00061 
00062 #define INT_NAME_STR_SIZE    64 
00063 
00064 /*** Data structures ***/
00065 
00066 
00067 static boolean ssd_ready = FALSE;  
00068 static int ssd_server_fd;          
00069 static int client_id;              
00070 static int client_nexthop_id;      
00071 static uint32_t client_ctx;        
00072 static uint32_t rt_tbl_id;         
00073 static uint32_t pfd_rt_tbl_id;     
00074 static evTimerID  timer_id;        
00075 
00076 // Need these forward declarations for ssd_client_ft, the function table:
00077 
00078 static int serv_rt_client_connection(int fd);
00079 static void serv_rt_client_connection_close(int fd, int cause);
00080 static void serv_rt_client_msg(int fd, struct ssd_ipc_msg *cmsg);
00081 
00085 static struct ssd_ipc_ft ssd_client_ft = {
00086     serv_rt_client_connection,           
00087     serv_rt_client_connection_close,     
00088     serv_rt_client_msg                   
00089 };
00090 
00094 typedef struct route_info_s {
00095     uint32_t  rt_table_id;  
00096     uint32_t  client_ctx;   
00097     int       client_nh_id; 
00098     ifl_idx_t ifl_index;    
00099     nh_idx_t  nh_index;     
00100     in_addr_t address;      
00101     in_addr_t mask;         
00102     TAILQ_ENTRY(route_info_s) entries;
00103 } route_info_t;
00104 
00108 static TAILQ_HEAD(route_list_s, route_info_s) route_list = 
00109             TAILQ_HEAD_INITIALIZER(route_list);
00110 
00111 
00112 enum action {
00113     ADD_PFD_ROUTE,         
00114     ADD_NORMAL_ROUTE,      
00115     DELETE_PFD_ROUTE,      
00116     DELETE_NORMAL_ROUTE    
00117 };
00118 
00122 typedef struct request_info_s {
00123     enum action req_action;                 
00124     char interface_name[INT_NAME_STR_SIZE]; 
00125     in_addr_t address;                      
00126     TAILQ_ENTRY(request_info_s) entries;    
00127 } request_info_t;
00128 
00129 
00133 static TAILQ_HEAD(request_buffer_s, request_info_s) requests = 
00134             TAILQ_HEAD_INITIALIZER(requests);
00135 
00136 
00137 /*** STATIC/INTERNAL Functions ***/
00138 
00139 
00158 static void
00159 connect_ssd(evContext ctx,
00160             void * uap  __unused,
00161             struct timespec due __unused,
00162             struct timespec inter __unused)
00163 {
00164     int rt_table_id;
00165 
00166     if(ssd_server_fd >= 0) {
00167         return;
00168     }
00169 
00170     // STEP #0
00171 
00172     rt_table_id = ssd_get_routing_instance();
00173     ssd_server_fd = ssd_ipc_connect_rt_tbl(NULL, &ssd_client_ft,
00174                                      rt_table_id, ctx);
00175     
00176     if (ssd_server_fd < 0) {
00177         ERRMSG(PED, TRACE_LOG_ERR,
00178                 "%s%s: Opening socket to the SSD failed! Will retry.",
00179                 __func__, __FILE__);
00180         return;
00181     }
00182     
00183     evClearTimer(ctx, timer_id);
00184     
00185     junos_trace(PED_TRACEFLAG_ROUTING,
00186         "%s: Service route module connected to the SSD", __func__);
00187 }
00188 
00189 
00199 static route_info_t *
00200 get_route_by_ctx(uint32_t client_context)
00201 {
00202     route_info_t * route_info = TAILQ_FIRST(&route_list);
00203     
00204     while(route_info) {
00205         if(client_context == route_info->client_ctx) { // found it
00206             return route_info;
00207         }
00208         route_info = TAILQ_NEXT(route_info, entries);
00209     }
00210     
00211     return NULL;
00212 }
00213 
00214 
00227 static status_t
00228 get_ifl_index(char * interface_name, ifl_idx_t * ifl_index)
00229 {
00230     kcom_ifl_t ifl_info;
00231     char * dot;
00232     int rc;
00233     
00234     // Parse the interface name for the IFD name and the logical unit #
00235     
00236     if((dot = strchr(interface_name, '.')) == NULL) {
00237         ERRMSG(PED, TRACE_LOG_ERR, "%s: Cannot parse interface name",
00238             __func__);
00239         return EFAIL;
00240     }
00241     
00242     *dot = '\0'; // separate strings at the dot
00243     ++dot; // move to the start of next string indicating the logical unit #
00244     
00245     // Get the IFL index usign KCOM
00246     rc = junos_kcom_ifl_get_by_name(
00247         interface_name, (if_subunit_t)atoi(dot), &ifl_info);
00248     
00249     // restore dot
00250     --dot;
00251     *dot = '.';
00252 
00253     if (rc != KCOM_OK) {
00254         return ENOENT;
00255     }
00256     
00257     ifl_idx_t_set_equal(*ifl_index, ifl_info.ifl_index);
00258     
00259     return SUCCESS;
00260 }
00261 
00262 
00269 static void
00270 add_service_route_helper(route_info_t * route_info)
00271 {
00272     struct ssd_route_parms rtp;
00273     ssd_sockaddr_un route_addr;
00274     int rc;
00275 
00276     /* Initialize the information for route add  */
00277     bzero(&route_addr, sizeof(route_addr));
00278     ssd_setsocktype(&route_addr, SSD_GF_INET);
00279     route_addr.in.gin_addr = route_info->address;
00280 
00281     bzero(&rtp, sizeof(rtp));
00282     rtp.rta_dest = &route_addr;
00283     rtp.rta_prefixlen = route_info->mask;
00284     rtp.rta_nhtype = SSD_RNH_SERVICE; // flag it as a service route
00285     rtp.rta_preferences.rtm_val[0] = SERVICE_ROUTE_PREF;
00286     rtp.rta_preferences.rtm_type[0] = SSD_RTM_VALUE_PRESENT;
00287     rtp.rta_rtt = route_info->rt_table_id;
00288     rtp.rta_gw_handle = 0;
00289     rtp.rta_n_gw = 1;
00290     rtp.rta_gateway[0].rtg_ifl = route_info->ifl_index;
00291     rtp.rta_gateway[0].rtg_nhindex = route_info->nh_index;
00292 
00293     rc = ssd_request_route_add(ssd_server_fd, &rtp, ++client_ctx);
00294     
00295     if(rc == -1) {
00296         ERRMSG(PED, TRACE_LOG_ERR,
00297             "%s: Failed to request service route addition: %m", __func__);
00298     }
00299     
00300     route_info->client_ctx = client_ctx;
00301 }
00302 
00303 
00307 static void
00308 process_requests(void)
00309 {
00310     request_info_t * req;
00311     
00312     while((req = TAILQ_FIRST(&requests))) {
00313         switch(req->req_action) {
00314             case ADD_PFD_ROUTE:
00315                 add_pfd_service_route(req->interface_name);
00316                 break;
00317             case DELETE_PFD_ROUTE:
00318                 delete_pfd_service_route(req->interface_name);
00319                 break;
00320             case ADD_NORMAL_ROUTE:
00321                 add_service_route(req->interface_name, req->address);
00322                 break;
00323             case DELETE_NORMAL_ROUTE:
00324                 delete_service_route(req->interface_name, req->address);
00325                 break;
00326         }
00327         TAILQ_REMOVE(&requests, req, entries);
00328         free(req);
00329     }
00330 }
00331 
00332 
00337 static int
00338 serv_rt_client_connection(int fd)
00339 {
00340     // STEP #0 (finished)
00341     
00342     if(ssd_get_client_id(fd, 0) < 0) {  // STEP #1
00343         ERRMSG(PED, TRACE_LOG_ERR,
00344             "%s: Service route module ERROR requesting "
00345             "client ID from the SSD %m", __func__);
00346         
00347         return -1;
00348     }
00349 
00350     junos_trace(PED_TRACEFLAG_ROUTING,
00351             "%s: SSD acknowledged connection.", __func__);
00352     
00353     return SUCCESS;
00354 }
00355 
00356 
00366 static void
00367 serv_rt_client_connection_close(int fd __unused, int cause __unused)
00368 {
00369     ssd_server_fd = -1;
00370     ssd_ready = FALSE;
00371     
00372     junos_trace(PED_TRACEFLAG_ROUTING, "%s: SSD disconnected from "
00373         "the service route module.", __func__);
00374 
00375     junos_trace(PED_TRACEFLAG_ROUTING, 
00376        "PED's Service route module is NOT accepting route add/delete requests");
00377 }
00378 
00379 
00389 static void
00390 serv_rt_client_msg (int fd, struct ssd_ipc_msg * cmsg)
00391 {
00392     char * rt_tb_name = NULL;
00393     route_info_t * route_info;
00394     
00395     switch (cmsg->ssd_ipc_cmd) {
00396 
00397     case SSD_SESSION_ID_REPLY:
00398     
00399         if(SSD_SESSION_ID_REPLY_CHECK_STATUS(cmsg)) {
00400             
00401             client_id = SSD_SESSION_ID_REPLY_GET_CLIENT_ID(cmsg); // STEP #1 (finished)
00402             
00403             junos_trace(PED_TRACEFLAG_ROUTING, 
00404                     "%s: Received client id from SSD : %u",
00405                     __func__, client_id);
00406             
00407             // Requesting route service setup...
00408             
00409             if(ssd_setup_route_service(fd) < 0) {  // STEP #2
00410                 ERRMSG(PED, TRACE_LOG_ERR,
00411                     "%s: Error requesting route service setup from SSD %m",
00412                     __func__);
00413             }
00414         }
00415         
00416         break;
00417         
00418     case SSD_ROUTE_SERVICE_REPLY:
00419     
00420         if(SSD_ROUTE_SERVICE_REPLY_CHECK_STATUS(cmsg)) {
00421             
00422             junos_trace(PED_TRACEFLAG_ROUTING, // STEP #2 (finished)
00423                 "%s: Route service has been setup properly",
00424                  __func__);
00425             
00426             if(rt_tbl_id && pfd_rt_tbl_id) {
00427                 // Only falls here after clean route service was performed and
00428                 // we have to re-call ssd_setup_route_service()
00429                 
00430                 // Service route module is ready to accept requests
00431                 
00432                 ssd_ready = TRUE;
00433                 
00434                 junos_trace(PED_TRACEFLAG_ROUTING, 
00435                     "PED's Service route module is ready to accept route "
00436                     "add/delete requests again after routes were purged");
00437                 
00438                 process_requests(); // process existing requests
00439                 
00440                 break;
00441             }
00442             
00443             // Request route table IDs for both routing tables       STEP #3
00444             // that we'll beadding service routes to
00445             
00446             rt_tb_name = strdup(RT_TBL_NAME);
00447             INSIST(rt_tb_name != NULL);
00448                  
00449             if(ssd_request_route_table_lookup(fd, rt_tb_name, 0) < 0) {
00450 
00451                 ERRMSG(PED, TRACE_LOG_ERR,
00452                     "%s: Error requesting route table lookup from SSD %m",
00453                     __func__);
00454             }
00455             
00456             rt_tb_name = strdup(PFD_RT_TBL_NAME);
00457             INSIST(rt_tb_name != NULL);
00458                  
00459             if(ssd_request_route_table_lookup(fd, rt_tb_name, 1) < 0) {
00460 
00461                 ERRMSG(PED, TRACE_LOG_ERR,
00462                     "%s: Error requesting route table lookup from SSD %m",
00463                     __func__);
00464             }
00465         }
00466         break;
00467         
00468     case SSD_ROUTE_TABLE_LOOKUP_REPLY:
00469     
00470         if(SSD_ROUTE_TABLE_LOOKUP_REPLY_CHECK_STATUS(cmsg)) {
00471             
00472             // STEP #3 (finished)
00473             // retrieve the routing table IDs from the message
00474             
00475             if(SSD_ROUTE_TABLE_LOOKUP_REPLY_GET_CLIENT_CTX(cmsg) == 0) {
00476                 rt_tbl_id = SSD_ROUTE_TABLE_LOOKUP_REPLY_GET_RTTID(cmsg);
00477                 
00478                 junos_trace(PED_TRACEFLAG_ROUTING, "%s: Route table "
00479                     "found, id: %u", __func__, rt_tbl_id);
00480                 
00481             } else if(SSD_ROUTE_TABLE_LOOKUP_REPLY_GET_CLIENT_CTX(cmsg) == 1) {
00482                 pfd_rt_tbl_id = SSD_ROUTE_TABLE_LOOKUP_REPLY_GET_RTTID(cmsg);
00483                 
00484                 junos_trace(PED_TRACEFLAG_ROUTING, "%s: Route table "
00485                     "found, id: %u", __func__, pfd_rt_tbl_id);
00486             } else {
00487                 ERRMSG(PED, TRACE_LOG_ERR, "%s: Received a route table"
00488                     " ID for an unknown route table", __func__);
00489             }
00490             
00491             if(rt_tbl_id && pfd_rt_tbl_id) { // if we've got both back
00492                 // Service route module is ready to accept requests
00493                 
00494                 ssd_ready = TRUE;                     // STEP #4
00495                 
00496                 junos_trace(PED_TRACEFLAG_ROUTING, 
00497                     "PED's Service route module is ready to accept "
00498                     "route add/delete requests");
00499                 
00500                 process_requests(); // process existing requests
00501             }
00502         } else {
00503             if(SSD_ROUTE_TABLE_LOOKUP_REPLY_GET_CLIENT_CTX(cmsg) == 1) {
00504                 ERRMSG(PED, TRACE_LOG_WARNING, "%s: Route table ID "
00505                     "lookup for %s has failed. The service route module is not "
00506                     "available and is waiting for notification to try the "
00507                     "request again.", __func__, PFD_RT_TBL_NAME);
00508             } else {
00509                 ERRMSG(PED, TRACE_LOG_ERR, "%s: Route table ID lookup "
00510                     "for %s has failed. The service route module will be "
00511                     "offline.", __func__, RT_TBL_NAME);
00512             }
00513         }
00514         
00515         break;
00516 
00517     case SSD_NH_ADD_REPLY:
00518         
00519         route_info =
00520             get_route_by_ctx(SSD_NEXTHOP_ADD_REPLY_GET_CLIENT_CTX(cmsg));
00521         
00522         if (SSD_NEXTHOP_ADD_REPLY_CHECK_STATUS(cmsg)) {
00523             
00524             if(route_info) {
00525                 
00526                 // SAVE the next-hop id and ADD the route
00527                 
00528                 junos_trace(PED_TRACEFLAG_ROUTING, 
00529                     "%s: Successfully added next-hop, adding service route",
00530                     __func__);
00531                 
00532                 nh_idx_t_setval(route_info->nh_index,
00533                         SSD_NEXTHOP_ADD_REPLY_GET_NH_ID(cmsg));
00534                 
00535                 add_service_route_helper(route_info);
00536                 
00537             } else {
00538                 ERRMSG(PED, TRACE_LOG_ERR, "%s: Couldn't find route "
00539                     "to add after next-hop add succeeded.", __func__);
00540             }
00541         } else {
00542             
00543             ERRMSG(PED, TRACE_LOG_ERR, "%s: Failed to add next-hop",
00544                 __func__);
00545             
00546             // Take it out of the list
00547             
00548             if(route_info) {
00549                 TAILQ_REMOVE(&route_list, route_info, entries);
00550                 free(route_info);
00551             } else {
00552                 ERRMSG(PED, TRACE_LOG_ERR, "%s: Couldn't find route "
00553                    "to remove after next-hop add failed.", __func__);
00554             }
00555         }
00556         break;
00557         
00558     case SSD_ROUTE_ADD_REPLY:
00559 
00560         if(SSD_ROUTE_ADD_REPLY_CHECK_STATUS(cmsg)) {
00561             junos_trace(PED_TRACEFLAG_ROUTING, 
00562                     "%s: Successfully added service route", __func__);
00563         } else {
00564             ERRMSG(PED, TRACE_LOG_ERR, 
00565                     "%s: Failed to add service route", __func__);
00566 
00567             // Delete the next-hop associated with it
00568             
00569             route_info =
00570                 get_route_by_ctx(SSD_NEXTHOP_ADD_REPLY_GET_CLIENT_CTX(cmsg));
00571             
00572             if(route_info) {
00573                 ssd_request_nexthop_delete(ssd_server_fd,
00574                     route_info->client_nh_id, route_info->nh_index,
00575                     ++client_ctx);
00576                 
00577                 route_info->client_ctx = client_ctx;
00578             } else {
00579                 ERRMSG(PED, TRACE_LOG_ERR, "%s: Couldn't find route "
00580                    "to delete next-hop after route add failed.", __func__);
00581             }
00582         }
00583         
00584         break;
00585         
00586     case SSD_ROUTE_DELETE_REPLY:
00587     
00588         if (SSD_ROUTE_DELETE_REPLY_CHECK_STATUS(cmsg)) {
00589             junos_trace(PED_TRACEFLAG_ROUTING, "%s: Successfully deleted " 
00590                 "service route, removing next hop", __func__);  
00591         } else {
00592             ERRMSG(PED, TRACE_LOG_ERR, "%s: Failed to delete service "
00593                 "route, removing next hop", __func__);  
00594         }
00595 
00596         route_info =
00597             get_route_by_ctx(SSD_NEXTHOP_ADD_REPLY_GET_CLIENT_CTX(cmsg));
00598         
00599         // Delete the next-hop associated with it
00600         
00601         if(route_info) {
00602             ssd_request_nexthop_delete(ssd_server_fd,
00603                 route_info->client_nh_id, route_info->nh_index,
00604                 ++client_ctx);
00605             
00606             route_info->client_ctx = client_ctx;
00607         } else {
00608             ERRMSG(PED, TRACE_LOG_ERR, "%s: Could not find route in "
00609                 "list to delete the next hop", __func__);
00610         }
00611         
00612         break;
00613         
00614     case SSD_NH_DELETE_REPLY:
00615         
00616         if (SSD_NEXTHOP_DELETE_REPLY_CHECK_STATUS(cmsg)) {
00617             junos_trace(PED_TRACEFLAG_ROUTING, 
00618                 "%s: Successfully deleted next-hop", __func__);  
00619         } else {
00620             ERRMSG(PED, TRACE_LOG_ERR,
00621                 "%s: Failed to delete next-hop", __func__);  
00622         }
00623         
00624         // Remove route from list
00625         
00626         route_info =
00627             get_route_by_ctx(SSD_NEXTHOP_ADD_REPLY_GET_CLIENT_CTX(cmsg));
00628         
00629         if(route_info) {
00630             junos_trace(PED_TRACEFLAG_ROUTING, 
00631                 "%s: Successfully deleted route from management", __func__);
00632             
00633             TAILQ_REMOVE(&route_list, route_info, entries);
00634             free(route_info);
00635         } else {
00636             ERRMSG(PED, TRACE_LOG_ERR, "%s: Could not find route to "
00637                 "remove in list", __func__);
00638         }
00639         
00640         break;
00641         
00642     case SSD_ROUTE_SERVICE_CLEAN_UP_REPLY:
00643         
00644         if (SSD_ROUTE_SERVICE_CLEAN_UP_REPLY_CHECK_STATUS(cmsg)) {
00645             junos_trace(PED_TRACEFLAG_ROUTING, 
00646                 "%s: Route service cleanup succeeded", __func__);  
00647         } else {
00648             junos_trace(PED_TRACEFLAG_ROUTING,
00649                 "%s: Route service cleanup failure", __func__);  
00650         }
00651         
00652         // Requesting route service setup...
00653         
00654         if(ssd_setup_route_service(fd) < 0) {
00655             ERRMSG(PED, TRACE_LOG_ERR,
00656                 "%s: Error requesting route service setup from SSD %m",
00657                 __func__);
00658         }
00659         
00660         break;
00661 
00662     default:
00663         ERRMSG(PED, TRACE_LOG_ERR, "%s: Unknown message type %d",
00664             __func__, cmsg->ssd_ipc_args[0]);
00665     }
00666 }
00667 
00668 
00669 /*** GLOBAL/EXTERNAL Functions ***/
00670 
00671 
00678 void
00679 service_route_init(evContext ctx)
00680 {
00681     ssd_server_fd = -1;
00682     client_id = -1;
00683     client_ctx = 2; // we use 0 and 1 in route table lookups
00684     rt_tbl_id = 0;
00685     pfd_rt_tbl_id = 0;
00686     client_nexthop_id = 0;
00687 
00688     /*
00689      * Set the SSD connect retry timer:
00690      * immediate one-shot event now, and periodocally afterward every 
00691      * RETRY_CONNECT seconds
00692      * 
00693      * calls connect_ssd()
00694      */
00695     if(evSetTimer(ctx, connect_ssd, NULL, evNowTime(),
00696         evConsTime(RETRY_CONNECT, 0), &timer_id)) {
00697 
00698         ERRMSG(PED, TRACE_LOG_ERR,
00699                 "%s: evSetTimer() FAILED! Will not be able to connect "
00700                 "to the SSD", __func__);
00701     }
00702 }
00703 
00704 
00708 void
00709 service_route_shutdown(void)
00710 {
00711     if(ssd_server_fd != -1) {
00712         ssd_ipc_close(ssd_server_fd);
00713     }
00714 }
00715 
00716 
00722 void
00723 pfd_ri_created(void)
00724 {
00725     char * rt_tb_name;
00726     
00727     if(client_id == -1) { // haven't got a connection to the SSD yet 
00728         return;
00729     }
00730     
00731     junos_trace(PED_TRACEFLAG_ROUTING, "%s: trying to get the route table ID "
00732         "for %s again.", __func__, PFD_RT_TBL_NAME);
00733     
00734     if(!ssd_ready) {
00735         rt_tb_name = strdup(PFD_RT_TBL_NAME);
00736         INSIST(rt_tb_name != NULL);
00737              
00738         if(ssd_request_route_table_lookup(ssd_server_fd, rt_tb_name, 1) < 0) {
00739             ERRMSG(PED, TRACE_LOG_ERR,
00740                 "%s: Error requesting route table lookup from SSD %m",
00741                 __func__);
00742         }
00743     }
00744 }
00745 
00746 
00753 boolean
00754 get_serviceroute_ready(void)
00755 {
00756     return ssd_ready;
00757 }
00758 
00759 
00767 void
00768 add_pfd_service_route(char * interface_name)
00769 {
00770     route_info_t * route_info;
00771     request_info_t * req;
00772     struct ssd_nh_add_parms nh_params;
00773     int rc;
00774     
00775     INSIST(interface_name != NULL);
00776     
00777     if(!ssd_ready) {
00778         // save request for later
00779         req = calloc(1, sizeof(request_info_t));
00780         INSIST(req != NULL);
00781         req->req_action = ADD_PFD_ROUTE;
00782         strncpy(req->interface_name, interface_name, INT_NAME_STR_SIZE); 
00783         TAILQ_INSERT_TAIL(&requests, req, entries);
00784         return;
00785     }
00786     
00787     bzero(&nh_params, sizeof(nh_params));
00788     
00789     // Set the IFL index
00790     rc = get_ifl_index(interface_name, &nh_params.ifl);
00791     
00792     if(rc != SUCCESS || ifl_idx_t_is_equal(nh_params.ifl, null_ifl_idx)) {
00793         
00794         ERRMSG(PED, TRACE_LOG_ERR, "%s: Cannot parse or get a valid IFL"
00795             " index for %s", __func__, interface_name);
00796         return;
00797     }
00798     
00799     // Use round-robin packet distribution on PFD
00800     nh_params.pkt_dist_type = SSD_NEXTHOP_PKT_DIST_RR;
00801     
00802     // Add next hop
00803     rc = ssd_request_nexthop_add(
00804         ssd_server_fd, ++client_nexthop_id, &nh_params, ++client_ctx);
00805     
00806     if(rc == -1) {
00807         ERRMSG(PED, TRACE_LOG_ERR,
00808             "%s: Could not request next-hop addition.", __func__);
00809         return;
00810     }
00811     
00812     route_info = calloc(1, sizeof(route_info_t));
00813     INSIST(route_info != NULL);
00814     route_info->rt_table_id = pfd_rt_tbl_id;
00815     route_info->address = DEFAULT_ROUTE_ADDRESS;
00816     route_info->mask = DEFAULT_ROUTE_MASK;
00817     route_info->client_ctx = client_ctx;
00818     route_info->client_nh_id = client_nexthop_id;
00819     ifl_idx_t_set_equal(nh_params.ifl, route_info->ifl_index);
00820     
00821     TAILQ_INSERT_TAIL(&route_list, route_info, entries);
00822 }
00823 
00824 
00832 void
00833 delete_pfd_service_route(char * interface_name)
00834 {
00835     route_info_t * route_info;
00836     request_info_t * req;
00837     struct ssd_rt_delete_parms rtp;
00838     ssd_sockaddr_un route_addr;
00839     ifl_idx_t ifl_index;
00840     int rc;
00841 
00842     INSIST(interface_name != NULL);
00843 
00844     if(!ssd_ready) {
00845         // save request for later
00846         req = calloc(1, sizeof(request_info_t));
00847         INSIST(req != NULL);
00848         req->req_action = DELETE_PFD_ROUTE;
00849         strncpy(req->interface_name, interface_name, INT_NAME_STR_SIZE); 
00850         TAILQ_INSERT_TAIL(&requests, req, entries);
00851         return;
00852     }
00853 
00854     bzero(&route_addr, sizeof(route_addr));
00855     bzero(&rtp, sizeof(rtp));
00856     
00857     get_ifl_index(interface_name, &ifl_index); // used to search for the route
00858 
00859     route_info = TAILQ_FIRST(&route_list);
00860     while(route_info) {
00861         if(ifl_idx_t_is_equal(ifl_index, route_info->ifl_index)) {
00862             
00863             ssd_setsocktype(&route_addr, SSD_GF_INET);
00864             route_addr.in.gin_addr = route_info->address;
00865             
00866             rtp.rtd_dest = &route_addr;
00867             rtp.rtd_prefixlen = route_info->mask;
00868             rtp.rtd_rtt = route_info->rt_table_id;
00869             rtp.rtd_gw_handle = 0;
00870             
00871             rc = ssd_request_route_delete(ssd_server_fd, &rtp, ++client_ctx);
00872             
00873             route_info->client_ctx = client_ctx;
00874             
00875             if(rc == -1) {
00876                 ERRMSG(PED, TRACE_LOG_ERR,
00877                     "%s: Request to delete service route failed", __func__);
00878                 
00879                 // Remove the route from the list
00880                 TAILQ_REMOVE(&route_list, route_info, entries);
00881                 free(route_info);
00882             }
00883             
00884             return;
00885         }
00886         route_info = TAILQ_NEXT(route_info, entries);
00887     }
00888     
00889     ERRMSG(PED, TRACE_LOG_ERR, "%s: Could not find route to delete",
00890         __func__);
00891 }
00892 
00893 
00905 void
00906 add_service_route(char * interface_name, in_addr_t address)
00907 {
00908     route_info_t * route_info;
00909     request_info_t * req;
00910     struct ssd_nh_add_parms nh_params;
00911     int rc;
00912     
00913     INSIST(interface_name != NULL);
00914 
00915     if(!ssd_ready) {
00916         // save request for later
00917         req = calloc(1, sizeof(request_info_t));
00918         INSIST(req != NULL);
00919         req->req_action = ADD_NORMAL_ROUTE;
00920         req->address = address;
00921         strncpy(req->interface_name, interface_name, INT_NAME_STR_SIZE); 
00922         TAILQ_INSERT_TAIL(&requests, req, entries);
00923         return;
00924     }
00925     
00926     bzero(&nh_params, sizeof(nh_params));
00927     
00928     // Set the IFL index
00929     rc = get_ifl_index(interface_name, &nh_params.ifl);
00930     
00931     if(rc != SUCCESS || ifl_idx_t_is_equal(nh_params.ifl, null_ifl_idx)) {
00932         
00933         ERRMSG(PED, TRACE_LOG_ERR, "%s: Cannot parse or get a valid IFL"
00934             " index for %s", __func__, interface_name);
00935         return;
00936     }
00937     
00938     // Use round-robin packet distribution on PFD
00939     nh_params.pkt_dist_type = SSD_NEXTHOP_PKT_DIST_RR;
00940     
00941     // Add next hop
00942     rc = ssd_request_nexthop_add(
00943         ssd_server_fd, ++client_nexthop_id, &nh_params, ++client_ctx);
00944     
00945     if(rc == -1) {
00946         ERRMSG(PED, TRACE_LOG_ERR,
00947             "%s: Could not request next-hop addition.", __func__);
00948         return;
00949     }
00950 
00951     route_info = calloc(1, sizeof(route_info_t));
00952     INSIST(route_info != NULL);
00953     route_info->rt_table_id = rt_tbl_id;
00954     route_info->address = address;
00955     route_info->mask = FULL_ROUTE_MASK;
00956     route_info->client_ctx = client_ctx;
00957     route_info->client_nh_id = client_nexthop_id;
00958     ifl_idx_t_set_equal(nh_params.ifl, route_info->ifl_index);
00959     
00960     TAILQ_INSERT_TAIL(&route_list, route_info, entries);
00961 }
00962 
00963 
00974 void
00975 delete_service_route(char * interface_name, in_addr_t address)
00976 {
00977     route_info_t * route_info;
00978     request_info_t * req;
00979     struct ssd_rt_delete_parms rtp;
00980     ssd_sockaddr_un route_addr;
00981     ifl_idx_t ifl_index;
00982     int rc;
00983 
00984     INSIST(interface_name != NULL);
00985 
00986     if(!ssd_ready) {
00987         // save request for later
00988         req = calloc(1, sizeof(request_info_t));
00989         INSIST(req != NULL);
00990         req->req_action = DELETE_NORMAL_ROUTE;
00991         req->address = address;
00992         strncpy(req->interface_name, interface_name, INT_NAME_STR_SIZE); 
00993         TAILQ_INSERT_TAIL(&requests, req, entries);
00994         return;
00995     }
00996     
00997     bzero(&route_addr, sizeof(route_addr));
00998     bzero(&rtp, sizeof(rtp));
00999     
01000     get_ifl_index(interface_name, &ifl_index); // used to search for the route
01001 
01002     route_info = TAILQ_FIRST(&route_list);
01003     while(route_info) {
01004         if(ifl_idx_t_is_equal(ifl_index, route_info->ifl_index)) {
01005             
01006             if(address != route_info->address) {
01007                 ERRMSG(PED, TRACE_LOG_ERR, "%s: Address does not match "
01008                     "the address associated with the service route on the "
01009                     "interface %s", __func__, interface_name);
01010                 return;
01011             }
01012             
01013             ssd_setsocktype(&route_addr, SSD_GF_INET);
01014             route_addr.in.gin_addr = address;
01015             
01016             rtp.rtd_dest = &route_addr;
01017             rtp.rtd_prefixlen = route_info->mask;
01018             rtp.rtd_rtt = route_info->rt_table_id;
01019             rtp.rtd_gw_handle = 0;
01020             
01021             rc = ssd_request_route_delete(ssd_server_fd, &rtp, ++client_ctx);
01022             
01023             route_info->client_ctx = client_ctx;
01024             
01025             if(rc == -1) {
01026                 ERRMSG(PED, TRACE_LOG_ERR,
01027                     "%s: Request to delete service route failed", __func__);
01028                 
01029                 // Remove the route from the list
01030                 TAILQ_REMOVE(&route_list, route_info, entries);
01031                 free(route_info);
01032             }
01033             
01034             return;
01035         }
01036         route_info = TAILQ_NEXT(route_info, entries);
01037     }
01038     
01039     ERRMSG(PED, TRACE_LOG_ERR, "%s: Could not find route to delete",
01040         __func__);
01041 }
01042 
01043 
01047 void
01048 clean_service_routes(void)
01049 {
01050     int rc;
01051     
01052     if(ssd_ready) {
01053         junos_trace(PED_TRACEFLAG_ROUTING,
01054             "%s: Route service module is purging routes", __func__);
01055         ssd_ready = FALSE;
01056         rc = ssd_clean_up_route_service(ssd_server_fd, ++client_ctx);
01057         
01058         if(rc == -1) {
01059             ERRMSG(PED, TRACE_LOG_ERR,
01060                 "%s: Route service could not issue clean-up due to error: %m",
01061                 __func__);
01062         }
01063 
01064     }
01065 }

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