diff options
Diffstat (limited to 'hicn-light/src/hicn/core/pit.c')
-rw-r--r-- | hicn-light/src/hicn/core/pit.c | 227 |
1 files changed, 227 insertions, 0 deletions
diff --git a/hicn-light/src/hicn/core/pit.c b/hicn-light/src/hicn/core/pit.c new file mode 100644 index 000000000..fa54e2429 --- /dev/null +++ b/hicn-light/src/hicn/core/pit.c @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2017-2020 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * The pending interest table. + * + * Interest aggregation strategy: + * - The first Interest for a name is forwarded + * - A second Interest for a name from a different reverse path may be + * aggregated + * - A second Interest for a name from an existing Interest is forwarded + * - The Interest Lifetime is like a subscription time. A reverse path entry is + * removed once the lifetime is exceeded. + * - Whan an Interest arrives or is aggregated, the Lifetime for that reverse + * hop is extended. As a simplification, we only keep a single lifetime not per + * reverse hop. + * + */ + +#include <assert.h> +#include <stdio.h> +#define __STDC_FORMAT_MACROS +#include <inttypes.h> + +#include <hicn/core/msgbuf.h> +#include <hicn/base/pool.h> +#include <hicn/core/ticks.h> +#include <hicn/util/log.h> + +#include "pit.h" + +// XXX TODO Should not be defined here +#define DEFAULT_INTEREST_LIFETIME 4000000000ULL + +static Ticks _pit_calculate_lifetime(pit_t * pit, + msgbuf_t *interest_msgbuf) { + uint64_t interestLifetimeTicks = + msgbuf_get_interest_lifetime(interest_msgbuf); + if (interestLifetimeTicks == 0) { + interestLifetimeTicks = NSEC_TO_TICKS(DEFAULT_INTEREST_LIFETIME); + } + + Ticks expiry_time = ticks_now() + interestLifetimeTicks; + return expiry_time; +} + +// max_elts default is 65535 +pit_t * +pit_create(size_t max_elts) +{ + pit_t * pit = malloc(sizeof(pit_t)); + if (!pit) + return NULL; + + pool_init(pit->entries, max_elts); + pit->index_by_name = kh_init(pit_name); + + DEBUG("PIT %p created", pit); + + return pit; +} + +void +pit_free(pit_t * pit) +{ + assert(pit); + // XXX TODO + + DEBUG("PIT %p destroyed", pit); +} + +pit_verdict_t +pit_on_interest(pit_t * pit, msgbuf_t * interest_msgbuf) +{ + assert(pit); + assert(interest_msgbuf); + assert(msgbuf_get_type(interest_msgbuf) == MESSAGE_TYPE_INTEREST); + + fib_entry_t * fib_entry; + Ticks expiry_time; + + /* Lookup entry by name */ + khiter_t k = kh_get_pit_name(pit->index_by_name, msgbuf_get_name(interest_msgbuf)); + if (k == kh_end(pit->index_by_name)) + goto NOT_FOUND; + pit_entry_t * entry = pit->entries + kh_val(pit->index_by_name, k); + assert(entry); + + // has it expired? + if (ticks_now() >= pit_entry_get_expiry_time(entry)) + goto TIMEOUT; + + /* Extend entry lifetime */ + expiry_time = _pit_calculate_lifetime(pit, interest_msgbuf); + if (expiry_time > pit_entry_get_expiry_time(entry)) + pit_entry_set_expiry_time(entry, expiry_time); + + unsigned connection_id = msgbuf_get_connection_id(interest_msgbuf); + + // Is the reverse path already in the PIT entry? + if (pit_entry_ingress_contains(entry, connection_id)) { + // It is already in the PIT entry, so this is a retransmission, so + // forward it. + DEBUG("Message %p existing entry (expiry %" PRIu64 ") and reverse path, forwarding", + interest_msgbuf, pit_entry_get_expiry_time(entry)); + return PIT_VERDICT_RETRANSMIT; + } + + // It is in the PIT but this is the first interest for the reverse path + pit_entry_ingress_add(entry, connection_id); + + DEBUG("Message %p existing entry (expiry %" PRIu64 ") and reverse path is new, aggregate", + interest_msgbuf, pit_entry_get_expiry_time(entry)); + return PIT_VERDICT_AGGREGATE; + +TIMEOUT: + fib_entry = pit_entry_get_fib_entry(entry); + if (fib_entry) + fib_entry_on_timeout(fib_entry, pit_entry_get_egress(entry)); + + // it's an old entry, remove it + k = kh_get(pit_name, pit->index_by_name, msgbuf_get_name(interest_msgbuf)); + if (k != kh_end(pit->index_by_name)) + kh_del(pit_name, pit->index_by_name, k); + +NOT_FOUND: + /* Create PIT entry */ + + expiry_time = _pit_calculate_lifetime(pit, interest_msgbuf); + + pit_allocate(pit, entry, interest_msgbuf); + pit_entry_from_msgbuf(entry, interest_msgbuf, expiry_time, ticks_now()); + + DEBUG("Message %p added to PIT (expiry %" PRIu64 ") ingress %u", + interest_msgbuf, pit_entry_get_expiry_time(entry), + msgbuf_get_connection_id(interest_msgbuf)); + + return PIT_VERDICT_FORWARD; +} + +nexthops_t * +pit_on_data(pit_t * pit, const msgbuf_t * data_msgbuf) +{ + assert(pit); + assert(data_msgbuf); + assert(msgbuf_get_type(data_msgbuf) == MESSAGE_TYPE_DATA); + + nexthops_t * nexthops = NULL; + + /* Lookup entry by name */ + khiter_t k = kh_get_pit_name(pit->index_by_name, msgbuf_get_name(data_msgbuf)); + if (k == kh_end(pit->index_by_name)) + goto NOT_FOUND; + + pit_entry_t * entry = pit->entries + kh_val(pit->index_by_name, k); + assert(entry); + + // here we need to check if the PIT entry is expired + // if so, remove the PIT entry. + Ticks now = ticks_now(); + if (now >= pit_entry_get_expiry_time(entry)) + goto TIMEOUT; + + /* PIT entry is not expired, use it */ + fib_entry_t * fib_entry = pit_entry_get_fib_entry(entry); + if (fib_entry) + fib_entry_on_data(fib_entry, pit_entry_get_egress(entry), + data_msgbuf, pit_entry_get_creation_time(entry), ticks_now()); + + // XXX TODO : be sure nexthops are valid b/c pit entry is removed + // XXX TODO eventually pass holding structure as parameter + nexthops = pit_entry_get_ingress(entry); + +TIMEOUT: + /* Remove entry from PIT */ + kh_del(pit_name, pit->index_by_name, k); + +NOT_FOUND: + return nexthops; +} + +void +pit_remove(pit_t * pit, const msgbuf_t * interest_msgbuf) +{ + assert(pit); + assert(interest_msgbuf); + assert(msgbuf_get_type(interest_msgbuf) == MESSAGE_TYPE_INTEREST); + + khiter_t k = kh_get(pit_name, pit->index_by_name, msgbuf_get_name(interest_msgbuf)); + if (k == kh_end(pit->index_by_name)) + return; + //off_t index = kh_val(pit->index_by_name, k); + //pit_entry_t * entry = pit_at(pit, index); + kh_del(pit_name, pit->index_by_name, k); + + DEBUG("Message %p removed from PIT", interest_msgbuf); +} + +pit_entry_t * +pit_lookup(const pit_t * pit, const msgbuf_t * interest_msgbuf) +{ + assert(pit); + assert(interest_msgbuf); + assert(msgbuf_get_type(interest_msgbuf) == MESSAGE_TYPE_INTEREST); + + khiter_t k = kh_get(pit_name, pit->index_by_name, + msgbuf_get_name(interest_msgbuf)); + if (k == kh_end(pit->index_by_name)) + return NULL; + off_t index = kh_val(pit->index_by_name, k); + pit_entry_t * entry = pit_at(pit, index); + assert(entry); + + return entry; +} |