/* BGP Nexthop tracking
 * Copyright (C) 2013 Cumulus Networks, Inc.
 *
 * This file is part of GNU Zebra.
 *
 * GNU Zebra 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, or (at your option) any
 * later version.
 *
 * GNU Zebra 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 GNU Zebra; see the file COPYING.  If not, write to the Free
 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 * 02111-1307, USA.
 */

#include <zebra.h>

#include "command.h"
#include "thread.h"
#include "prefix.h"
#include "zclient.h"
#include "stream.h"
#include "network.h"
#include "log.h"
#include "memory.h"
#include "nexthop.h"
#include "filter.h"

#include "bgpd/bgpd.h"
#include "bgpd/bgp_table.h"
#include "bgpd/bgp_route.h"
#include "bgpd/bgp_attr.h"
#include "bgpd/bgp_nexthop.h"
#include "bgpd/bgp_debug.h"
#include "bgpd/bgp_nht.h"
#include "bgpd/bgp_fsm.h"
#include "bgpd/bgp_zebra.h"

extern struct zclient *zclient;
extern struct bgp_table *bgp_nexthop_cache_table[AFI_MAX];

static void register_nexthop(struct bgp_nexthop_cache *bnc);
static void unregister_nexthop (struct bgp_nexthop_cache *bnc);
static void evaluate_paths(struct bgp_nexthop_cache *bnc);
static int make_prefix(int afi, struct bgp_info *ri, struct prefix *p);
static void path_nh_map(struct bgp_info *path, struct bgp_nexthop_cache *bnc,
			int keep);

int
bgp_find_nexthop (struct bgp_info *path, int connected)
{
  struct bgp_nexthop_cache *bnc = path->nexthop;

  if (!bnc)
    return 0;

  if (connected && !(CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED)))
    return 0;

  return (bgp_zebra_num_connects() == 0 ||
          CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID));
}

static void
bgp_unlink_nexthop_check (struct bgp_nexthop_cache *bnc)
{
  if (LIST_EMPTY(&(bnc->paths)) && !bnc->nht_info)
    {
      if (BGP_DEBUG(nht, NHT))
	{
	  char buf[INET6_ADDRSTRLEN];
	  zlog_debug("bgp_unlink_nexthop: freeing bnc %s",
		     bnc_str(bnc, buf, INET6_ADDRSTRLEN));
	}
      unregister_nexthop(bnc);
      bnc->node->info = NULL;
      bgp_unlock_node(bnc->node);
      bnc->node = NULL;
      bnc_free(bnc);
    }
}

void
bgp_unlink_nexthop (struct bgp_info *path)
{
  struct bgp_nexthop_cache *bnc = path->nexthop;

  if (!bnc)
    return;

  path_nh_map(path, NULL, 0);
  
  bgp_unlink_nexthop_check (bnc);
}

void
bgp_unlink_nexthop_by_peer (struct peer *peer)
{
  struct prefix p;
  struct bgp_node *rn;
  struct bgp_nexthop_cache *bnc;
  afi_t afi = family2afi(peer->su.sa.sa_family);

  if (afi == AFI_IP)
    {
      p.family = AF_INET;
      p.prefixlen = IPV4_MAX_BITLEN;
      p.u.prefix4 = peer->su.sin.sin_addr;
    }
  else if (afi == AFI_IP6)
    {
      p.family = AF_INET6;
      p.prefixlen = IPV6_MAX_BITLEN;
      p.u.prefix6 = peer->su.sin6.sin6_addr;
    }
  else
    return;

  rn = bgp_node_get (bgp_nexthop_cache_table[afi], &p);

  if (!rn->info)
    return;
  
  bnc = rn->info;
  
  /* cleanup the peer reference */
  bnc->nht_info = NULL;
  
  bgp_unlink_nexthop_check (bnc);
}

int
bgp_find_or_add_nexthop (afi_t afi, struct bgp_info *ri, struct peer *peer,
			 int connected)
{
  struct bgp_node *rn;
  struct bgp_nexthop_cache *bnc;
  struct prefix p;

  if (ri)
    {
      if (make_prefix(afi, ri, &p) < 0)
	return 1;
    }
  else if (peer)
    {
      if (afi == AFI_IP)
	{
	  p.family = AF_INET;
	  p.prefixlen = IPV4_MAX_BITLEN;
	  p.u.prefix4 = peer->su.sin.sin_addr;
	}
      else if (afi == AFI_IP6)
	{
	  p.family = AF_INET6;
	  p.prefixlen = IPV6_MAX_BITLEN;
	  p.u.prefix6 = peer->su.sin6.sin6_addr;
	}
    }

  rn = bgp_node_get (bgp_nexthop_cache_table[afi], &p);

  if (!rn->info)
    {
      bnc = bnc_new();
      rn->info = bnc;
      bnc->node = rn;
      bgp_lock_node(rn);
      if (connected)
	SET_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED);
    }

  bnc = rn->info;
  bgp_unlock_node (rn);

  if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED))
    register_nexthop(bnc);

  if (ri)
    {
      path_nh_map(ri, bnc, 1); /* updates NHT ri list reference */

      if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID) && bnc->metric)
	(bgp_info_extra_get(ri))->igpmetric = bnc->metric;
      else if (ri->extra)
	ri->extra->igpmetric = 0;
    }
  else if (peer)
    bnc->nht_info = (void *)peer; /* NHT peer reference */

  return (bgp_zebra_num_connects() == 0 ||
          CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID));
}

void
bgp_parse_nexthop_update (void)
{
  struct stream *s;
  struct bgp_node *rn;
  struct bgp_nexthop_cache *bnc;
  struct nexthop *nexthop;
  struct nexthop *oldnh;
  struct nexthop *nhlist_head = NULL;
  struct nexthop *nhlist_tail = NULL;
  uint32_t metric;
  u_char nexthop_num;
  struct prefix p;
  int i;

  s = zclient->ibuf;

  memset(&p, 0, sizeof(struct prefix));
  p.family = stream_getw(s);
  p.prefixlen = stream_getc(s);
  switch (p.family)
    {
    case AF_INET:
      p.u.prefix4.s_addr = stream_get_ipv4 (s);
      break;
    case AF_INET6:
      stream_get(&p.u.prefix6, s, 16);
      break;
    default:
      break;
    }

  rn = bgp_node_lookup(bgp_nexthop_cache_table[family2afi(p.family)], &p);
  if (!rn || !rn->info)
    {
      if (BGP_DEBUG(nht, NHT))
	{
	  char buf[INET6_ADDRSTRLEN];
	  prefix2str(&p, buf, INET6_ADDRSTRLEN);
	  zlog_debug("parse nexthop update(%s): rn not found", buf);
	}
      if (rn)
        bgp_unlock_node (rn);
      return;
    }

  bnc = rn->info;
  bgp_unlock_node (rn);
  bnc->last_update = bgp_clock();
  bnc->change_flags = 0;
  metric = stream_getl (s);
  nexthop_num = stream_getc (s);

  /* debug print the input */
  if (BGP_DEBUG(nht, NHT))
    {
      char buf[INET6_ADDRSTRLEN];
      prefix2str(&p, buf, INET6_ADDRSTRLEN);
      zlog_debug("parse nexthop update(%s): metric=%d, #nexthop=%d", buf,
		 metric, nexthop_num);
    }

  if (metric != bnc->metric)
    bnc->change_flags |= BGP_NEXTHOP_METRIC_CHANGED;

  if(nexthop_num != bnc->nexthop_num)
    bnc->change_flags |= BGP_NEXTHOP_CHANGED;

  if (nexthop_num)
    {
      bnc->flags |= BGP_NEXTHOP_VALID;
      bnc->metric = metric;
      bnc->nexthop_num = nexthop_num;

      for (i = 0; i < nexthop_num; i++)
	{
	  nexthop = nexthop_new();
	  nexthop->type = stream_getc (s);
	  switch (nexthop->type)
	    {
	    case ZEBRA_NEXTHOP_IPV4:
	      nexthop->gate.ipv4.s_addr = stream_get_ipv4 (s);
	      break;
	    case ZEBRA_NEXTHOP_IFINDEX:
	    case ZEBRA_NEXTHOP_IFNAME:
	      nexthop->ifindex = stream_getl (s);
	      break;
            case ZEBRA_NEXTHOP_IPV4_IFINDEX:
	    case ZEBRA_NEXTHOP_IPV4_IFNAME:
	      nexthop->gate.ipv4.s_addr = stream_get_ipv4 (s);
	      nexthop->ifindex = stream_getl (s);
	      break;
#ifdef HAVE_IPV6
            case ZEBRA_NEXTHOP_IPV6:
	      stream_get (&nexthop->gate.ipv6, s, 16);
	      break;
            case ZEBRA_NEXTHOP_IPV6_IFINDEX:
	    case ZEBRA_NEXTHOP_IPV6_IFNAME:
	      stream_get (&nexthop->gate.ipv6, s, 16);
	      nexthop->ifindex = stream_getl (s);
	      break;
#endif
            default:
              /* do nothing */
              break;
	    }

	  if (nhlist_tail)
	    {
	      nhlist_tail->next = nexthop;
	      nhlist_tail = nexthop;
	    }
	  else
	    {
	      nhlist_tail = nexthop;
	      nhlist_head = nexthop;
	    }

	  /* No need to evaluate the nexthop if we have already determined
	   * that there has been a change.
	   */
	  if (bnc->change_flags & BGP_NEXTHOP_CHANGED)
	    continue;

	  for (oldnh = bnc->nexthop; oldnh; oldnh = oldnh->next)
	      if (nexthop_same_no_recurse(oldnh, nexthop))
		  break;

	  if (!oldnh)
	    bnc->change_flags |= BGP_NEXTHOP_CHANGED;
	}
      bnc_nexthop_free(bnc);
      bnc->nexthop = nhlist_head;
    }
  else
    {
      bnc->flags &= ~BGP_NEXTHOP_VALID;
      UNSET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED);
      bnc_nexthop_free(bnc);
      bnc->nexthop = NULL;
    }

  evaluate_paths(bnc);
}

/**
 * make_prefix - make a prefix structure from the path (essentially
 * path's node.
 */
static int
make_prefix (int afi, struct bgp_info *ri, struct prefix *p)
{
  memset (p, 0, sizeof (struct prefix));
  switch (afi)
    {
    case AFI_IP:
      p->family = AF_INET;
      p->prefixlen = IPV4_MAX_BITLEN;
      p->u.prefix4 = ri->attr->nexthop;
      break;
#ifdef HAVE_IPV6
    case AFI_IP6:
      if (ri->attr->extra->mp_nexthop_len != 16
	  || IN6_IS_ADDR_LINKLOCAL (&ri->attr->extra->mp_nexthop_global))
	return -1;

      p->family = AF_INET6;
      p->prefixlen = IPV6_MAX_BITLEN;
      p->u.prefix6 = ri->attr->extra->mp_nexthop_global;
      break;
#endif
    default:
      break;
    }
  return 0;
}

/**
 * sendmsg_nexthop -- Format and send a nexthop register/Unregister
 *   command to Zebra.
 * ARGUMENTS:
 *   struct bgp_nexthop_cache *bnc -- the nexthop structure.
 *   int command -- either ZEBRA_NEXTHOP_REGISTER or ZEBRA_NEXTHOP_UNREGISTER
 * RETURNS:
 *   void.
 */
static void
sendmsg_nexthop (struct bgp_nexthop_cache *bnc, int command)
{
  struct stream *s;
  struct prefix *p;
  int ret;

  /* Check socket. */
  if (!zclient || zclient->sock < 0)
    {
      zlog_debug("%s: Can't send NH register, Zebra client not established",
		 __FUNCTION__);
      return;
    }

  p = &(bnc->node->p);
  s = zclient->obuf;
  stream_reset (s);
  zclient_create_header (s, command, VRF_DEFAULT);
  if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED))
    stream_putc(s, 1);
  else
    stream_putc(s, 0);

  stream_putw(s, PREFIX_FAMILY(p));
  stream_putc(s, p->prefixlen);
  switch (PREFIX_FAMILY(p))
    {
    case AF_INET:
      stream_put_in_addr (s, &p->u.prefix4);
      break;
    case AF_INET6:
      stream_put(s, &(p->u.prefix6), 16);
      break;
    default:
      break;
    }
  stream_putw_at (s, 0, stream_get_endp (s));

  ret = zclient_send_message(zclient);
  /* TBD: handle the failure */
  if (ret < 0)
    zlog_warn("sendmsg_nexthop: zclient_send_message() failed");

  if (command == ZEBRA_NEXTHOP_REGISTER)
    SET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
  else if (command == ZEBRA_NEXTHOP_UNREGISTER)
    UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
  return;
}

