blob: eb16d5aec17dd353a9d75323041a42a7b175f6f4 [file] [log] [blame]
Jeremy Kerr42dc98c2016-02-25 10:23:14 +08001/******************************************************************************
2* Copyright 2016 Foxconn
3*
4* Licensed under the Apache License, Version 2.0 (the "License");
5* you may not use this file except in compliance with the License.
6* You may obtain a copy of the License at
7*
8* http://www.apache.org/licenses/LICENSE-2.0
9*
10* Unless required by applicable law or agreed to in writing, software
11* distributed under the License is distributed on an "AS IS" BASIS,
12* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13* See the License for the specific language governing permissions and
14* limitations under the License.
15******************************************************************************/
16#define MAX_SERVER_NODE 24
17#define SKU1_MAX_SERVER_NODES 24
18
19#define ETH_ARP_FRAME_LEN ( sizeof(struct ethhdr)+\
20 sizeof(struct arphdr)+\
21 ((ETH_ALEN+4)*2)\
22 )
23
24struct ARP_DATA {
25 unsigned char src_mac [ETH_ALEN];//source mac addr
26 unsigned char src_ip [4]; //source ip addr
27 unsigned char dest_mac[ETH_ALEN];//dest mac addr
28 unsigned char dest_ip [4]; //dest ip
29};
30struct ETH_ARP_PACKET {
31 struct ethhdr eh;
32 struct arphdr arp;
33 struct ARP_DATA arp_data;
34};
35
36struct ETH_ARP_PACKET *inarp_req;
37
38static char based_mac[6] = {0,0,0,0,0,0};
39int send_arp_packet(int fd,
40 int ifindex,
41 struct ETH_ARP_PACKET *eth_arp,
42 __be16 ar_op,
43 unsigned char *src_mac,
44 unsigned char *src_ip,
45 unsigned char *dest_mac,
46 unsigned char *dest_ip
47 )
48{
49 int send_result = 0;
50 struct ethhdr *eh = &eth_arp->eh;
51 struct arphdr *arp = &eth_arp->arp;
52 struct ARP_DATA *arp_data = &eth_arp->arp_data;
53 /*target address*/
54 struct sockaddr_ll socket_address;
55 /*prepare sockaddr_ll*/
56 /*RAW communication*/
57 socket_address.sll_family = PF_PACKET;
58 /*we don't use a protocoll above ethernet layer
59 ->just use anything here*/
60 socket_address.sll_protocol = htons(ETH_P_ARP);
61 /*index of the network device
62 see full code later how to retrieve it*/
63 socket_address.sll_ifindex = ifindex;
64 /*ARP hardware identifier is ethernet*/
65 socket_address.sll_hatype = ARPHRD_ETHER;
66 /*target is another host*/
67 socket_address.sll_pkttype = PACKET_OTHERHOST;
68 /*address length*/
69 socket_address.sll_halen = ETH_ALEN;
70 memcpy(socket_address.sll_addr, dest_mac, ETH_ALEN);
71 /*set the frame header*/
72 memcpy((void*)eh->h_dest, (void*)dest_mac, ETH_ALEN);
73 memcpy((void*)eh->h_source, (void*)src_mac, ETH_ALEN);
74 eh->h_proto = htons(ETH_P_ARP);
75 /*fill InARP request data for ethernet + ipv4*/
76 arp->ar_hrd = htons(ARPHRD_ETHER);
77 arp->ar_pro = htons(ETH_P_ARP);
78 arp->ar_hln = ETH_ALEN;
79 arp->ar_pln = 4;
80 arp->ar_op = htons(ar_op);
81 //fill arp ethernet mac & ipv4 info
82 arp_data = (void*)(arp + 1);
83 memcpy(arp_data->src_mac , (void*)src_mac, ETH_ALEN); //source mac addr
84 memcpy(arp_data->src_ip , src_ip, 4); //source ip addr
85 memcpy(arp_data->dest_mac, (void*)dest_mac, ETH_ALEN); //dest mac addr
86 memcpy(arp_data->dest_ip , dest_ip, 4); //dest ip
87 /*send the packet*/
88 send_result = sendto(fd, eth_arp, ETH_ARP_FRAME_LEN, 0,
89 (struct sockaddr*)&socket_address, sizeof(socket_address));
90 if (send_result == -1) {
91 printf("sendto: [%s]\n", strerror(errno));
92 }
93 return send_result;
94}
95void show_mac_addr(char *name, unsigned char *mac_addr)
96{
97 int i;
98 printf("%s MAC address: ", name);
99 for( i = 0; i < 6; i++ )
100 {
101 printf("%.2X%c", (unsigned char)mac_addr[i], (i == 5) ? '\n': ':');
102 }
103 return;
104}
105void show_ip_addr(char *desc, unsigned char *ip_addr)
106{
107 int i;
108 printf("%s IPv4 address: ", desc);
109 for(i = 0; i < 4; i++ )
110 {
111 printf("%d%c", (unsigned char)ip_addr[i], (i == 3) ? '\n': '.');
112 }
113}
114void dump_data(char *desc, unsigned char *buffer, int length)
115{
116 int i;
117 printf("%s & length is [%d]:\n", desc, length);
118 for (i=0; i<length; i++) {
119 printf ("[%02X]", 0xff & buffer[i]);
120 if ((i&0xf)==0x7) printf(" - ");
121 if ((i&0xf)==0xf) printf("\n");
122 }
123 printf("\n");
124}
125void get_mac_address_for_node_id(int node_id, char *mac_addr) {
126 int i;
127 int add = node_id;
128 int carry = 0;
129 int mac;
130 for (i=5; i>=0;i--) {
131 mac = (int)based_mac[i];
132 mac += (add + carry);
133 add = 0;
134 if (mac > 255) {
135 carry = 1;
136 mac -= 256;
137 } else {
138 carry = 0;
139 }
140 mac_addr[i] = (char)mac;
141 }
142}
143//return node_id or -1 for error
144int get_node_id_by_mac_address(unsigned char *target_mac_addr) {
145 char mac_addr[ETH_ALEN];
146 int i;
147 for (i=0; i<MAX_SERVER_NODE; i++) {
148 get_mac_address_for_node_id(i, mac_addr);
149 if (0 == memcmp(target_mac_addr, mac_addr, ETH_ALEN))
150 break;
151 }
152 if (i != MAX_SERVER_NODE) {
153// int j;
154// printf("mac_address for node[%d]:", i+1);
155// for (j=0; j<6; j++)
156// printf("%02x:", 0xff & mac_addr[j]);
157// printf("\n");
158 return i;
159 } else
160 return -1;
161}
162#if ENABLE_MONOTONIC_SYSCALL
163#include <sys/syscall.h>
164/* Old glibc (< 2.3.4) does not provide this constant. We use syscall
165 * directly so this definition is safe. */
166#ifndef CLOCK_MONOTONIC
167#define CLOCK_MONOTONIC 1
168#endif
169
170unsigned FAST_FUNC monotonic_sec(void)
171{
172 struct timespec ts;
173 get_mono(&ts);
174 return ts.tv_sec;
175}
176
177#else
178
179unsigned monotonic_sec(void)
180{
181 return time(NULL);
182}
183#endif
184//query ip addr for server node w/ mac addr
185//inarp "ethX" "peer mac addr(xx:xx:xx:xx:xx:xx)"
186//inarp daemon to handle inarp packets
187//inarp "ethX" "file for storing node list"
188void InvARPServerTask(
189 /** the internal task ID of this task (in) */
190 ULONG thread_input
191 )
192{
193 int fd, ret;
194 /*buffer for ethernet frame*/
195 static unsigned char buffer[ETH_FRAME_LEN]; /* single packets are usually not bigger than 8192 bytes */
196 int send_result = 0;
197 static struct ifreq ifreq_buffer;
198
199 /*our MAC address*/
200 static unsigned char src_mac[6];
201 static unsigned char src_ip[4];
202 int ifindex;
203// int InARP_SERVER;
204
205 if (((fd = socket (AF_PACKET, SOCK_PACKET, htons(ETH_P_ARP)))) == -1) {
206// if (((fd = socket (AF_PACKET, SOCK_RAW, 0))) == -1) {
207 printf("socket: [%s]\n", strerror(errno));
208 exit(-1);
209 }
210 //local mac address
211 memset(&ifreq_buffer, 0x00, sizeof(ifreq_buffer));
212 strcpy(ifreq_buffer.ifr_name, "ncsi0");
213 ret = ioctl(fd, SIOCGIFHWADDR, &ifreq_buffer);
214 if (ret == -1) {
215 printf("ioctl2: [%s]\n", strerror(errno));
216 close(fd);
217 exit(-1);
218 }
219 memcpy(src_mac, ifreq_buffer.ifr_hwaddr.sa_data, ETH_ALEN);
220 show_mac_addr("ncsi0", src_mac);
221 //interface index
222 memset(&ifreq_buffer, 0x00, sizeof(ifreq_buffer));
223 strcpy(ifreq_buffer.ifr_name, "ncsi0");
224 ret = ioctl(fd, SIOCGIFINDEX, &ifreq_buffer);
225 if (ret == -1) {
226 printf("ioctl4: [%s]\n", strerror(errno));
227 close(fd);
228 exit(-1);
229 }
230 ifindex = ifreq_buffer.ifr_ifindex;
231
232 int length = 0; /*length of the received frame*/
233 static struct ETH_ARP_PACKET *inarp_req = (struct ETH_ARP_PACKET *)buffer; /* single packets are usually not bigger than 8192 bytes */
234 static struct ETH_ARP_PACKET inarp_resp; /* single packets are usually not bigger than 8192 bytes */
235 static struct {
236 unsigned char dest_ip[4];
237 struct timespec update_time;
238 } node[SKU1_MAX_SERVER_NODES];
239 struct timespec current_time;
240 //argv[2]: file name used for storing node ip list
241 // line format in file: <node_id> <mac_addr> <ip_addr>
242 //get based address via EMS
243 //set socket as async
244// fcntl(fd, F_SETFL,O_NONBLOCK|FASYNC);
245 //got based address
246 while (1) {
247 //get local ip address
248 memset(&ifreq_buffer, 0x00, sizeof(ifreq_buffer));
249 strcpy(ifreq_buffer.ifr_name, "ncsi0");
250 ret = ioctl(fd, SIOCGIFADDR, &ifreq_buffer);
251 if (ret == -1) {
252// printf("ioctl3: [%s]\n", strerror(errno));
253 sleep(1);
254 continue;
255 }
256
257 if (AF_INET == ifreq_buffer.ifr_addr.sa_family) {
258 memcpy(src_ip, &ifreq_buffer.ifr_addr.sa_data[2], 4);
259// show_ip_addr("local", (unsigned char *)&ifreq_buffer.ifr_addr.sa_data[2]);
260 //show_ip_addr("local", src_ip);
261 } else {
262 printf("unknown address family [%d]!\n", ifreq_buffer.ifr_addr.sa_family);
263 sleep(1);
264 continue;
265 }
266
267 memset((void*)&inarp_resp, 0, sizeof inarp_resp);
268 length = recvfrom(fd, buffer, ETH_ARP_FRAME_LEN, 0, NULL, NULL);
269 if (length == -1) {
270 sleep(1);
271 }
272// printf("length = %d\r\nfd = %d\r\n", length, fd);
273 current_time.tv_sec = (unsigned)monotonic_sec();
274 if (0 == memcmp(src_mac, inarp_req->eh.h_dest, ETH_ALEN)) {
275 if (ntohs(inarp_req->arp.ar_op) == ARPOP_InREQUEST) { //get a inverse arp request
276// printf("[Rsp] InRequest\n");
277 //dump_data("got InARP request packet", buffer, length);
278 //send inarp response
279
280 printf("src mac =%02x:%02x:%02x:%02x:%02x:%02x\r\n",
281 inarp_req->arp_data.src_mac[0],
282 inarp_req->arp_data.src_mac[1],
283 inarp_req->arp_data.src_mac[2],
284 inarp_req->arp_data.src_mac[3],
285 inarp_req->arp_data.src_mac[4],
286 inarp_req->arp_data.src_mac[5]
287 );
288 printf("src ip =%d:%d:%d:%d\r\n",
289 inarp_req->arp_data.src_ip[0],
290 inarp_req->arp_data.src_ip[1],
291 inarp_req->arp_data.src_ip[2],
292 inarp_req->arp_data.src_ip[3]
293 );
294 int fd_1;
295 if (((fd_1 = socket (AF_PACKET, SOCK_RAW, 0))) == -1) {
296 printf("socket: [%s]\n", strerror(errno));
297 exit(-1);
298 }
299 send_result = send_arp_packet(fd_1, ifindex, &inarp_resp, ARPOP_InREPLY,
300 inarp_req->arp_data.dest_mac, src_ip,
301 inarp_req->arp_data.src_mac, inarp_req->arp_data.src_ip);
302 close(fd_1);
303 if (send_result == -1) {
304 printf("[Rsp] sendto: [%s]\n", strerror(errno));
305 sleep(1);
306 continue;
307 }
308 }
309// } else if (ntohs(inarp_req->arp.ar_op) == ARPOP_InREPLY) { //get a InARP Response
310// int node_id;
311// printf("[Rsp] InReply\n");
312// node_id = get_node_id_by_mac_address(inarp_req->arp_data.src_mac);
313// if (node_id == -1) {
314// //invalid node
315// printf("%02x:%02x:%02x:%02x:%02x:%02x does not belong to this rack.",
316// inarp_req->arp_data.src_mac[0],
317// inarp_req->arp_data.src_mac[1],
318// inarp_req->arp_data.src_mac[2],
319// inarp_req->arp_data.src_mac[3],
320// inarp_req->arp_data.src_mac[4],
321// inarp_req->arp_data.src_mac[5]
322// );
323// } else {
324 //valid node id
325// node[node_id].update_time.tv_sec = current_time.tv_sec;
326 //update or remain node's ip
327// if ((0 != memcmp(node[node_id].dest_ip, inarp_req->arp_data.src_ip, 4))) {
328 //ip address is changed.
329// static char ipv4_addr[16];
330// printf("[Rsp] update node[%d] ip @ %u\n", node_id+1, (unsigned)current_time.tv_sec);
331// show_mac_addr("[Rsp] ", inarp_req->arp_data.src_mac);
332// show_ip_addr("[Rsp] ", inarp_req->arp_data.src_ip);
333// memcpy(node[node_id].dest_ip, inarp_req->arp_data.src_ip, 4);
334// sprintf(ipv4_addr, "%d.%d.%d.%d",
335// inarp_req->arp_data.src_ip[0],
336// inarp_req->arp_data.src_ip[1],
337// inarp_req->arp_data.src_ip[2],
338// inarp_req->arp_data.src_ip[3]);
339// printf("[Rsp] update node[%d] ip @ %u\n", node_id+1, (unsigned)current_time.tv_sec);
340// }
341 memset(buffer, 0, sizeof(buffer));
342 }
343 }
344 close(fd);
345 return 0;
346}