From 40b50b6618d3de2da3f0b1d5cb78f2bc277c7f20 Mon Sep 17 00:00:00 2001 From: Christian Franke Date: Mon, 16 Dec 2013 15:00:28 +0100 Subject: isisd: first feeble attempt at redistribute --- isisd/isis_lsp.c | 138 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 136 insertions(+), 2 deletions(-) (limited to 'isisd/isis_lsp.c') diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c index 9bbba7fc..43170f66 100644 --- a/isisd/isis_lsp.c +++ b/isisd/isis_lsp.c @@ -35,6 +35,7 @@ #include "if.h" #include "checksum.h" #include "md5.h" +#include "table.h" #include "isisd/dict.h" #include "isisd/isis_constants.h" @@ -950,7 +951,7 @@ lsp_print_detail (struct isis_lsp *lsp, struct vty *vty, char dynhost) memcpy (in6.s6_addr, ipv6_reach->prefix, PSIZE (ipv6_reach->prefix_len)); inet_ntop (AF_INET6, &in6, (char *)buff, BUFSIZ); - if ((ipv6_reach->control_info && + if ((ipv6_reach->control_info & CTRL_INFO_DISTRIBUTION) == DISTRIBUTION_INTERNAL) vty_out (vty, " Metric : %-8d IPv6-Internal : %s/%d%s", ntohl (ipv6_reach->metric), @@ -1144,6 +1145,123 @@ lsp_next_frag (u_char frag_num, struct isis_lsp *lsp0, struct isis_area *area, return lsp; } +static void +lsp_build_ext_reach_ipv4(struct isis_lsp *lsp, struct isis_area *area, + struct tlvs *tlv_data) +{ + struct route_table *er_table; + struct route_node *rn; + struct prefix_ipv4 *ipv4; + struct isis_ext_info *info; + struct ipv4_reachability *ipreach; + struct te_ipv4_reachability *te_ipreach; + + er_table = get_ext_reach(area, AF_INET, lsp->level); + if (!er_table) + return; + + for (rn = route_top(er_table); rn; rn = route_next(rn)) + { + if (!rn->info) + continue; + + ipv4 = (struct prefix_ipv4*)&rn->p; + info = rn->info; + if (area->oldmetric) + { + if (tlv_data->ipv4_ext_reachs == NULL) + { + tlv_data->ipv4_ext_reachs = list_new(); + tlv_data->ipv4_ext_reachs->del = free_tlv; + } + ipreach = XMALLOC(MTYPE_ISIS_TLV, sizeof(*ipreach)); + + ipreach->prefix.s_addr = ipv4->prefix.s_addr; + masklen2ip(ipv4->prefixlen, &ipreach->mask); + ipreach->prefix.s_addr &= ipreach->mask.s_addr; + + if ((info->metric & 0x3f) != info->metric) + ipreach->metrics.metric_default = 0x3f; + else + ipreach->metrics.metric_default = info->metric; + ipreach->metrics.metric_expense = METRICS_UNSUPPORTED; + ipreach->metrics.metric_error = METRICS_UNSUPPORTED; + ipreach->metrics.metric_delay = METRICS_UNSUPPORTED; + listnode_add(tlv_data->ipv4_ext_reachs, ipreach); + } + if (area->newmetric) + { + if (tlv_data->te_ipv4_reachs == NULL) + { + tlv_data->te_ipv4_reachs = list_new(); + tlv_data->te_ipv4_reachs->del = free_tlv; + } + te_ipreach = + XCALLOC(MTYPE_ISIS_TLV, + sizeof(*te_ipreach) - 1 + PSIZE(ipv4->prefixlen)); + if (info->metric > MAX_WIDE_PATH_METRIC) + te_ipreach->te_metric = htonl(MAX_WIDE_PATH_METRIC); + else + te_ipreach->te_metric = htonl(info->metric); + te_ipreach->control = ipv4->prefixlen & 0x3f; + memcpy(&te_ipreach->prefix_start, &ipv4->prefix.s_addr, + PSIZE(ipv4->prefixlen)); + listnode_add(tlv_data->te_ipv4_reachs, te_ipreach); + } + } +} + +#ifdef HAVE_IPV6 +static void +lsp_build_ext_reach_ipv6(struct isis_lsp *lsp, struct isis_area *area, + struct tlvs *tlv_data) +{ + struct route_table *er_table; + struct route_node *rn; + struct prefix_ipv6 *ipv6; + struct isis_ext_info *info; + struct ipv6_reachability *ip6reach; + + er_table = get_ext_reach(area, AF_INET6, lsp->level); + if (!er_table) + return; + + for (rn = route_top(er_table); rn; rn = route_next(rn)) + { + if (!rn->info) + continue; + + ipv6 = (struct prefix_ipv6*)&rn->p; + info = rn->info; + + if (tlv_data->ipv6_reachs == NULL) + { + tlv_data->ipv6_reachs = list_new(); + tlv_data->ipv6_reachs->del = free_tlv; + } + ip6reach = XCALLOC(MTYPE_ISIS_TLV, sizeof(*ip6reach)); + if (info->metric > MAX_WIDE_PATH_METRIC) + ip6reach->metric = htonl(MAX_WIDE_PATH_METRIC); + else + ip6reach->metric = htonl(info->metric); + ip6reach->control_info = DISTRIBUTION_EXTERNAL; + ip6reach->prefix_len = ipv6->prefixlen; + memcpy(ip6reach->prefix, ipv6->prefix.s6_addr, sizeof(ip6reach->prefix)); + listnode_add(tlv_data->ipv6_reachs, ip6reach); + } +} +#endif + +static void +lsp_build_ext_reach (struct isis_lsp *lsp, struct isis_area *area, + struct tlvs *tlv_data) +{ + lsp_build_ext_reach_ipv4(lsp, area, tlv_data); +#ifdef HAVE_IPV6 + lsp_build_ext_reach_ipv6(lsp, area, tlv_data); +#endif +} + /* * Builds the LSP data part. This func creates a new frag whenever * area->lsp_frag_threshold is exceeded. @@ -1230,6 +1348,7 @@ lsp_build (struct isis_lsp *lsp, struct isis_area *area) lsp->tlv_data.hostname = XMALLOC (MTYPE_ISIS_TLV, sizeof (struct hostname)); + /* FIXME: check length of hostname */ memcpy (lsp->tlv_data.hostname->name, unix_hostname (), strlen (unix_hostname ())); lsp->tlv_data.hostname->namelen = strlen (unix_hostname ()); @@ -1478,6 +1597,8 @@ lsp_build (struct isis_lsp *lsp, struct isis_area *area) } } + lsp_build_ext_reach(lsp, area, &tlv_data); + while (tlv_data.ipv4_int_reachs && listcount (tlv_data.ipv4_int_reachs)) { if (lsp->tlv_data.ipv4_int_reachs == NULL) @@ -1485,12 +1606,25 @@ lsp_build (struct isis_lsp *lsp, struct isis_area *area) lsp_tlv_fit (lsp, &tlv_data.ipv4_int_reachs, &lsp->tlv_data.ipv4_int_reachs, IPV4_REACH_LEN, area->lsp_frag_threshold, - tlv_add_ipv4_reachs); + tlv_add_ipv4_int_reachs); if (tlv_data.ipv4_int_reachs && listcount (tlv_data.ipv4_int_reachs)) lsp = lsp_next_frag (LSP_FRAGMENT (lsp->lsp_header->lsp_id) + 1, lsp0, area, level); } + while (tlv_data.ipv4_ext_reachs && listcount (tlv_data.ipv4_ext_reachs)) + { + if (lsp->tlv_data.ipv4_ext_reachs == NULL) + lsp->tlv_data.ipv4_ext_reachs = list_new (); + lsp_tlv_fit (lsp, &tlv_data.ipv4_ext_reachs, + &lsp->tlv_data.ipv4_ext_reachs, + IPV4_REACH_LEN, area->lsp_frag_threshold, + tlv_add_ipv4_ext_reachs); + if (tlv_data.ipv4_ext_reachs && listcount (tlv_data.ipv4_ext_reachs)) + lsp = lsp_next_frag (LSP_FRAGMENT (lsp->lsp_header->lsp_id) + 1, + lsp0, area, level); + } + /* FIXME: We pass maximum te_ipv4_reachability length to the lsp_tlv_fit() * for now. lsp_tlv_fit() needs to be fixed to deal with variable length * TLVs (sub TLVs!). */ -- cgit v1.2.1