📄 hello.c
字号:
if (RT_IFAP(new_rt) && !BIT_TEST(RT_IFAP(new_rt)->ifa_state, IFS_UP)) { /* The interface is down */ goto no_export; } /* Assign default metric */ if (new_rt->rt_gwp->gw_proto == RTPROTO_AGGREGATE) { /* Originate aggregates a metric of one */ result.res_metric = HELLO_HOP; } else if (!RT_IFAP(new_rt) || BIT_TEST(RT_IFAP(new_rt)->ifa_state, IFS_LOOPBACK)) { /* Routes via the loopback interface must have an explicit metric */ result.res_metric = HELLO_UNREACHABLE; } else if (new_rt->rt_gwp->gw_proto == RTPROTO_DIRECT) { /* Interface routes */ if (BIT_TEST(RT_IFAP(new_rt)->ifa_state, IFS_POINTOPOINT)) { /* Add a hop for the P2P link */ result.res_metric = HELLO_HOP * 2; } else { /* Default to one hop */ result.res_metric = HELLO_HOP; } } else { /* Use configured default metric */ result.res_metric = hello_default_metric; } if (!export(new_rt, tp->task_rtproto, hello_export_list, ifap->ifa_ps[tp->task_rtproto].ips_export, tlp->target_gwp ? tlp->target_gwp->gw_export : (adv_entry *) 0, &result)) { /* Policy prohibits announcement */ goto no_export; } else { /* Add the interface metric */ result.res_metric += ifap->ifa_ps[tp->task_rtproto].ips_metric_out; } if (result.res_metric < HELLO_UNREACHABLE) { exportable = TRUE; } no_export: ; } /* Now that we have determined the exportablility of the new */ /* route we decide what changed need to be made. The */ /* complexity is required to surpress routing loops both */ /* within HELLO and between HELLO and other protocols. */ /* There are two types of holddowns used, the first one is */ /* called HOLDDOWN and is used when a route goes away or is */ /* overridden by a route that is not suspected to be an echo */ /* of a route we are announcing. The second is called POISON */ /* and is used when a route is overridden by a route suspected */ /* to be an echo of a route we are announcing. */ if (!tdp) { /* New route */ if (exportable) { /* and it is exportable */ /* Allocate new entry and fill it in */ TD_ALLOC(tdp); TD_TSI_SET(tlp, rth, tdp); tdp->td_rt = new_rt; rtbit_set(tdp->td_rt, tlp->target_rtbit); TD_ENQUE(tlp, tdp); set_metric++; changes++; } } else if (!new_rt) { /* No new route, just an old one */ if (!BIT_TEST(tdp->td_flags, TDF_POISON|TDF_HOLDDOWN)) { if (BIT_TEST(tdp->td_rt->rt_state, RTS_DELETE|RTS_HIDDEN)) { /* Put into holddown */ holddown++; changed++; } else { /* Poison the old route */ poison++; changed++; } } } else if (new_rt == tdp->td_rt) { /* Something has changed with the route we are announcing */ if (BIT_TEST(tdp->td_flags, TDF_POISON|TDF_HOLDDOWN)) { if (exportable) { set_metric++; changed++; } } else { if (!exportable) { poison++; changed++; } else if (tdp->td_metric != result.res_metric) { set_metric++; changed++; } } } else if (!BIT_TEST(new_rt->rt_state, RTS_PENDING)) { /* The new route is not from a holddown protocol */ if (exportable && (BIT_TEST(new_rt->rt_gwp->gw_flags, GWF_NOHOLD) || BIT_TEST(tdp->td_rt->rt_gwp->gw_flags, GWF_NOHOLD))) { /* The new route is a ``static'' route or the old route */ /* is a ``static'' route, override immediately */ set_metric++; changed++; move_bit++; } else if (BIT_TEST(tdp->td_flags, TDF_HOLDDOWN) && !BIT_TEST(tdp->td_rt->rt_gwp->gw_flags, GWF_NEEDHOLD) && !BIT_TEST(new_rt->rt_gwp->gw_flags, GWF_NEEDHOLD)) { /* No changes necessary */ changed = move_bit = 0; } else if (!BIT_TEST(tdp->td_flags, TDF_POISON|TDF_HOLDDOWN)) { /* Previously active, has been deleted */ holddown++; changed++; } else { if (exportable) { set_metric++; changed++; } else { if (!BIT_TEST(tdp->td_flags, TDF_POISON)) { poison++; changed++; } } move_bit++; } } else { /* New route is just better */ if (BIT_TEST(tdp->td_rt->rt_state, RTS_DELETE|RTS_HIDDEN)) { if (!BIT_TEST(tdp->td_flags, TDF_HOLDDOWN)) { holddown++; changed++; } } else { if (!BIT_TEST(tdp->td_flags, TDF_POISON)) { poison++; changed++; } move_bit++; } } if ((changed || set_metric) && TRACE_TP(tp, TR_POLICY)) { if (!logged) { logged++; trace_only_tp(tp, TRC_NL_BEFORE, ("hello_policy: Policy for target %A", *tlp->target_dst)); } tracef("\t%A/%A ", rth->rth_dest, rth->rth_dest_mask); } if (set_metric) { target_set_metric(tdp, result.res_metric); trace_tp(tp, TR_POLICY, 0, ("metric %u", tdp->td_metric)); } else if (holddown) { target_set_holddown(tdp, HELLO_HOLDCOUNT); trace_tp(tp, TR_POLICY, 0, ("starting holddown")); } else if (poison) { target_set_poison(tdp, HELLO_HOLDCOUNT); trace_tp(tp, TR_POLICY, 0, ("starting poison")); } else if (TRACE_TP(tp, TR_POLICY)) { trace_clear(); } if (changed) { /* Changed entries need to be at the head of the queue to */ /* make triggered updates quick */ TD_DEQUE(tdp); TD_ENQUE(tlp, tdp); changes++; } if (move_bit) { /* Move lock to new route */ rtbit_set(new_rt, tlp->target_rtbit); (void) rtbit_reset(tdp->td_rt, tlp->target_rtbit); tdp->td_rt = new_rt; } } RT_LIST_END(rth, change_list, rt_head) ; return changes;}/* * Process changes in the routing table. */static voidhello_flash __PF2(tp, task *, change_list, rt_list *){ int changes = 0; target *tlp; rt_open(tp); /* Re-evaluate policy */ TARGET_LIST(tlp, &hello_targets) { if (BIT_TEST(tlp->target_flags, TARGETF_SUPPLY)) { changes += hello_policy(tp, tlp, change_list); } } TARGET_LIST_END(tlp, &hello_targets) ; /* Close the table */ rt_close(tp, (gw_entry *)0, 0, NULL); if (changes) { /* Schedule a flash update */ hello_need_flash(tp); }}/* * Re-evaluate routing table */static voidhello_newpolicy __PF2(tp, task *, change_list, rt_list *){ /* Indicate reconfig done */ BIT_RESET(hello_flags, HELLOF_RECONFIG); /* And evaluate policy */ hello_flash(tp, change_list);}/* * Age out HELLO routes */static voidhello_age __PF2(tip, task_timer *, interval, time_t){ time_t expire_to = time_sec - HELLO_T_EXPIRE; time_t nexttime = time_sec + 1; if (expire_to > 0) { gw_entry *gwp; rt_open(tip->task_timer_task); GW_LIST(hello_gw_list, gwp) { rt_entry *rt; if (!gwp->gw_n_routes) { /* No routes for this gateway */ if (!gwp->gw_import && !gwp->gw_export && !BIT_TEST(gwp->gw_flags, GWF_SOURCE|GWF_TRUSTED)) { /* No routes, delete this gateway */ /* XXX */ } continue; } /* Age any routes for this gateway */ RTQ_LIST(&gwp->gw_rtq, rt) { if (rt->rt_time <= expire_to) { /* This route has expired */ rt_delete(rt); } else { /* This is the next route to expire */ if (rt->rt_time < nexttime) { nexttime = rt->rt_time; } break; } } RTQ_LIST_END(&gwp->gw_rtq, rt) ; } GW_LIST_END(hello_gw_list, gwp) ; rt_close(tip->task_timer_task, (gw_entry *) 0, 0, NULL); } if (nexttime > time_sec) { /* No routes to expire */ nexttime = time_sec; } task_timer_set(tip, (time_t) 0, nexttime + HELLO_T_EXPIRE - time_sec);}/* * Initialize static variables */voidhello_var_init __PF0(void){ hello_flags = HELLOF_CHOOSE; hello_default_metric = HELLO_UNREACHABLE; hello_preference = RTPREF_HELLO;}/* * Cleanup before re-init *//*ARGSUSED*/static voidhello_cleanup __PF1(tp, task *){ adv_cleanup(RTPROTO_HELLO, &hello_n_trusted, &hello_n_source, hello_gw_list, &hello_int_policy, &hello_import_list, &hello_export_list); if (tp) { trace_freeup(tp->task_trace); } trace_freeup(hello_trace_options);}static voidhello_tsi_dump __PF4(fp, FILE *, rth, rt_head *, data, void_t, pfx, const char *){ target *tlp = (target *) data; td_entry *tdp; TD_TSI_GET(tlp, rth, tdp); if (tdp) { if (BIT_TEST(tdp->td_flags, TDF_HOLDDOWN|TDF_POISON)) { (void) fprintf(fp, "%sHELLO %A <%s> remaining %#T\n", pfx, *tlp->target_dst, trace_bits(target_entry_bits, tdp->td_flags), tdp->td_metric * HELLO_T_UPDATE); } else { (void) fprintf(fp, "%sHELLO %A <%s> metric %u\n", pfx, *tlp->target_dst, trace_bits(target_entry_bits, tdp->td_flags), tdp->td_metric); } } return;}/* * Update the target list */static voidhello_target_list __PF1(jp, task_job *){ register task *tp = jp->task_job_task; int targets; flag_t target_flags = 0; static int n_targets, n_source; /* If broadcast/nobroadcast not specified, figure out if we */ /* need to broadcast packets */ if (BIT_TEST(hello_flags, HELLOF_CHOOSE)) { if (if_n_addr[AF_INET].up > 1 && inet_ipforwarding) { BIT_SET(hello_flags, HELLOF_BROADCAST); } else { BIT_RESET(hello_flags, HELLOF_BROADCAST); } } if (!hello_timer_age) { /* Create route age timer */ hello_timer_age = task_timer_create(tp, "Age", (flag_t) 0, (time_t) 0, HELLO_T_EXPIRE, hello_age, (void_t) 0); } if (BIT_TEST(hello_flags, HELLOF_SOURCE|HELLOF_BROADCAST)) { /* We are supplying updates */ /* Gateways do not listen to redirects */ redirect_disable(tp->task_rtproto); /* Make sure the timers are active */ if (!hello_timer_update) { /* Create the update timer */ hello_timer_update = task_timer_create(tp, "Update", 0, (time_t) HELLO_T_UPDATE, (time_t) HELLO_T_MAX, hello_job, (void_t) 0); } if (!hello_timer_flash) { /* Create flash update timer */ hello_timer_flash = task_timer_create(tp, "Flash", (flag_t) 0, (time_t) HELLO_T_FLASH, (time_t) HELLO_T_MAX, hello_do_flash, (void_t) 0); } } else { /* We are just listening */ /* Hosts do listen to redirects */ redirect_enable(tp->task_rtproto); /* Make sure the timers do not exist */ if (hello_timer_update) { task_timer_delete(hello_timer_update); hello_timer_update = (task_timer *) 0; } if (hello_timer_flash) { task_timer_delete(hello_timer_flash); hello_timer_flash = (task_timer *) 0; } } /* Set flags for target list build */ if (BIT_TEST(hello_flags, HELLOF_BROADCAST)) { BIT_SET(target_flags, TARGETF_BROADCAST); } if (BIT_TEST(hello_flags, HELLOF_SOURCE)) { BIT_SET(target_flags, TARGETF_SOURCE); } /* Build or update target list */ targets = target_build(tp, &hello_targets, hello_gw_list, target_flags, hello_tsi_dump); /* Allocate the send and receive buffers */ { mtu_t mtu_max = 0; target *tlp; TARGET_LIST(tlp, &hello_targets) { if (tlp->target_ifap->ifa_mtu > mtu_max) { mtu_max = tlp->target_ifap->ifa_mtu; } } TARGET_LIST_END(tlp, &hello_targets) ; task_alloc_send(tp, (size_t) mtu_max); task_alloc_recv(tp, (size_t) mtu_max + IP_MAXHDRLEN); } /* Evaluate policy for new targets */ { int changes = 0; int have_list = 0; rt_list *rthl = (rt_list *) 0; target *tlp; rt_open(tp); TARGET_LIST(tlp, &hello_targets) { if (BIT_TEST(tlp->target_flags, TARGETF_BROADCAST)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -