📄 sctp_route.c
字号:
/***************************************************************************** @(#) sctp_route.c,v 0.7.8.1 2001/12/11 13:26:34 brian Exp ----------------------------------------------------------------------------- Copyright (C) 2001 OpenSS7 Corporation <http://www.openss7.com> All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ----------------------------------------------------------------------------- U.S. GOVERNMENT RESTRICTED RIGHTS. If you are licensing this Software on behalf of the U.S. Government ("Government"), the following provisions apply to you. If the Software is supplied by the Department of Defense ("DoD"), it is classified as "Commercial Computer Software" under paragraph 252.227-7014 of the DoD Supplement to the Federal Acquisition Regulations ("DFARS") (or any successor regulations) and the Government is acquiring only the license rights granted herein (the license rights customarily provided to non-Government users). If the Software is supplied to any unit or agency of the Government other than DoD, it is classified as "Restricted Computer Software" and the Government's rights in the Software are defined in paragraph 52.227-19 of the Federal Acquisition Regulations ("FAR") (or any success regulations) or, in the cases of NASA, in paragraph 18.52.227-86 of the NASA Supplement to the FAR (or any successor regulations). ----------------------------------------------------------------------------- Last Modified 2001/12/11 13:26:34 by brian *****************************************************************************/#ident "@(#) sctp_route.c,v 0.7.8.1 2001/12/11 13:26:34 brian Exp"static char const ident[] = "SS7AlphaRelease(0.7.8.1) 2001/12/11 13:26:34";#define __NO_VERSION__#include <linux/config.h>#include <linux/version.h>#include <linux/modversions.h>#include <linux/module.h>#include <sys/stream.h>#include <sys/stropts.h>#include <sys/cmn_err.h>#include <sys/dki.h>#include "sctp_debug.h"#include "sctp_bufq.h"#include "sctp.h"#include "sctp_defs.h"#include "sctp_cache.h"#include "sctp_route.h"#include "sctp_output.h"#undef min /* LiS should not have defined these */#undef max /* LiS should not have defined these */#define sctp_daddr sctp_daddr__#define sctp_saddr sctp_saddr__#define sctp_strm sctp_strm__#ifdef ASSERT#undef ASSERT#endif#include <net/ip.h>#include <net/icmp.h>#include <net/route.h>#undef sctp_daddr#undef sctp_saddr#undef sctp_strm#ifdef ASSERT#undef ASSERT#endif/* * ========================================================================= * * IP OUTPUT: ROUTING FUNCTIONS * * ========================================================================= * * MULTI-HOMED IP ROUTING FUNCTIONS * * ------------------------------------------------------------------------- * * CHOSE BEST * ------------------------------------------------------------------------- * This function is called by sctp_update_routes to choose the best primary * and secondary addresses. We alway return a usable address if possible, * even if the secondary is not different from the primary. This is called * only when a route fails or a destination goes inactive due to too many * timeouts, so destinations that are timing out are not so large a factor. */static sctp_daddr_t *sctp_choose_best(sp, not) sctp_t *sp; sctp_daddr_t *not;{ sctp_daddr_t *best, *sd; assert(sp); if ( (best = sp->daddr) ) for ( sd = best->next; sd; sd = sd->next ) { /* choose usable over unusable */ if ( !best->dst_cache && sd->dst_cache ) { best = sd; continue; } /* choose active routes */ if ( best->retransmits > best->max_retrans && sd->retransmits <= sd->max_retrans ) { best = sd; continue; } /* choose routes without timeouts */ if ( best->retransmits && !(sd->retransmits) ) { best = sd; continue; } /* choose routes without dups */ if ( best->dups && !(sd->dups) ) { best = sd; continue; } /* choose usable alternate if possible */ if ( best == not && sd != not ) { best = sd; continue; } /* choose routes with least excessive timeouts */ if ( best->retransmits + sd->max_retrans > sd->retransmits + best->max_retrans ) { best = sd; continue; } /* choose routes with the least duplicates */ if ( best->dups > sd->dups ) { best = sd; continue; } /* choose lowest rto */ if ( best->rto > sd->rto ) { best = sd; continue; } /* choose not to slow start */ if ( best->cwnd <= best->ssthresh && sd->cwnd > sd->ssthresh ) { best = sd; continue; } /* choose largest available window */ if ( best->cwnd + best->mtu - 1 - best->in_flight < sd->cwnd + sd->mtu - 1 - sd->in_flight ) { best = sd; continue; } } return (best);}/* * UPDATE ROUTES * ------------------------------------------------------------------------- * This function is called whenever there is a routing problem or whenever a * timeout occurs on a destination. It's purpose is to perform a complete * re-analysis of the available destination addresses and IP routing and * establish new routes as required and set the (primary) and (secondary) * destination addresses. */#ifndef sysctl_ip_dynaddr#define sysctl_ip_dynaddr 0#elseextern int sysctl_ip_dynaddr;#endif/* * sysctl_ip_dynaddr: this symbol is normally not exported, but we exported * for the Linux Native version of SCTP, so we may have to treat it as extern * here... */int sctp_update_routes(sp, force_reselect) sctp_t *sp; int force_reselect;{ int err = -EHOSTUNREACH; int mtu_changed = 0; int viable_route = 0; int route_changed = 0; sctp_daddr_t *sd; sctp_daddr_t *taddr, *raddr; int old_pmtu; assert( sp ); ensure( sp->daddr, return(-EFAULT) ); old_pmtu = xchg(&sp->pmtu, 5000); /* big enough? */ taddr = sp->taddr; raddr = sp->raddr; /* * First we check our cached routes.. */ for ( sd = sp->daddr; sd; sd = sd->next ) { struct rtable *rt = (struct rtable *)sd->dst_cache; if ( rt && rt->u.dst.obsolete ) { rare(); sd->dst_cache = NULL; ip_rt_put(rt); sd->saddr = 0; route_changed = 1; } if ( !rt ) { if ( sd->dif ) sd->saddr = 0; if ( (err = ip_route_connect(&rt, sd->daddr, sd->saddr, RT_TOS(sp->ip_tos)|RTO_CONN|sp->ip_dontroute, sd->dif)) < 0 ) { rare(); continue; } if ( rt->rt_flags & (RTCF_MULTICAST|RTCF_BROADCAST) && !sp->ip_broadcast ) { rare(); ip_rt_put(rt); err = -ENETUNREACH; continue; } sd->saddr = rt->rt_src; if ( !sctp_find_saddr(sp, sd->saddr) ) { rare(); if ( !sp->saddr ) { rare(); ip_rt_put(rt); assure( sp->saddr ); err = -EADDRNOTAVAIL; continue; } sd->saddr = sp->saddr->saddr; } /* always revert to initial settings when rerouting */ sd->rto = sp->rto_ini; sd->rttvar = 0; sd->srtt = 0; sd->mtu = rt->u.dst.pmtu; sd->ssthresh = 2*rt->u.dst.pmtu; sd->cwnd = rt->u.dst.pmtu; sd->dst_cache = &rt->u.dst; route_changed = 1; } /* You're welcome diald! */ if ( sysctl_ip_dynaddr && sp->s_state == SCTP_COOKIE_WAIT && sd == sp->daddr ) { /* see if route changed on primary as result of INIT * that was discarded */ struct rtable *rt2 = NULL; if ( !ip_route_connect(&rt2, rt->rt_dst, 0, RT_TOS(sp->ip_tos)|sp->ip_dontroute, sd->dif) ) { if ( rt2->rt_src != rt->rt_src ) { rare(); rt2 = xchg(&rt, rt2); sd->rto = sp->rto_ini; sd->rttvar = 0; sd->srtt = 0; sd->mtu = rt->u.dst.pmtu; sd->ssthresh = 2*rt->u.dst.pmtu; sd->cwnd = rt->u.dst.pmtu; sd->dst_cache = &rt->u.dst; route_changed = 1; } ip_rt_put(rt2); } } viable_route = 1; /* always update MTU if we have a viable route */ if ( sd->mtu != rt->u.dst.pmtu ) { sd->mtu = rt->u.dst.pmtu; mtu_changed = 1; rare(); } if ( sp->pmtu > sd->mtu ) sp->pmtu = sd->mtu; } if ( !viable_route ) { rare(); /* set defaults */ sp->taddr = sp->daddr; sp->raddr = sp->daddr->next?sp->daddr->next:sp->daddr; sp->pmtu = 576; return(err); } /* if we have made or need changes then we want to reanalyze routes */ if ( force_reselect || route_changed || mtu_changed || sp->pmtu != old_pmtu || !sp->taddr || !sp->raddr ) {#ifdef _DEBUG#ifdef ERROR_GENERATOR int bad_choice = 0;#endif#endif sp->taddr = sctp_choose_best(sp, NULL); usual( sp->taddr );#ifdef _DEBUG#ifdef ERROR_GENERATOR if ( (sp->options & SCTP_OPTION_BREAK) && ( sp->taddr == sp->daddr || sp->taddr == sp->daddr->next ) && sp->taddr->packets > BREAK_GENERATOR_LEVEL ) { ptrace(("Primary sp->taddr %03d.%03d.%03d.%03d chosen poorly on %x\n", (sp->taddr->daddr>> 0)&0xff, (sp->taddr->daddr>> 8)&0xff, (sp->taddr->daddr>>16)&0xff, (sp->taddr->daddr>>24)&0xff, (uint)sp )); bad_choice = 1; }#endif#endif#if 0if ( sp->taddr && sp->taddr != taddr ) ptrace(("sp = %u, New primary route: %d.%d.%d.%d\n", (uint)sp, (sp->taddr->daddr>> 0)&0xff, (sp->taddr->daddr>> 8)&0xff, (sp->taddr->daddr>>16)&0xff, (sp->taddr->daddr>>24)&0xff));#endif sp->raddr = sctp_choose_best(sp, sp->taddr); usual( sp->raddr );#ifdef _DEBUG#ifdef ERROR_GENERATOR if ( (sp->options & SCTP_OPTION_BREAK) && ( sp->raddr == sp->daddr || sp->raddr == sp->daddr->next ) && sp->raddr->packets > BREAK_GENERATOR_LEVEL ) { ptrace(("Secondary sp->raddr %03d.%03d.%03d.%03d chosen poorly on %x\n", (sp->raddr->daddr>> 0)&0xff, (sp->raddr->daddr>> 8)&0xff, (sp->raddr->daddr>>16)&0xff, (sp->raddr->daddr>>24)&0xff, (uint)sp )); bad_choice = 1; } if ( bad_choice ) { for ( sd = sp->daddr; sd; sd = sd->next ) { printk(KERN_INFO "%03d.%03d.%03d.%03d: %x, %u:%u, %u, %lu, %u:%u, %u, %u\n", (sd->daddr>> 0)&0xff, (sd->daddr>> 8)&0xff, (sd->daddr>>16)&0xff, (sd->daddr>>24)&0xff, (uint)sd->dst_cache, sd->retransmits, sd->max_retrans, sd->dups, sd->rto, sd->cwnd, sd->ssthresh, sd->mtu, sd->in_flight); } }#endif#endif#if 0if ( sp->raddr && sp->raddr != raddr ) ptrace(("sp = %u, New secondary route: %d.%d.%d.%d\n", (uint)sp, (sp->raddr->daddr>> 0)&0xff, (sp->raddr->daddr>> 8)&0xff, (sp->raddr->daddr>>16)&0xff, (sp->raddr->daddr>>24)&0xff));#endif } return(0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -