00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00022 #include <stdbool.h>
00023 #include <string.h>
00024 #include <strings.h>
00025 #include <sys/types.h>
00026 #include <sys/queue.h>
00027 #include <sys/socket.h>
00028 #include <isc/eventlib.h>
00029 #include <jnx/aux_types.h>
00030 #include <jnx/junos_trace.h>
00031 #include <jnx/ssd_ipc.h>
00032 #include <jnx/ssd_ipc_msg.h>
00033 #include "route-manager.h"
00034
00035 #include OUT_H
00036
00037 extern nh_t nh_pool[];
00038
00040 bool svc_ready;
00041
00043 static int ssd_fd;
00044
00045
00046 static int client_id;
00047
00058 static int
00059 ssd_client_conn_open (int fd)
00060 {
00061 ssd_fd = fd;
00062 RM_TRACE(TF_SSD, "%s: SSD connection is open.", __func__);
00063
00064
00065 ssd_get_client_id(fd, client_id);
00066 return 0;
00067 }
00068
00076 static void
00077 ssd_client_conn_close (int fd UNUSED, int cause)
00078 {
00079 ssd_fd = -1;
00080 RM_TRACE(TF_SSD, "%s: SSD connection is closed by %d.", __func__, cause);
00081 }
00082
00092 static void
00093 ssd_client_msg_hdlr (int fd UNUSED, struct ssd_ipc_msg *msg)
00094 {
00095 route_t *rt;
00096
00097 switch (msg->ssd_ipc_cmd) {
00098 case SSD_SESSION_ID_REPLY:
00099 if (SSD_SESSION_ID_REPLY_CHECK_STATUS(msg)) {
00100 if (client_id == 0) {
00101
00102 client_id = SSD_SESSION_ID_REPLY_GET_CLIENT_ID(msg);
00103 kcom_client_id_save(client_id);
00104 RM_TRACE(TF_SSD, "%s: Got client ID %d and saved it.",
00105 __func__, client_id);
00106
00107
00108 ssd_setup_route_service(fd);
00109 } else {
00110
00111 RM_TRACE(TF_SSD, "%s: Session is restored %d.", __func__,
00112 client_id);
00113 svc_ready = true;
00114 }
00115 } else {
00116 RM_TRACE(TF_SSD, "%s: Request client ID %d ERROR!", __func__,
00117 client_id);
00118 }
00119 break;
00120
00121 case SSD_ROUTE_SERVICE_REPLY:
00122 if (SSD_ROUTE_SERVICE_REPLY_CHECK_STATUS(msg)) {
00123 RM_TRACE(TF_SSD, "%s: Route service is ready.", __func__);
00124 svc_ready = true;
00125 config_rt_proc(NULL);
00126 } else {
00127 RM_TRACE(TF_SSD, "%s: Setup route service ERROR!", __func__);
00128 }
00129 break;
00130
00131 case SSD_ROUTE_TABLE_LOOKUP_REPLY:
00132 rt = (route_t *)SSD_ROUTE_TABLE_LOOKUP_REPLY_GET_CLIENT_CTX(msg);
00133 if (SSD_ROUTE_TABLE_LOOKUP_REPLY_CHECK_STATUS(msg)) {
00134 RM_TRACE(TF_SSD, "%s: Routing table ID %d.", __func__,
00135 SSD_ROUTE_TABLE_LOOKUP_REPLY_GET_RTTID(msg));
00136
00137
00138 if (rt->ctx_id) {
00139 nh_pool[rt->ctx_id].idx =
00140 SSD_ROUTE_TABLE_LOOKUP_REPLY_GET_RTTID(msg);
00141 nh_pool[rt->ctx_id].op_state = NH_STATE_ADD_OK;
00142 } else {
00143
00144 RM_LOG(LOG_ERR, "%s: No route is waiting for this!", __func__);
00145 }
00146 } else {
00147 RM_TRACE(TF_SSD, "%s: Routing table ID lookup ERROR %d.", __func__,
00148 SSD_ROUTE_TABLE_LOOKUP_REPLY_GET_ERROR_CODE(msg));
00149
00150
00151 rt->op_state = RT_STATE_ADD_ERR;
00152 }
00153
00154 config_rt_proc(rt);
00155 break;
00156 case SSD_ROUTE_ADD_REPLY:
00157 rt = (route_t *)SSD_ROUTE_ADD_REPLY_GET_CLIENT_CTX(msg);
00158 if (SSD_ROUTE_ADD_REPLY_CHECK_STATUS(msg)) {
00159 RM_TRACE(TF_SSD, "%s: Add route %08x OK.", __func__,
00160 rt->dst_addr.in.gin_addr);
00161 rt->op_state = RT_STATE_ADD_OK;
00162 } else {
00163 RM_TRACE(TF_SSD, "%s: Add route %08x ERROR %d.", __func__,
00164 rt->dst_addr.in.gin_addr,
00165 SSD_ROUTE_ADD_REPLY_GET_ERROR_CODE(msg));
00166 rt->op_state = RT_STATE_ADD_ERR;
00167 }
00168
00169 config_rt_proc(rt);
00170 break;
00171 case SSD_NH_ADD_REPLY:
00172 rt = (route_t *)SSD_NEXTHOP_ADD_REPLY_GET_CLIENT_CTX(msg);
00173 if (SSD_NEXTHOP_ADD_REPLY_CHECK_STATUS(msg)) {
00174 RM_TRACE(TF_SSD, "%s: Add next-hop %s OK %d.", __func__,
00175 nh_pool[rt->ctx_id].name,
00176 SSD_NEXTHOP_ADD_REPLY_GET_NH_ID(msg));
00177 nh_pool[rt->ctx_id].idx = SSD_NEXTHOP_ADD_REPLY_GET_NH_ID(msg);
00178 nh_pool[rt->ctx_id].op_state = NH_STATE_ADD_OK;
00179 } else {
00180 RM_TRACE(TF_SSD, "%s: Add next-hop %s ERROR %d.", __func__,
00181 nh_pool[rt->ctx_id].name,
00182 SSD_NEXTHOP_ADD_REPLY_GET_ERROR_CODE(msg));
00183 nh_pool[rt->ctx_id].op_state = NH_STATE_ADD_ERR;
00184
00185 rt->op_state = RT_STATE_ADD_ERR;
00186 }
00187
00188 config_rt_proc(rt);
00189 break;
00190
00191 case SSD_ROUTE_DELETE_REPLY:
00192 rt = (route_t *)SSD_ROUTE_DELETE_REPLY_GET_CLIENT_CTX(msg);
00193 if (SSD_ROUTE_DELETE_REPLY_CHECK_STATUS(msg)) {
00194 RM_TRACE(TF_SSD, "%s: Delete route %08x OK.", __func__,
00195 rt->dst_addr.in.gin_addr);
00196 rt->op_state = RT_STATE_DEL_OK;
00197
00198 } else {
00199 RM_TRACE(TF_SSD, "%s: Delete route %08x ERROR %d.", __func__,
00200 rt->dst_addr.in.gin_addr,
00201 SSD_ROUTE_DELETE_REPLY_GET_ERROR_CODE(msg));
00202 rt->op_state = RT_STATE_DEL_ERR;
00203
00204
00205
00206 }
00207
00208 config_rt_proc(rt);
00209 break;
00210
00211 case SSD_NH_DELETE_REPLY:
00212 rt = (route_t *)SSD_NEXTHOP_DELETE_REPLY_GET_CLIENT_CTX(msg);
00213 if (SSD_NEXTHOP_DELETE_REPLY_CHECK_STATUS(msg)) {
00214 RM_TRACE(TF_SSD, "%s: Delete next-hop %s OK.", __func__,
00215 nh_pool[rt->ctx_id].name);
00216 } else {
00217 RM_TRACE(TF_SSD, "%s: Delete next-hop %s ERROR %d.", __func__,
00218 nh_pool[rt->ctx_id].name,
00219 SSD_NEXTHOP_DELETE_REPLY_GET_ERROR_CODE(msg));
00220 }
00221
00222
00223
00224 nh_pool[rt->ctx_id].op_state = NH_STATE_FREE;
00225
00226 config_rt_proc(rt);
00227 break;
00228
00229 case SSD_ROUTE_SERVICE_CLEAN_UP_REPLY:
00230 if (SSD_ROUTE_SERVICE_CLEAN_UP_REPLY_CHECK_STATUS(msg)) {
00231 RM_TRACE(TF_SSD, "%s: Clean up routing service OK.", __func__);
00232 } else {
00233 RM_TRACE(TF_SSD, "%s: Clean up routing service ERROR.", __func__);
00234 }
00235 break;
00236 default:
00237 RM_TRACE(TF_SSD, "%s: Undefined message command %d.", __func__,
00238 msg->ssd_ipc_cmd);
00239 }
00240 }
00241
00243 static struct ssd_ipc_ft ssd_client_cbs = {
00244 ssd_client_conn_open,
00245 ssd_client_conn_close,
00246 ssd_client_msg_hdlr
00247 };
00248
00259 int
00260 ssd_rt_add (route_t *rt)
00261 {
00262 struct ssd_route_parms params;
00263 int i;
00264
00265 bzero(¶ms, sizeof(params));
00266 params.rta_dest = &rt->dst_addr;
00267 params.rta_prefixlen = rt->prefix_len;
00268 params.rta_rtt = nh_pool[rt->rtt_id].idx;
00269 params.rta_nhtype = rt->nh_type;
00270 params.rta_state = rt->op_state;
00271 params.rta_flags = rt->flag;
00272 params.rta_preferences.rtm_val[0] = rt->preference;
00273 params.rta_preferences.rtm_type[0] = SSD_RTM_VALUE_PRESENT;
00274 params.rta_n_gw = rt->gw_num;
00275 for (i = 0; i < rt->gw_num; i++) {
00276 if (rt->gw_addr[i].in.gin_family == SSD_GF_INET) {
00277 params.rta_gateway[i].rtg_gwaddr = &rt->gw_addr[i];
00278 }
00279 if (rt->gw_ifl_addr[i].in.gin_family == SSD_GF_INET) {
00280 params.rta_gateway[i].rtg_lcladdr = &rt->gw_ifl_addr[i];
00281 }
00282 if (rt->gw_ifl_name[i][0] != '\0') {
00283 params.rta_gateway[i].rtg_iflname = rt->gw_ifl_name[i];
00284 }
00285 ifl_idx_t_setval(params.rta_gateway[i].rtg_ifl, rt->gw_ifl_idx);
00286 nh_idx_t_setval(params.rta_gateway[i].rtg_nhindex,
00287 nh_pool[rt->nh_id[i]].idx);
00288 RM_TRACE(TF_SSD, "%s: %d, %d, %d, %d, %d", __func__,
00289 rt->gw_addr[i].in.gin_family,
00290 rt->gw_ifl_addr[i].in.gin_family,
00291 rt->gw_ifl_name[i][0],
00292 rt->gw_ifl_idx,
00293 nh_pool[rt->nh_id[i]].idx);
00294
00295 }
00296 if (ssd_request_route_add(ssd_fd, ¶ms, (unsigned int)rt) < 0) {
00297 return -1;
00298 } else {
00299 return 0;
00300 }
00301 }
00302
00313 int
00314 ssd_rt_del (route_t *rt)
00315 {
00316 struct ssd_rt_delete_parms params;
00317
00318 bzero(¶ms, sizeof(params));
00319 params.rtd_dest = &rt->dst_addr;
00320 params.rtd_prefixlen = rt->prefix_len;
00321 params.rtd_rtt = nh_pool[rt->rtt_id].idx;
00322
00323 if (ssd_request_route_delete(ssd_fd, ¶ms, (unsigned int)rt) < 0) {
00324 return -1;
00325 } else {
00326 return 0;
00327 }
00328 }
00329
00342 int
00343 ssd_nh_add (route_t *rt, int nh_id)
00344 {
00345 struct ssd_nh_add_parms params;
00346 int ifl_idx;
00347 char *name;
00348 int rc;
00349
00350 if (rt->rtt_id == nh_id) {
00351
00352 name = strdup(nh_pool[nh_id].name);
00353 if (ssd_request_route_table_lookup(ssd_fd, name,
00354 (unsigned int)rt) < 0) {
00355 RM_LOG(LOG_ERR, "%s: Request routing table ID ERROR!");
00356 return -1;
00357 } else {
00358 RM_TRACE(TF_SSD, "%s: Request routing table %s ID OK.", __func__,
00359 nh_pool[nh_id].name);
00360 return 0;
00361 }
00362 }
00363
00364 switch (rt->nh_type) {
00365 case SSD_RNH_SERVICE:
00366 bzero(¶ms, sizeof(params));
00367 ifl_idx = kcom_ifl_get_idx_by_name(nh_pool[nh_id].name);
00368 if (ifl_idx < 0) {
00369 return -1;
00370 }
00371 ifl_idx_t_setval(params.ifl, ifl_idx);
00372 rc = ssd_request_nexthop_add(ssd_fd, nh_id, ¶ms, (unsigned int)rt);
00373 break;
00374 case SSD_RNH_TABLE:
00375 name = strdup(nh_pool[nh_id].name);
00376 rc = ssd_request_route_table_lookup(ssd_fd, name, (unsigned int)rt);
00377 break;
00378 default:
00379 rc = -1;
00380 }
00381 return rc;
00382 }
00383
00396 int
00397 ssd_nh_del (route_t *rt, int nh_id)
00398 {
00399 nh_idx_t idx;
00400
00401 nh_idx_t_setval(idx, nh_pool[nh_id].idx);
00402 if (ssd_request_nexthop_delete(ssd_fd, nh_id, idx, (unsigned int)rt) < 0) {
00403 return -1;
00404 } else {
00405 return 0;
00406 }
00407 }
00408
00414 void
00415 ssd_close (void)
00416 {
00417 ssd_clean_up_route_service(ssd_fd, 1);
00418 ssd_ipc_close(ssd_fd);
00419 ssd_fd = -1;
00420 svc_ready = false;
00421 }
00422
00433 int
00434 ssd_open (evContext ev_ctx)
00435 {
00436 svc_ready = false;
00437 client_id = kcom_client_id_restore();
00438 if (client_id < 0) {
00439 client_id = 0;
00440 }
00441 ssd_fd = ssd_ipc_connect_rt_tbl(NULL, &ssd_client_cbs, 0, ev_ctx);
00442 if (ssd_fd < 0) {
00443 return -1;
00444 } else {
00445 return 0;
00446 }
00447 }
00448