#!/usr/bin/env python
# Copyright (c) 2016 Orange and others.
#
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Apache License, Version 2.0
# which accompanies this distribution, and is available at
# http://www.apache.org/licenses/LICENSE-2.0
# pylint: disable=missing-docstring
import logging
import unittest
import mock
from xtesting.core import vnf
from
@media only all and (prefers-color-scheme: dark) {
.highlight .hll { background-color: #49483e }
.highlight .c { color: #75715e } /* Comment */
.highlight .err { color: #960050; background-color: #1e0010 } /* Error */
.highlight .k { color: #66d9ef } /* Keyword */
.highlight .l { color: #ae81ff } /* Literal */
.highlight .n { color: #f8f8f2 } /* Name */
.highlight .o { color: #f92672 } /* Operator */
.highlight .p { color: #f8f8f2 } /* Punctuation */
.highlight .ch { color: #75715e } /* Comment.Hashbang */
.highlight .cm { color: #75715e } /* Comment.Multiline */
.highlight .cp { color: #75715e } /* Comment.Preproc */
.highlight .cpf { color: #75715e } /* Comment.PreprocFile */
.highlight .c1 { color: #75715e } /* Comment.Single */
.highlight .cs { color: #75715e } /* Comment.Special */
.highlight .gd { color: #f92672 } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gi { color: #a6e22e } /* Generic.Inserted */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #75715e } /* Generic.Subheading */
.highlight .kc { color: #66d9ef } /* Keyword.Constant */
.highlight .kd { color: #66d9ef } /* Keyword.Declaration */
.highlight .kn { color: #f92672 } /* Keyword.Namespace */
.highlight .kp { color: #66d9ef } /* Keyword.Pseudo */
.highlight .kr { color: #66d9ef } /* Keyword.Reserved */
.highlight .kt { color: #66d9ef } /* Keyword.Type */
.highlight .ld { color: #e6db74 } /* Literal.Date */
.highlight .m { color: #ae81ff } /* Literal.Number */
.highlight .s { color: #e6db74 } /* Literal.String */
.highlight .na { color: #a6e22e } /* Name.Attribute */
.highlight .nb { color: #f8f8f2 } /* Name.Builtin */
.highlight .nc { color: #a6e22e } /* Name.Class */
.highlight .no { color: #66d9ef } /* Name.Constant */
.highlight .nd { color: #a6e22e } /* Name.Decorator */
.highlight .ni { color: #f8f8f2 } /* Name.Entity */
.highlight .ne { color: #a6e22e } /* Name.Exception */
.highlight .nf { color: #a6e22e } /* Name.Function */
.highlight .nl { color: #f8f8f2 } /* Name.Label */
.highlight .nn { color: #f8f8f2 } /* Name.Namespace */
.highlight .nx { color: #a6e22e } /* Name.Other */
.highlight .py { color: #f8f8f2 } /* Name.Property */
.highlight .nt { color: #f92672 } /* Name.Tag */
.highlight .nv { color: #f8f8f2 } /* Name.Variable */
.highlight .ow { color: #f92672 } /* Operator.Word */
.highlight .w { color: #f8f8f2 } /* Text.Whitespace */
.highlight .mb { color: #ae81ff } /* Literal.Number.Bin */
.highlight .mf { color: #ae81ff } /* Literal.Number.Float */
.highlight .mh { color: #ae81ff } /* Literal.Number.Hex */
.highlight .mi { color: #ae81ff } /* Literal.Number.Integer */
.highlight .mo { color: #ae81ff } /* Literal.Number.Oct */
.highlight .sa { color: #e6db74 } /* Literal.String.Affix */
.highlight .sb { color: #e6db74 } /* Literal.String.Backtick */
.highlight .sc { color: #e6db74 } /* Literal.String.Char */
.highlight .dl { color: #e6db74 } /* Literal.String.Delimiter */
.highlight .sd { color: #e6db74 } /* Literal.String.Doc */
.highlight .s2 { color: #e6db74 } /* Literal.String.Double */
.highlight .se { color: #ae81ff } /* Literal.String.Escape */
.highlight .sh { color: #e6db74 } /* Literal.String.Heredoc */
.highlight .si { color: #e6db74 } /* Literal.String.Interpol */
.highlight .sx { color: #e6db74 } /* Literal.String.Other */
.highlight .sr { color: #e6db74 } /* Literal.String.Regex */
.highlight .s1 { color: #e6db74 } /* Literal.String.Single */
.highlight .ss { color: #e6db74 } /* Literal.String.Symbol */
.highlight .bp { color: #f8f8f2 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #a6e22e } /* Name.Function.Magic */
.highlight .vc { color: #f8f8f2 } /* Name.Variable.Class */
.highlight .vg { color: #f8f8f2 } /* Name.Variable.Global */
.highlight .vi { color: #f8f8f2 } /* Name.Variable.Instance */
.highlight .vm { color: #f8f8f2 } /* Name.Variable.Magic */
.highlight .il { color: #ae81ff } /* Literal.Number.Integer.Long */
}
@media (prefers-color-scheme: light) {
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
}
/*
// Copyright (c) 2017 Intel Corporation
//
// 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.
*/
#ifndef __INCLUDE_LIB_ARP_H__
#define __INCLUDE_LIB_ARP_H__
#include <rte_pipeline.h>
#include "rte_ether.h"
#include "l2_proto.h"
#include "app.h"
#define ND_IPV6_ADDR_SIZE 16 /**< 16 Byte of IPv6 Address. */
#define ND_IPV6_TIMER_EXPIRY 300 /**< in Seconds, Timer for ND IPv6 Expiry */
#define ARP_TIMER_EXPIRY 20 /**< in Seconds, TIMER for ARP Expiry */
#define TIMER_MILLISECOND 1
#define RTE_LOGTYPE_LIBARP RTE_LOGTYPE_USER1
#define MAX_ND_RT_ENTRY 32
#define MAX_ARP_RT_ENTRY 32
#define NUM_DESC (get_arp_buf())
#define ARP_BUF_DEFAULT 30000
#define PROBE_TIME 50
#define ARP_RETRY_COUNT 100
#undef L3_STACK_SUPPORT
#define MAX_LOCAL_MAC_ADDRESS 32
#define MAX_PORTS 32
struct arp_cache {
uint32_t nhip[MAX_LOCAL_MAC_ADDRESS];
struct ether_addr link_hw_laddr[MAX_LOCAL_MAC_ADDRESS];
uint32_t num_nhip;
};
struct nd_cache {
uint8_t nhip[MAX_LOCAL_MAC_ADDRESS][16];
struct ether_addr link_hw_laddr[MAX_LOCAL_MAC_ADDRESS];
uint32_t num_nhip;
};
uint8_t arp_cache_dest_mac_present(uint32_t out_port);
uint8_t nd_cache_dest_mac_present(uint32_t out_port);
extern struct ether_addr *get_local_cache_hw_addr(uint8_t out_port, uint32_t nhip);
extern struct ether_addr *get_nd_local_link_hw_addr(uint8_t out_port, uint8_t nhip[]);
extern struct arp_cache arp_local_cache[MAX_PORTS];
extern void prefetch(void);
extern void update_nhip_access(uint8_t);
uint32_t get_arp_buf(void);
uint32_t get_nd_buf(void);
enum {
ARP_FOUND,
ARP_NOT_FOUND,
NH_NOT_FOUND,
};
enum arp_key_type {
ARP_IPV4,
ND_IPV6,
};
struct arp_key_ipv4 {
uint32_t ip; /**< IP address */
uint8_t port_id; /**< Port id */
uint8_t filler1; /**< filler 1, for better hash key */
uint8_t filler2; /**< filler 2, for better hash key */
uint8_t filler3; /**< filler 3, for better hash key */
};
/**
* IPv6
*/
struct nd_key_ipv6 {
uint8_t ipv6[ND_IPV6_ADDR_SIZE]; /**< 128 Bit of IPv6 Address*/
uint8_t port_id; /**< Port id */
uint8_t filler1;
uint8_t filler2;
uint8_t filler3;
};
/**
* Arp Key
*/
struct arp_key {
enum arp_key_type type;
union {
struct arp_key_ipv4 ipv4;
} key; /**< Key of type arp key Ipv4 */
};
/**
* call back function parameter pair remove nd entry
*
*/
struct nd_timer_key {
uint8_t ipv6[ND_IPV6_ADDR_SIZE]; /**< IPv6 address */
uint8_t port_id; /**< Port id */
} __rte_cache_aligned;
/**
* call back function parameter remove arp entry
*
*/
struct arp_timer_key {
uint32_t ip; /**< Ip address */
uint8_t port_id; /**< Port id */
} __rte_cache_aligned;
extern uint32_t ARPICMP_DEBUG;
enum {
INCOMPLETE,
COMPLETE,
PROBE,
STALE
};
#define USED_TIME 5
extern uint32_t NDIPV6_DEBUG; /**< ND IPv6 */
#define ICMPv6_COMPLETE 1 /**< ICMPv6 entry populated and echo reply recieved. */
#define ICMPv6_INCOMPLETE 0 /**< ICMPv6 entry populated and either awaiting echo reply or stale entry. */
#define STATIC_ARP 1 /**< Static ARP Entry. */
#define DYNAMIC_ARP 0 /**< Dynamic ARP Entry. */
#define STATIC_ND 1 /**< Static ND Entry. */
#define DYNAMIC_ND 0 /**< Dynamic ND Entry. */
/**
* A structure is used to defined the ARP entry data
* This structure is used as a input parameters for entry of ARP data
*/
struct arp_entry_data {
struct ether_addr eth_addr; /**< ethernet address */
uint32_t ip; /**< IP address */
uint8_t port; /**< Port */
uint8_t status; /**< Status of entry */
uint8_t mode; /**< Mode */
uint8_t retry_count; /**< retry count for ARP*/
struct rte_timer *timer; /**< Timer Associated with ARP*/
struct arp_timer_key *timer_key;
rte_rwlock_t queue_lock; /** queue lock */
struct rte_mbuf **buf_pkts;
uint32_t num_pkts;
uint64_t n_confirmed;
} __attribute__ ((packed));
/**
* A structure is used to defined the table for arp entry data
* This structure is used to maintain the arp entry data
*/
struct table_arp_entry_data {
uint8_t eth_addr[6]; /**< Ethernet address */
uint8_t port; /**< port */
uint8_t status; /**< status of entry */
uint32_t ip; /**< Ip address */
} __attribute__ ((packed));
/**
* A structure is used to define the ND entry data for IPV6
* This structure is used as a input parameters for ND entry data
*/
struct nd_entry_data {
struct ether_addr eth_addr; /**< Ethernet address */
uint8_t port; /**< port */
uint8_t status; /**< statusof the entry */
uint8_t mode; /**< Mode */
uint8_t ipv6[ND_IPV6_ADDR_SIZE]; /**< Ipv6 address */
uint8_t retry_count; /**< retry count for ARP*/
struct rte_timer *timer; /**< Timer */
struct nd_timer_key *timer_key;
rte_rwlock_t queue_lock; /** queue lock */
struct rte_mbuf **buf_pkts;
uint32_t num_pkts;
uint64_t n_confirmed;
} __attribute__ ((packed));
/**
* A structure is used to define the table for ND entry data
* This structure is used to maintain ND entry data
*
*/
struct table_nd_entry_data {
uint8_t eth_addr[6]; /**< Ethernet address */
uint8_t port; /**< Port */
uint8_t status; /**< status of Entry */
uint8_t ipv6[ND_IPV6_ADDR_SIZE]; /**< IPv6 address */
struct rte_timer *timer; /**< Timer */
} __attribute__ ((packed));
struct arp_data {
struct arp_cache arp_local_cache[MAX_PORTS];
struct nd_cache nd_local_cache[MAX_PORTS];
struct ether_addr link_hw_addr[MAX_LOCAL_MAC_ADDRESS];
uint32_t link_hw_addr_array_idx;
uint8_t arp_cache_hw_laddr_valid[MAX_LOCAL_MAC_ADDRESS];
uint8_t nd_cache_hw_laddr_valid[MAX_LOCAL_MAC_ADDRESS];
uint64_t update_tsc[MAX_LOCAL_MAC_ADDRESS];
} __rte_cache_aligned;
/**
* To get the destination MAC address andnext hop for the ip address and outgoing port
* @param1 ip addr
* IP address for which MAC address is needed.
* @param2 phy_port
* Physical Port
* @param3 ether_addr
* pointer to the ether_addr, This gets update with valid MAC addresss
* @Param4 next nhip
* Gets the next hop IP by Ip address and physical port
* @return
* 0 if failure, and 1 if success
*/
struct arp_entry_data *get_dest_mac_addr_port(const uint32_t ipaddr,
uint32_t phy_port, struct ether_addr *hw_addr);
/**
* To get the destination mac address for IPV6 address
* @param ipv6addr
* IPv6 address which need the destination mac adress
* @param Phy_Port
* physical prt
* @param ether_addr
* pointer to the ether_address, This gets update with valid mac address
* @param Nhipv6[]
* Gets the next hop ipv6 address by ipv6 address and physical port
* @return
* 0 if failure, 1 ifsuccess
*/
int arp_queue_unresolved_packet(struct arp_entry_data * arp_data,
struct rte_mbuf * m);
extern void arp_send_buffered_pkts(struct arp_entry_data *ret_arp_data,struct ether_addr *hw_addr, uint8_t port_id);
int nd_queue_unresolved_packet(struct nd_entry_data *nd_data,
struct rte_mbuf * m);
extern void nd_send_buffered_pkts(struct nd_entry_data *ret_nd_data,struct ether_addr *hw_addr, uint8_t port_id);
/**
* To get hardware link address
* @param out_port
* out going port
*/
struct ether_addr *get_link_hw_addr(uint8_t out_port);
/**
* This prints the Arp Table
* @param void
*
*/
void print_arp_table(void);
/**
* This prints the ND table
* @param void
*
*/
void print_nd_table(void);
/**
* This removes arp entry from Table
* @param ipaddr
* Ipv4 address
* @param portid
* Port id
*/
void remove_arp_entry(struct arp_entry_data *ret_arp_data, void *arg);
/**
* Removes ND entry from Nd Table
* @Param ipv6addr[]
* Ipv6 address
* @Param portid
* Port id
*/
void remove_nd_entry_ipv6(struct nd_entry_data *ret_nd_data, void *arg);
/**
* Populate arp entry in arp Table
* @param ether_addr
* Ethernet address
* @param ipaddr
* Ipv4 adress
* @Param portid
* port id
* @Param mode
* Mode
*/
void populate_arp_entry(const struct ether_addr *hw_addr, uint32_t ipaddr,
uint8_t portid, uint8_t mode);
/**
* Populate ND entry in ND Table
* @param ether_addr
* Ethernet address
* @param ip[]
* Ipv6 adress
* @Param portid
* port id
* @Param mode
* Mode
*/
void populate_nd_entry(const struct ether_addr *hw_addr, uint8_t ip[],
uint8_t portid, uint8_t mode);
/**
* To send ARp request
* @Param port_id
* port id
@ Param IP
* Ip address
*/
void request_arp(uint8_t port_id, uint32_t ip);
/**
* TO send echo request
* @param port_id
* Port id
* @Param ip
* Ip address
*/
struct rte_mbuf *request_echo(uint32_t port_id, uint32_t ip);
/**
* To send icmpv6 echo request
* @Param port_id
* Port id
* @Param ipv6
* ipv6 address
*/
struct rte_mbuf *request_icmpv6_echo(uint8_t ipv6[], l2_phy_interface_t *port);
/**
* To request ND
* @Param ipv6
* ipv6 address
* @Param port
* pointer to port
*/
struct rte_mbuf *request_nd(uint8_t ipv6[], l2_phy_interface_t *port);
/**
* To process te ARP and ICMP packets
* @Param Pkt
* Packets to be processed
* @Param pkt_num
* packet number
* @Param portid
* port id
*/
void process_arpicmp_pkt(struct rte_mbuf *pkt, l2_phy_interface_t *port);
/**
* IPv4
* Validate if key-value pair already exists in the hash table for given key - IPv4
* @Param arp_key
* Arp key to validate entry
*/
struct arp_entry_data *retrieve_arp_entry(const struct arp_key_ipv4 arp_key, uint8_t mode);
/**
* ND IPv6
* Validate if key-value pair already exists in the hash table for given key - ND IPv6
* @Param nd_key
* Nd key to validate Nd entry
*/
struct nd_entry_data *retrieve_nd_entry(struct nd_key_ipv6 nd_key, uint8_t mode);
/**
* Setsup Arp Initilization
*/
//void lib_arp_init(void);
void lib_arp_init(struct pipeline_params *params, struct app_params *app);
#if 0
void set_port_to_loadb_map(uint8_t pipeline_num);
/**
* Acts on port_to_loadb_map
*/
uint8_t get_port_to_loadb_map(uint8_t phy_port_id);
void set_phy_inport_map(uint8_t pipeline_num, uint8_t *map);
void set_phy_outport_map(uint8_t pipeline_num, uint8_t *map);
/**
* Acts on lb_outport_id
*/
uint8_t get_loadb_outport_id(uint8_t actual_phy_port);
uint8_t get_vnf_set_num(uint8_t pipeline_num);
void pipelines_port_info(void);
void pipelines_map_info(void);
#endif
/**
* A callback for arp Timer
* @Param rte_timer
* timer pointer
* @Param arg
* arguments to timer
*/
void arp_timer_callback(struct rte_timer *, void *arg);
/**
* A callback for ND timer
* @Param rte_timer
* timer pointer
* @Param arg
* arguments to timer
*/
void nd_timer_callback(struct rte_timer *timer, void *arg);
/**
* To create Arp Table
* @param void
*/
void create_arp_table(void);
/**
* To create ND Table
* @param void
*/
void create_nd_table(void);
/**
* To parse and process the Arp and icmp packets
* @Param pkt
* pkt to process
* @Param pkt_num
* pkt number
* @Param pkt_mask
* packet mask
* @Param port
* pointer to port
*/
void process_arpicmp_pkt_parse(struct rte_mbuf **pkt, uint16_t pkt_num,
uint64_t pkt_mask, l2_phy_interface_t *port);
/**
* Sends garp packet
* @Param port
* pointer to port
*/
void send_gratuitous_arp(l2_phy_interface_t *port);
/**
* To set arp debug
* @Param flag
* set 1 unset 0
*/
void set_arpdebug(int flag);
/**
* To set timer for arp entry
* @Param timeout_val
* timer val for arp entry
*/
void set_arptimeout(uint32_t timeout_val);
/**
* To get nexthop for ipv4
* @Param ipv4
* ipv4 address
* @Param
* timeout_val to set
*/
uint32_t get_nh(uint32_t, uint32_t *, struct ether_addr *addr);
/**
* To get nexthop for ipv6
* @Param ipv6
* ipv6 address
* @Param port
* pointer to port
* @Param nhipv6
* next hop ipv6
*/
void get_nh_ipv6(uint8_t ipv6[], uint32_t *port, uint8_t nhipv6[], struct ether_addr *hw_addr);
struct arp_entry_data *get_dest_mac_addr_ipv4(const uint32_t nhip,
uint32_t phy_port, struct ether_addr *hw_addr);
struct nd_entry_data *get_dest_mac_addr_ipv6(uint8_t nhipv6[],
uint32_t phy_port, struct ether_addr *hw_addr);
#endif