/**
 * register_nexthop - register a nexthop with Zebra for notification
 *    when the route to the nexthop changes.
 * ARGUMENTS:
 *   struct bgp_nexthop_cache *bnc -- the nexthop structure.
 * RETURNS:
 *   void.
 */
static void
register_nexthop (struct bgp_nexthop_cache *bnc)
{
  /* Check if we have already registered */
  if (bnc->flags & BGP_NEXTHOP_REGISTERED)
    return;
  sendmsg_nexthop(bnc, ZEBRA_NEXTHOP_REGISTER);
}

/**
 * unregister_nexthop -- Unregister the nexthop from Zebra.
 * ARGUMENTS:
 *   struct bgp_nexthop_cache *bnc -- the nexthop structure.
 * RETURNS:
 *   void.
 */
static void
unregister_nexthop (struct bgp_nexthop_cache *bnc)
{
  /* Check if we have already registered */
  if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED))
    return;

  sendmsg_nexthop(bnc, ZEBRA_NEXTHOP_UNREGISTER);
}

/**
 * evaluate_paths - Evaluate the paths/nets associated with a nexthop.
 * ARGUMENTS:
 *   struct bgp_nexthop_cache *bnc -- the nexthop structure.
 * RETURNS:
 *   void.
 */
static void
evaluate_paths (struct bgp_nexthop_cache *bnc)
{
  struct bgp_node *rn;
  struct bgp_info *path;
  struct bgp *bgp = bgp_get_default();
  int afi;
  struct peer *peer = (struct peer *)bnc->nht_info;

  LIST_FOREACH(path, &(bnc->paths), nh_thread)
    {
      if (!(path->type == ZEBRA_ROUTE_BGP &&
	    path->sub_type == BGP_ROUTE_NORMAL))
	continue;

      rn = path->net;
      afi = family2afi(rn->p.family);

      /* Path becomes valid/invalid depending on whether the nexthop
       * reachable/unreachable.
       */
      if ((CHECK_FLAG(path->flags, BGP_INFO_VALID) ? 1 : 0) !=
	  (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID) ? 1 : 0))
	{
	  if (CHECK_FLAG (path->flags, BGP_INFO_VALID))
	    {
	      bgp_aggregate_decrement (bgp, &rn->p, path,
				       afi, SAFI_UNICAST);
	      bgp_info_unset_flag (rn, path, BGP_INFO_VALID);
	    }
	  else
	    {
	      bgp_info_set_flag (rn, path, BGP_INFO_VALID);
	      bgp_aggregate_increment (bgp, &rn->p, path,
				       afi, SAFI_UNICAST);
	    }
	}

      /* Copy the metric to the path. Will be used for bestpath computation */
      if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID) && bnc->metric)
	(bgp_info_extra_get(path))->igpmetric = bnc->metric;
      else if (path->extra)
	path->extra->igpmetric = 0;

      if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_METRIC_CHANGED) ||
	  CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CHANGED))
	SET_FLAG(path->flags, BGP_INFO_IGP_CHANGED);

      bgp_process(bgp, rn, afi, SAFI_UNICAST);
    }

  if (peer && !CHECK_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED))
    {
      if (BGP_DEBUG(nht, NHT))
	zlog_debug("%s: Updating peer (%s) status with NHT", __FUNCTION__, peer->host);
      BGP_EVENT_ADD (peer, NHT_Update);
      SET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED);
    }

  RESET_FLAG(bnc->change_flags);
}

/**
 * path_nh_map - make or break path-to-nexthop association.
 * ARGUMENTS:
 *   path - pointer to the path structure
 *   bnc - pointer to the nexthop structure
 *   make - if set, make the association. if unset, just break the existing
 *          association.
 */
static void
path_nh_map (struct bgp_info *path, struct bgp_nexthop_cache *bnc, int make)
{
  if (path->nexthop)
    {
      LIST_REMOVE(path, nh_thread);
      path->nexthop->path_count--;
      path->nexthop = NULL;
    }
  if (make)
    {
      LIST_INSERT_HEAD(&(bnc->paths), path, nh_thread);
      path->nexthop = bnc;
      path->nexthop->path_count++;
    }
}
