blob: 19c07d4410ffbf21e84664d8900c1af43ff64366 [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 {
Jeremy Kerr5514f7b2016-02-25 12:41:44 +080025 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
Jeremy Kerr42dc98c2016-02-25 10:23:14 +080029};
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
Jeremy Kerr5514f7b2016-02-25 12:41:44 +080038static char based_mac[6] = { 0, 0, 0, 0, 0, 0 };
39
Jeremy Kerr42dc98c2016-02-25 10:23:14 +080040int send_arp_packet(int fd,
Jeremy Kerr5514f7b2016-02-25 12:41:44 +080041 int ifindex,
42 struct ETH_ARP_PACKET *eth_arp,
43 __be16 ar_op,
44 unsigned char *src_mac,
45 unsigned char *src_ip,
46 unsigned char *dest_mac, unsigned char *dest_ip)
Jeremy Kerr42dc98c2016-02-25 10:23:14 +080047{
48 int send_result = 0;
49 struct ethhdr *eh = &eth_arp->eh;
50 struct arphdr *arp = &eth_arp->arp;
51 struct ARP_DATA *arp_data = &eth_arp->arp_data;
Jeremy Kerr5514f7b2016-02-25 12:41:44 +080052 /*target address */
Jeremy Kerr42dc98c2016-02-25 10:23:14 +080053 struct sockaddr_ll socket_address;
Jeremy Kerr5514f7b2016-02-25 12:41:44 +080054 /*prepare sockaddr_ll */
55 /*RAW communication */
56 socket_address.sll_family = PF_PACKET;
Jeremy Kerr42dc98c2016-02-25 10:23:14 +080057 /*we don't use a protocoll above ethernet layer
Jeremy Kerr5514f7b2016-02-25 12:41:44 +080058 ->just use anything here */
Jeremy Kerr42dc98c2016-02-25 10:23:14 +080059 socket_address.sll_protocol = htons(ETH_P_ARP);
60 /*index of the network device
Jeremy Kerr5514f7b2016-02-25 12:41:44 +080061 see full code later how to retrieve it */
62 socket_address.sll_ifindex = ifindex;
63 /*ARP hardware identifier is ethernet */
64 socket_address.sll_hatype = ARPHRD_ETHER;
65 /*target is another host */
66 socket_address.sll_pkttype = PACKET_OTHERHOST;
67 /*address length */
68 socket_address.sll_halen = ETH_ALEN;
Jeremy Kerr42dc98c2016-02-25 10:23:14 +080069 memcpy(socket_address.sll_addr, dest_mac, ETH_ALEN);
Jeremy Kerr5514f7b2016-02-25 12:41:44 +080070 /*set the frame header */
71 memcpy((void *)eh->h_dest, (void *)dest_mac, ETH_ALEN);
72 memcpy((void *)eh->h_source, (void *)src_mac, ETH_ALEN);
Jeremy Kerr42dc98c2016-02-25 10:23:14 +080073 eh->h_proto = htons(ETH_P_ARP);
Jeremy Kerr5514f7b2016-02-25 12:41:44 +080074 /*fill InARP request data for ethernet + ipv4 */
Jeremy Kerr42dc98c2016-02-25 10:23:14 +080075 arp->ar_hrd = htons(ARPHRD_ETHER);
76 arp->ar_pro = htons(ETH_P_ARP);
77 arp->ar_hln = ETH_ALEN;
78 arp->ar_pln = 4;
Jeremy Kerr5514f7b2016-02-25 12:41:44 +080079 arp->ar_op = htons(ar_op);
Jeremy Kerr42dc98c2016-02-25 10:23:14 +080080 //fill arp ethernet mac & ipv4 info
Jeremy Kerr5514f7b2016-02-25 12:41:44 +080081 arp_data = (void *)(arp + 1);
82 memcpy(arp_data->src_mac, (void *)src_mac, ETH_ALEN); //source mac addr
83 memcpy(arp_data->src_ip, src_ip, 4); //source ip addr
84 memcpy(arp_data->dest_mac, (void *)dest_mac, ETH_ALEN); //dest mac addr
85 memcpy(arp_data->dest_ip, dest_ip, 4); //dest ip
86 /*send the packet */
87 send_result = sendto(fd, eth_arp, ETH_ARP_FRAME_LEN, 0,
88 (struct sockaddr *)&socket_address,
89 sizeof(socket_address));
Jeremy Kerr42dc98c2016-02-25 10:23:14 +080090 if (send_result == -1) {
Jeremy Kerr5514f7b2016-02-25 12:41:44 +080091 printf("sendto: [%s]\n", strerror(errno));
Jeremy Kerr42dc98c2016-02-25 10:23:14 +080092 }
93 return send_result;
94}
Jeremy Kerr5514f7b2016-02-25 12:41:44 +080095
Jeremy Kerr42dc98c2016-02-25 10:23:14 +080096void show_mac_addr(char *name, unsigned char *mac_addr)
97{
98 int i;
99 printf("%s MAC address: ", name);
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800100 for (i = 0; i < 6; i++) {
101 printf("%.2X%c", (unsigned char)mac_addr[i],
102 (i == 5) ? '\n' : ':');
103 }
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800104 return;
105}
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800106
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800107void show_ip_addr(char *desc, unsigned char *ip_addr)
108{
109 int i;
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800110 printf("%s IPv4 address: ", desc);
111 for (i = 0; i < 4; i++) {
112 printf("%d%c", (unsigned char)ip_addr[i],
113 (i == 3) ? '\n' : '.');
114 }
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800115}
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800116
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800117void dump_data(char *desc, unsigned char *buffer, int length)
118{
119 int i;
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800120 printf("%s & length is [%d]:\n", desc, length);
121 for (i = 0; i < length; i++) {
122 printf("[%02X]", 0xff & buffer[i]);
123 if ((i & 0xf) == 0x7)
124 printf(" - ");
125 if ((i & 0xf) == 0xf)
126 printf("\n");
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800127 }
128 printf("\n");
129}
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800130
131void get_mac_address_for_node_id(int node_id, char *mac_addr)
132{
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800133 int i;
134 int add = node_id;
135 int carry = 0;
136 int mac;
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800137 for (i = 5; i >= 0; i--) {
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800138 mac = (int)based_mac[i];
139 mac += (add + carry);
140 add = 0;
141 if (mac > 255) {
142 carry = 1;
143 mac -= 256;
144 } else {
145 carry = 0;
146 }
147 mac_addr[i] = (char)mac;
148 }
149}
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800150
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800151//return node_id or -1 for error
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800152int get_node_id_by_mac_address(unsigned char *target_mac_addr)
153{
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800154 char mac_addr[ETH_ALEN];
155 int i;
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800156 for (i = 0; i < MAX_SERVER_NODE; i++) {
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800157 get_mac_address_for_node_id(i, mac_addr);
158 if (0 == memcmp(target_mac_addr, mac_addr, ETH_ALEN))
159 break;
160 }
161 if (i != MAX_SERVER_NODE) {
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800162// int j;
163// printf("mac_address for node[%d]:", i+1);
164// for (j=0; j<6; j++)
165// printf("%02x:", 0xff & mac_addr[j]);
166// printf("\n");
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800167 return i;
168 } else
169 return -1;
170}
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800171
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800172#if ENABLE_MONOTONIC_SYSCALL
173#include <sys/syscall.h>
174/* Old glibc (< 2.3.4) does not provide this constant. We use syscall
175 * directly so this definition is safe. */
176#ifndef CLOCK_MONOTONIC
177#define CLOCK_MONOTONIC 1
178#endif
179
180unsigned FAST_FUNC monotonic_sec(void)
181{
182 struct timespec ts;
183 get_mono(&ts);
184 return ts.tv_sec;
185}
186
187#else
188
189unsigned monotonic_sec(void)
190{
191 return time(NULL);
192}
193#endif
194//query ip addr for server node w/ mac addr
195//inarp "ethX" "peer mac addr(xx:xx:xx:xx:xx:xx)"
196//inarp daemon to handle inarp packets
197//inarp "ethX" "file for storing node list"
198void InvARPServerTask(
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800199 /** the internal task ID of this task (in) */
200 ULONG thread_input)
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800201{
202 int fd, ret;
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800203 /*buffer for ethernet frame */
204 static unsigned char buffer[ETH_FRAME_LEN]; /* single packets are usually not bigger than 8192 bytes */
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800205 int send_result = 0;
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800206 static struct ifreq ifreq_buffer;
207
208 /*our MAC address */
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800209 static unsigned char src_mac[6];
210 static unsigned char src_ip[4];
211 int ifindex;
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800212// int InARP_SERVER;
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800213
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800214 if (((fd = socket(AF_PACKET, SOCK_PACKET, htons(ETH_P_ARP)))) == -1) {
215// if (((fd = socket (AF_PACKET, SOCK_RAW, 0))) == -1) {
216 printf("socket: [%s]\n", strerror(errno));
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800217 exit(-1);
218 }
219 //local mac address
220 memset(&ifreq_buffer, 0x00, sizeof(ifreq_buffer));
221 strcpy(ifreq_buffer.ifr_name, "ncsi0");
222 ret = ioctl(fd, SIOCGIFHWADDR, &ifreq_buffer);
223 if (ret == -1) {
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800224 printf("ioctl2: [%s]\n", strerror(errno));
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800225 close(fd);
226 exit(-1);
227 }
228 memcpy(src_mac, ifreq_buffer.ifr_hwaddr.sa_data, ETH_ALEN);
229 show_mac_addr("ncsi0", src_mac);
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800230 //interface index
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800231 memset(&ifreq_buffer, 0x00, sizeof(ifreq_buffer));
232 strcpy(ifreq_buffer.ifr_name, "ncsi0");
233 ret = ioctl(fd, SIOCGIFINDEX, &ifreq_buffer);
234 if (ret == -1) {
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800235 printf("ioctl4: [%s]\n", strerror(errno));
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800236 close(fd);
237 exit(-1);
238 }
239 ifindex = ifreq_buffer.ifr_ifindex;
240
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800241 int length = 0; /*length of the received frame */
242 static struct ETH_ARP_PACKET *inarp_req = (struct ETH_ARP_PACKET *)buffer; /* single packets are usually not bigger than 8192 bytes */
243 static struct ETH_ARP_PACKET inarp_resp; /* single packets are usually not bigger than 8192 bytes */
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800244 static struct {
245 unsigned char dest_ip[4];
246 struct timespec update_time;
247 } node[SKU1_MAX_SERVER_NODES];
248 struct timespec current_time;
249 //argv[2]: file name used for storing node ip list
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800250 // line format in file: <node_id> <mac_addr> <ip_addr>
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800251 //get based address via EMS
252 //set socket as async
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800253// fcntl(fd, F_SETFL,O_NONBLOCK|FASYNC);
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800254 //got based address
255 while (1) {
256 //get local ip address
257 memset(&ifreq_buffer, 0x00, sizeof(ifreq_buffer));
258 strcpy(ifreq_buffer.ifr_name, "ncsi0");
259 ret = ioctl(fd, SIOCGIFADDR, &ifreq_buffer);
260 if (ret == -1) {
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800261// printf("ioctl3: [%s]\n", strerror(errno));
262 sleep(1);
263 continue;
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800264 }
265
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800266 if (AF_INET == ifreq_buffer.ifr_addr.sa_family) {
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800267 memcpy(src_ip, &ifreq_buffer.ifr_addr.sa_data[2], 4);
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800268// show_ip_addr("local", (unsigned char *)&ifreq_buffer.ifr_addr.sa_data[2]);
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800269 //show_ip_addr("local", src_ip);
270 } else {
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800271 printf("unknown address family [%d]!\n",
272 ifreq_buffer.ifr_addr.sa_family);
273 sleep(1);
274 continue;
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800275 }
276
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800277 memset((void *)&inarp_resp, 0, sizeof inarp_resp);
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800278 length = recvfrom(fd, buffer, ETH_ARP_FRAME_LEN, 0, NULL, NULL);
279 if (length == -1) {
280 sleep(1);
281 }
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800282// printf("length = %d\r\nfd = %d\r\n", length, fd);
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800283 current_time.tv_sec = (unsigned)monotonic_sec();
284 if (0 == memcmp(src_mac, inarp_req->eh.h_dest, ETH_ALEN)) {
285 if (ntohs(inarp_req->arp.ar_op) == ARPOP_InREQUEST) { //get a inverse arp request
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800286// printf("[Rsp] InRequest\n");
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800287 //dump_data("got InARP request packet", buffer, length);
288 //send inarp response
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800289
290 printf
291 ("src mac =%02x:%02x:%02x:%02x:%02x:%02x\r\n",
292 inarp_req->arp_data.src_mac[0],
293 inarp_req->arp_data.src_mac[1],
294 inarp_req->arp_data.src_mac[2],
295 inarp_req->arp_data.src_mac[3],
296 inarp_req->arp_data.src_mac[4],
297 inarp_req->arp_data.src_mac[5]
298 );
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800299 printf("src ip =%d:%d:%d:%d\r\n",
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800300 inarp_req->arp_data.src_ip[0],
301 inarp_req->arp_data.src_ip[1],
302 inarp_req->arp_data.src_ip[2],
303 inarp_req->arp_data.src_ip[3]
304 );
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800305 int fd_1;
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800306 if (((fd_1 =
307 socket(AF_PACKET, SOCK_RAW, 0))) == -1) {
308 printf("socket: [%s]\n",
309 strerror(errno));
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800310 exit(-1);
311 }
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800312 send_result =
313 send_arp_packet(fd_1, ifindex, &inarp_resp,
314 ARPOP_InREPLY,
315 inarp_req->arp_data.
316 dest_mac, src_ip,
317 inarp_req->arp_data.src_mac,
318 inarp_req->arp_data.src_ip);
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800319 close(fd_1);
320 if (send_result == -1) {
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800321 printf("[Rsp] sendto: [%s]\n",
322 strerror(errno));
323 sleep(1);
324 continue;
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800325 }
326 }
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800327// } else if (ntohs(inarp_req->arp.ar_op) == ARPOP_InREPLY) { //get a InARP Response
328// int node_id;
329// printf("[Rsp] InReply\n");
330// node_id = get_node_id_by_mac_address(inarp_req->arp_data.src_mac);
331// if (node_id == -1) {
332// //invalid node
333// printf("%02x:%02x:%02x:%02x:%02x:%02x does not belong to this rack.",
334// inarp_req->arp_data.src_mac[0],
335// inarp_req->arp_data.src_mac[1],
336// inarp_req->arp_data.src_mac[2],
337// inarp_req->arp_data.src_mac[3],
338// inarp_req->arp_data.src_mac[4],
339// inarp_req->arp_data.src_mac[5]
340// );
341// } else {
342 //valid node id
343// node[node_id].update_time.tv_sec = current_time.tv_sec;
344 //update or remain node's ip
345// if ((0 != memcmp(node[node_id].dest_ip, inarp_req->arp_data.src_ip, 4))) {
346 //ip address is changed.
347// static char ipv4_addr[16];
348// printf("[Rsp] update node[%d] ip @ %u\n", node_id+1, (unsigned)current_time.tv_sec);
349// show_mac_addr("[Rsp] ", inarp_req->arp_data.src_mac);
350// show_ip_addr("[Rsp] ", inarp_req->arp_data.src_ip);
351// memcpy(node[node_id].dest_ip, inarp_req->arp_data.src_ip, 4);
352// sprintf(ipv4_addr, "%d.%d.%d.%d",
353// inarp_req->arp_data.src_ip[0],
354// inarp_req->arp_data.src_ip[1],
355// inarp_req->arp_data.src_ip[2],
356// inarp_req->arp_data.src_ip[3]);
357// printf("[Rsp] update node[%d] ip @ %u\n", node_id+1, (unsigned)current_time.tv_sec);
358// }
359 memset(buffer, 0, sizeof(buffer));
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800360 }
361 }
362 close(fd);
363 return 0;
364}