1/*
2 Cisco Systems, Inc.
3*/
4
5/*
6Copyright (c) 2016-2016 Cisco Systems, Inc.
7
8Licensed under the Apache License, Version 2.0 (the "License");
9you may not use this file except in compliance with the License.
10You may obtain a copy of the License at
11
12    http://www.apache.org/licenses/LICENSE-2.0
13
14Unless required by applicable law or agreed to in writing, software
15distributed under the License is distributed on an "AS IS" BASIS,
16WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17See the License for the specific language governing permissions and
18limitations under the License.
19*/
20#include <string>
21#include <iostream>
22#include <pkt_gen.h>
23#include "utl_ip.h"
24
25void COneIPInfo::dump(FILE *fd, const char *offset) const {
26    uint8_t mac[ETHER_ADDR_LEN];
27    m_mac.copyToArray(mac);
28    char ip_str[100];
29    get_ip_str(ip_str);
30    std::string mac_str;
31    utl_macaddr_to_str(mac, mac_str);
32    const char *mac_char = resolve_needed() ?  "Unknown" : mac_str.c_str();
33    fprintf(fd, "%sip: %s ", offset, ip_str);
34    if (m_vlan != 0)
35        fprintf(fd, "vlan: %d ", m_vlan);
36    if (m_port != UINT8_MAX)
37        fprintf(fd, "port: %d ", m_port);
38    fprintf(fd, "mac: %s", mac_char);
39    fprintf(fd, "\n");
40}
41
42bool COneIPInfo::resolve_needed() const {
43    return m_mac.isDefaultAddress();
44}
45
46/*
47 * Fill buffer p with arp request.
48 * port_id - port id we intend to send on
49 * sip - source IP/MAC information
50 */
51void COneIPv4Info::fill_arp_req_buf(uint8_t *p, uint16_t port_id, COneIPInfo *sip) {
52    uint8_t src_mac[ETHER_ADDR_LEN];
53    sip->get_mac(src_mac);
54
55    CTestPktGen::create_arp_req(p, ((COneIPv4Info *)sip)->get_ip(), m_ip, src_mac, m_vlan, port_id);
56}
57
58void COneIPv4Info::fill_grat_arp_buf(uint8_t *p) {
59    uint8_t src_mac[ETHER_ADDR_LEN];
60    get_mac(src_mac);
61
62    CTestPktGen::create_arp_req(p, m_ip, m_ip, src_mac, m_vlan, 0);
63}
64
65void COneIPv6Info::fill_arp_req_buf(uint8_t *p, uint16_t port_id, COneIPInfo *sip) {
66    //??? implement ipv6
67}
68
69void COneIPv6Info::fill_grat_arp_buf(uint8_t *p) {
70    //??? implement ipv6
71}
72
73const COneIPInfo *CManyIPInfo::get_next() {
74    const COneIPInfo *ret;
75
76    if (!m_iter_initiated) {
77        m_ipv4_iter = m_ipv4_resolve.begin();
78        m_iter_initiated = true;
79    }
80
81
82    if (m_ipv4_iter == m_ipv4_resolve.end()) {
83        m_ipv4_iter = m_ipv4_resolve.begin();
84        return NULL;
85    }
86
87    ret = &(m_ipv4_iter->second);
88    m_ipv4_iter++;
89    return ret;
90}
91
92void CManyIPInfo::dump(FILE *fd) {
93    ip_vlan_to_many_ip_iter_t it;
94    for (it = m_ipv4_resolve.begin(); it != m_ipv4_resolve.end(); it++) {
95        fprintf(fd, "IPv4 resolved list:\n");
96        uint8_t mac[ETHER_ADDR_LEN];
97        it->second.get_mac(mac);
98        fprintf(fd, "ip:%s vlan: %d resolved to mac %s\n", ip_to_str(it->first.get_ip()).c_str(), it->first.get_vlan()
99                , utl_macaddr_to_str(mac).c_str());
100    }
101}
102
103void CManyIPInfo::insert(const COneIPv4Info &ip_info) {
104    CIpVlan ip_vlan(ip_info.get_ip(), ip_info.get_vlan());
105
106    m_ipv4_resolve.insert(std::make_pair(ip_vlan, ip_info));
107}
108
109bool CManyIPInfo::lookup(uint32_t ip, uint16_t vlan, MacAddress &ret_mac) const {
110    ip_vlan_to_many_ip_iter_t it = m_ipv4_resolve.find(CIpVlan(ip, vlan));
111    if (it != m_ipv4_resolve.end()) {
112        uint8_t mac[ETHER_ADDR_LEN];
113        (*it).second.get_mac(mac);
114        ret_mac.set(mac);
115        return true;
116    } else {
117        return false;
118    }
119}
120
121bool CManyIPInfo::exists(uint32_t ip, uint16_t vlan) const {
122    ip_vlan_to_many_ip_iter_t it = m_ipv4_resolve.find(CIpVlan(ip, vlan));
123    return (it != m_ipv4_resolve.end());
124}
125
126void CManyIPInfo::clear() {
127    m_ipv4_resolve.clear();
128    m_ipv6_resolve.clear();
129    m_iter_initiated = false;
130}
131
132const COneIPInfo *CManyIPInfo::get_first() {
133    if (m_ipv4_resolve.size() == 0) {
134        return NULL;
135    } else {
136        m_ipv4_iter = m_ipv4_resolve.begin();
137        return &(m_ipv4_iter->second);
138    }
139}
140