uint32_t find_prefix(StorageIterator first, StorageIterator last) { // @see prime2325::max_block_size() uint32_t size = sak::storage_size(first, last); assert(size <= m_max_block_size); assert(size > 0); uint32_t prefix = 0; for(uint32_t k = 0; k < m_k_pass; ++k) { update_buckets(first, last, k, prefix); update_prefix(k, &prefix); } return prefix; }
void update_range(int l, int r, ll val) { // v[l..r] += val update_prefix(l - 1, -val); update_prefix(r, val); }
//void //update_ia(iatype, ialist, ifp, serverid, authparam) void update_ia( iatype_t iatype, struct dhcp6_list *ialist, struct dhcp6_if *ifp, struct duid *serverid, struct authparam *authparam) { struct ia *ia; struct ia_conf *iac; struct iapd_conf *iapdc; struct iana_conf *ianac; struct dhcp6_listval *iav, *siav; struct timeval timo; /* iav指向的是一个具体的节点,该节点的内容则是在iav->val_ia中给出 */ for (iav = TAILQ_FIRST(ialist); iav; iav = TAILQ_NEXT(iav, link)) { /* if we're not interested in this IA, ignore it. */ /* 根据配置文件中的配置来判断是否这个iac存在 */ if ((iac = find_iaconf(&ifp->iaconf_list, iatype, iav->val_ia.iaid)) == NULL) { continue; } /* validate parameters */ /* * If a client receives an IA_NA with T1 greater than T2, and * both T1 and T2 are greater than 0, the client discards the * IA_NA option and processes the remainder of the message as * though the server had not included the invalid IA_NA option. * [RFC3315 22.4] * We apply the same rule to IA_PD as well. */ if (iav->val_ia.t2 != 0 && iav->val_ia.t1 > iav->val_ia.t2) { dprintf(LOG_INFO, FNAME, "invalid IA: T1(%lu) > T2(%lu)", iav->val_ia.t1, iav->val_ia.t2); continue; } /* locate the local IA or make a new one */ ia = get_ia(iatype, ifp, iac, iav, serverid); if (ia == NULL) { dprintf(LOG_WARNING, FNAME, "failed to get an IA " "type: %s, ID: %u", iastr(iac->type), iac->iaid); continue; } /* update authentication parameters */ if (update_authparam(ia, authparam)) { dprintf(LOG_WARNING, FNAME, "failed to update " "authentication param for IA " "type: %s, ID: %u", iastr(iac->type), iac->iaid); remove_ia(ia); continue; } /* update IA configuration information */ for (siav = TAILQ_FIRST(&iav->sublist); siav; siav = TAILQ_NEXT(siav, link)) { switch (siav->type) { case DHCP6_LISTVAL_PREFIX6: /* add or update the prefix */ iapdc = (struct iapd_conf *)iac; if (update_prefix(ia, &siav->val_prefix6, &iapdc->iapd_pif_list, ifp, &ia->ctl, callback)) { dprintf(LOG_NOTICE, FNAME, "failed to update a prefix %s/%d", in6addr2str(&siav->val_prefix6.addr, 0), siav->val_prefix6.plen); } break; case DHCP6_LISTVAL_STATEFULADDR6: ianac = (struct iana_conf *)iac; if (update_address(ia, &siav->val_statefuladdr6, ifp, &ia->ctl, callback)) { dprintf(LOG_NOTICE, FNAME, "failed to update an address %s", in6addr2str(&siav->val_statefuladdr6.addr, 0)); } break; case DHCP6_LISTVAL_STCODE: dprintf(LOG_INFO, FNAME, "status code for %s-%lu: %s", iastr(iatype), iav->val_ia.iaid, dhcp6_stcodestr(siav->val_num16)); if ((ia->state == IAS_RENEW || ia->state == IAS_REBIND) && siav->val_num16 == DH6OPT_STCODE_NOBINDING) { /* * For each IA in the original Renew or * Rebind message, the client * sends a Request message if the IA * contained a Status Code option * with the NoBinding status. * [RFC3315 18.1.8] * XXX: what about the PD case? */ dprintf(LOG_INFO, FNAME, "receive NoBinding against " "renew/rebind for %s-%lu", iastr(ia->conf->type), ia->conf->iaid); reestablish_ia(ia); goto nextia; } break; default: dprintf(LOG_ERR, FNAME, "impossible case"); goto nextia; } } /* see if this IA is still valid. if not, remove it. */ if (ia->ctl == NULL || !(*ia->ctl->isvalid)(ia->ctl)) { dprintf(LOG_DEBUG, FNAME, "IA %s-%lu is invalidated", iastr(ia->conf->type), ia->conf->iaid); remove_ia(ia); continue; } /* if T1 or T2 is 0, determine appropriate values locally. */ if (ia->t1 == 0 || ia->t2 == 0) { u_int32_t duration; if (ia->ctl && ia->ctl->duration) duration = (*ia->ctl->duration)(ia->ctl); else duration = 1800; /* 30min. XXX: no rationale */ if (ia->t1 == 0) { if (duration == DHCP6_DURATION_INFINITE) ia->t1 = DHCP6_DURATION_INFINITE; else ia->t1 = duration / 2; } if (ia->t2 == 0) { if (duration == DHCP6_DURATION_INFINITE) ia->t2 = DHCP6_DURATION_INFINITE; else ia->t2 = duration * 4 / 5; } /* make sure T1 <= T2 */ if (ia->t1 > ia->t2) ia->t1 = ia->t2 * 5 / 8; dprintf(LOG_INFO, FNAME, "T1(%lu) and/or T2(%lu) " "is locally determined", ia->t1, ia->t2); } /* * Be proactive for too-small timeout values. Note that * the adjusted values may make some information expire * without renewal. */ if (ia->t2 < DHCP6_DURATION_MIN) { dprintf(LOG_INFO, FNAME, "T1 (%lu) or T2 (%lu) " "is too small", ia->t1, ia->t2); ia->t2 = DHCP6_DURATION_MIN; ia->t1 = ia->t2 * 5 / 8; dprintf(LOG_INFO, "", " adjusted to %lu and %lu", ia->t1, ia->t2); } /* set up a timer for this IA. */ if (ia->t1 == DHCP6_DURATION_INFINITE) { if (ia->timer) dhcp6_remove_timer(&ia->timer); } else { if (ia->timer == NULL) ia->timer = dhcp6_add_timer(ia_timo, ia); if (ia->timer == NULL) { dprintf(LOG_ERR, FNAME, "failed to add IA timer"); remove_ia(ia); /* XXX */ continue; } timo.tv_sec = ia->t1; timo.tv_usec = 0; loginfo(FUNC, "set renew time: %d second", timo.tv_sec); dhcp6_set_timer(&timo, ia->timer); } /* 更新这个ia的状态为ACTIVE,接下来就可以使用renew来更新了 */ ia->state = IAS_ACTIVE; nextia: ; } }