📄 ip_cmn_rte_table.ex.c
字号:
{
ip_cmn_rte_default_route_add (route_table, src_obj_ptr,
next_hop, port_info, metric, proto, admin_distance);
/* Nothing more to be done. */
FRET (OPC_COMPCODE_SUCCESS);
}
/* Check if a standard routing protocol is adding an entry. */
if ((proto_type < IPC_INITIAL_CUSTOM_RTE_PROTOCOL_ID) && (proto_type != IPC_DYN_RTE_DEFAULT))
{
/** A standard routing protocol is adding an entry. **/
/* Because of support for route redistribution and */
/* route maps/filters, there are several cases which */
/* need to be handled. */
/* */
/* 1: There is no route to the destination network in */
/* the route table from any protocol. */
/* 2: There is a route to the destination network in */
/* the route table and it is provided from the same */
/* protocol. */
/* 3: There is a route to the destination network in */
/* the route table and it is provided from a protocol */
/* which has a better admin distance. */
/* 3A: The protocol in the table is directly connected. */
/* 4: There is a route to the destination network in */
/* the route table and it is provided from a protocol */
/* which has a worse admin distance. */
/* 4A: The new route's protocol is directly connected. */
/* */
/* Directly connected routes need to be handled */
/* differently because the routing protocols which */
/* provide routes to their networks need to be */
/* redistributed, even though the route table entry is */
/* a directly connected route. */
/* Use the keep route option to make sure that we do */
/* not blindly overwrite the existing entry. */
new_ptree_entry = oms_ptree_entry_add (ptree_ptr, address,
ip_cmn_rte_table_dest_prefix_mask_len_get (dest_prefix),
OPC_NIL, OMSC_PTREE_ADD_KEEP_ROUTE, &curr_ptree_entry);
if (PRGC_NIL != curr_ptree_entry)
{
/** An entry was found to this destination. **/
/* Access the IpT_Cmn_Rte_Table_Entry structure */
/* associated with this entry. */
curr_entry = ip_cmn_rte_table_entry_from_ptree_entry_get (curr_ptree_entry);
if ((curr_entry->admin_distance == admin_distance) && (curr_entry->route_src_proto == proto))
{
/** Entry being added is from the same protocol **/
/** that is currently being used by IP for this **/
/** destination. **/
/** This is case number 2 **/
/* Insert the new entry as a new next hop for */
/* this destination. */
ip_cmn_rte_next_hop_add (curr_entry, next_hop, metric, &port_info);
/* Set the last update time. */
if (oms_routing_convergence_status_check (route_table->convg_handle) == OmsC_Convergence_Reached)
{
ip_cmn_rte_table_dest_prefix_print (dest_str, dest_prefix);
ip_cmn_rte_proto_name_print (src_proto_str, proto);
if (!strcmp (src_proto_str, "Direct"))
strcpy (src_proto_str, "Local");
sprintf(convergence_reason,
"Added %s route to destination %s.", src_proto_str, dest_str);
ip_cmn_rte_table_last_update_time_set (route_table, convergence_reason);
}
else
{
ip_cmn_rte_table_last_update_time_set (route_table, OPC_NIL);
}
/* The type of redistribution is different */
/* in the case of directly connected routes */
/* so determine if this route is directly */
/* connected and set the redist type */
/* accordingly. */
if (IP_CMN_RTE_TABLE_PROTOCOL_IS_DIRECT (curr_entry->route_src_proto))
redist_type = IPC_REDIST_TYPE_UPDATE_DIRECT;
else
redist_type = IPC_REDIST_TYPE_UPDATE;
/* The protocol which sources this route */
/* has not changed, so the remove proto */
/* should be set to INVALID. */
removed_proto = IpC_Dyn_Rte_Invalid;
/* Redistribute an update message to other */
/* protocols advertising the new next hop */
ip_cmn_rte_table_entry_redistribute (route_table, curr_entry, redist_type, removed_proto);
/* Check if this entry is being used to resolve */
/* a default network route. */
if (ip_cmn_rte_table_entry_default_ntwk_flag_is_set (curr_entry))
{
/* It is possible that the new next hop */
/* caused the metric to improve. Call the */
/* function that will update the default */
/* network route. */
ip_cmn_rte_table_default_network_route_update (route_table, curr_entry);
}
FRET (OPC_COMPCODE_SUCCESS);
}
else if (curr_entry->admin_distance > admin_distance)
{
/* Entry being added has a better (lower) */
/* admin distance than the entry currently in */
/* the route table. This is case number 3 and 3A*/
if (curr_entry->admin_distance != OPC_INT_INFINITY)
{
/* The current entry isn't being replaced */
/* When Route_Delete is called and there */
/* is a backup routing protocol, the */
/* admin distance is set to infinity as a */
/* means of poisoning this protocol. IP */
/* then calls the backup routing protocols */
/* install proc which in turn calls */
/* Entry_Add. This essentially removes */
/* the no longer available protocols route */
/* Place the current entry in the backup */
/* list. */
/* TODO: should we free port info */
/* in this case also? */
ip_cmn_rte_enter_backup (curr_entry, curr_entry->route_src_proto,
curr_entry->admin_distance, curr_entry->route_src_obj_ptr);
}
/* The routing protocol which sources this route*/
/* is changing. Set the removed_proto to be */
/* the original protocol. */
/* This needs to be set before the route entry */
/* is replaced in the route table. */
if (((curr_entry->admin_distance == OPC_INT_INFINITY) && (proto_type == IPC_DYN_RTE_DIRECTLY_CONNECTED)) ||
(proto_type != IPC_DYN_RTE_DIRECTLY_CONNECTED))
{
removed_proto = curr_entry->route_src_proto;
}
else
removed_proto = IpC_Dyn_Rte_Invalid;
/* Replace the current entry w/ the new entry. */
ip_cmn_rte_entry_replace (route_table, src_obj_ptr, dest_prefix,
next_hop, port_info, metric, proto, admin_distance, curr_entry);
/* Set the last update time. */
if (oms_routing_convergence_status_check (route_table->convg_handle) == OmsC_Convergence_Reached)
{
ip_cmn_rte_table_dest_prefix_print (dest_str, dest_prefix);
ip_cmn_rte_proto_name_print (src_proto_str, proto);
if (!strcmp (src_proto_str, "Direct"))
strcpy (src_proto_str, "Local");
sprintf(convergence_reason,
"Added %s route to destination %s", src_proto_str, dest_str);
ip_cmn_rte_table_last_update_time_set (route_table, convergence_reason);
}
else
{
ip_cmn_rte_table_last_update_time_set (route_table, OPC_NIL);
}
/* The type of redistribution is different */
/* in the case of directly connected routes */
/* so determine if this route is directly */
/* connected and set the redist type */
/* accordingly. */
if (IP_CMN_RTE_TABLE_PROTOCOL_IS_DIRECT (curr_entry->route_src_proto))
redist_type = IPC_REDIST_TYPE_UPDATE_DIRECT;
else
redist_type = IPC_REDIST_TYPE_UPDATE;
/* Redistribute an update message to other */
/* protocols with the changed information */
/* for this destination. */
ip_cmn_rte_table_entry_redistribute (route_table, curr_entry, redist_type, removed_proto);
/* The administrative distance of an entry has improved. If */
/* this entry is used to resolve a default network route, */
/* the administrative distance of the default network route */
/* also has to be updated. */
if (ip_cmn_rte_table_entry_default_ntwk_flag_is_set (curr_entry))
{
ip_cmn_rte_table_default_network_route_update (route_table, curr_entry);
}
}
else
{
/** Existing entry has the better (lower) admin **/
/** distance. **/
/** This is case number 4 and 4A **/
/* Insert the new entry into the list of */
/* backup routes. */
ip_cmn_rte_enter_backup (curr_entry, proto, admin_distance, src_obj_ptr);
/* Some additional work needs to be done if this is a */
/* VRF table entry. If this backup entry is promoted to */
/* be the primary entry, the routing protocol is */
/* invoked (via install_proc) to add the route again. */
/* A fresh port_info object with top and bottom labels */
/* will be generated then. The current MPLS label in */
/* the port info can be freed now. */
if (ip_rte_port_info_contains_mpls_info (&port_info))
ip_cmn_rte_table_port_info_free (&port_info, route_table);
/* If the route is to a directly connected */
/* destination, we still need to send */
/* redistribution interrupts. */
if (IP_CMN_RTE_TABLE_PROTOCOL_IS_DIRECT (curr_entry->route_src_proto))
{
/* if the route which is in the */
/* table currently is a directly connected */
/* route, then the protocol sourcing the */
/* new route must redistribute this route */
/* into other protocols. */
/* In this case, there is only one type of */
/* redistribution. If the route does get */
/* redistributed, it will be for a directly */
/* connected route and an update. */
redist_type = IPC_REDIST_TYPE_UPDATE_DIRECT;
/* The protocol which sources this route */
/* has not changed, so the remove proto */
/* should be set to INVALID. */
removed_proto = IpC_Dyn_Rte_Invalid;
/* Redistribute an update message to other */
/* protocols with the changed information */
/* for this destination. */
/* This route should only be redistributed */
/* if it is a directly connected route. In */
/* all other cases, the backup list does not*/
/* affect redistribution. */
ip_cmn_rte_table_entry_redistribute (route_table, curr_entry, redist_type, removed_proto);
}
}
FRET (OPC_COMPCODE_SUCCESS);
}
}
else
{
/** A custom routing protocol is adding an entry. **/
/* Use the keep route option to make sure that we do */
/* not blindly overwrite the existing entry. */
new_ptree_entry = oms_ptree_entry_add (ptree_ptr, address,
ip_cmn_rte_table_dest_prefix_mask_len_get (dest_prefix),
OPC_NIL, OMSC_PTREE_ADD_KEEP_ROUTE, &curr_ptree_entry);
/* If the entry already exists, don't add it. */
if (PRGC_NIL != curr_ptree_entry)
{
FRET (OPC_COMPCODE_FAILURE);
}
}
/** There was no existing entry found in the route table to **/
/** this destination. Create a new entry and add it to the **/
/** table. Then redistribute it to other protocols as a **/
/** new route. **/
/** This is case number 1 **/
/* Increment the number of entries in the route table. */
++(route_table->num_entries);
if (oms_routing_convergence_status_check (route_table->convg_handle) == OmsC_Convergence_Reached)
{
ip_cmn_rte_table_dest_prefix_print (dest_str, dest_prefix);
ip_cmn_rte_proto_name_print (src_proto_str, proto);
if (!strcmp (src_proto_str, "Direct"))
strcpy (src_proto_str, "Local");
sprintf(convergence_reason,
"Added %s route to destination %s", src_proto_str, dest_str);
ip_cmn_rte_table_last_update_time_set (route_table, convergence_reason);
}
else
{
ip_cmn_rte_table_last_update_time_set (route_table, OPC_NIL);
}
/* Create a new IpT_Cmn_Rte_Table_Entry structure */
route_entry = ip_cmn_rte_table_entry_create (dest_prefix, proto, admin_distance, src_obj_ptr);
/* Make the first entry in the "next_hop" list for the new */
/* entry the new route. */
ip_cmn_rte_next_hop_add (route_entry, next_hop, metric, &port_info);
/* Set this structure as the src object in the new ptree*/
/* structure. */
oms_ptree_entry_src_obj_set (new_ptree_entry, route_entry);
/* Update statistics for this route table. */
op_stat_write (route_table->update_stathandle [IpC_Rte_Table_Entry_Add], 1.0);
op_stat_write (route_table->update_stathandle [IpC_Rte_Table_Any_Update], 1.0);
op_stat_write (route_table->update_stathandle [IpC_Rte_Table_Size], (double) route_table->num_entries);
/* Print trace information. */
#ifndef OPD_NO_DEBUG
if (op_prg_odb_ltrace_active ("ip_cmn_rte_table"))
{
/* Re-use the destination and protocol */
/* strings if created previously. */
ip_cmn_rte_table_dest_prefix_print (dest_str, dest_prefix);
ip_cmn_rte_proto_name_print (src_proto_str, proto);
inet_address_print (nh_str, next_hop);
/* And now the full message. */
sprintf (trace_msg,
"Dest |%s|, Next Hop |%s|, O/P Intf. |%d|, Metric |%d| and Src. Proto. |%s|.",
dest_str, nh_str, ip_rte_intf_tbl_index_from_port_info_get (route_table->iprmd_ptr, port_info),
metric, src_proto_str);
op_prg_odb_print_major ("Adding the following route to the Common IP Routing Table:", OPC_NIL);
op_prg_odb_print_minor (trace_msg, OPC_NIL);
}
#endif
/* In this case, there is only one type of */
/* redistribution. This is a new route, so the type*/
/* will be an ADD. */
redist_type = IPC_REDIST_TYPE_ADD;
/* Since there was no route in the table previously */
/* there is no route which can be withdrawn. */
removed_proto = IpC_Dyn_Rte_Invalid;
/* Redistribute this route as a new route to other */
/* routing protocols running on this node. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -