cloudFPGA (cF) API  1.0
The documentation of the source code of cloudFPGA (cF)
dhcp_client.cpp
Go to the documentation of this file.
1 
17 
43 
60 #include "dhcp_client.hpp"
61 
62 #define USE_DEPRECATED_DIRECTIVES
63 
64 
77 void pOpnComm(
78  ap_uint<1> &piMMIO_Enable,
79  stream<ap_uint<16> > &soUDMX_OpnReq,
80  stream<bool> &siUDMX_OpnAck,
81  stream<SigOpn> &soFsm_Signal)
82 {
83  //-- DIRECTIVES FOR THIS PROCESS ------------------------------------------
84  #pragma HLS PIPELINE II=1 enable_flush
85  #pragma HLS INLINE off
86 
87  //-- LOCAL VARIABLES ------------------------------------------------------
88  static bool opnAck = false;
89  static bool waitForAck = false;
90  static ap_uint<8> startupDelay = TIME_5S;
91 
92  if (piMMIO_Enable) {
93  if (startupDelay == 0) {
94  if (!opnAck && !waitForAck && !soUDMX_OpnReq.full()) {
95  // The DHCP protocol employs a connectionless service model, using
96  // the User Datagram Protocol (UDP). It is implemented with the two
97  // UDP port numbers 67 for server source port, and UDP port number
98  // 68 for the client source port.
99  soUDMX_OpnReq.write(68);
100  waitForAck = true;
101  }
102  else if (!siUDMX_OpnAck.empty() && waitForAck) {
103  siUDMX_OpnAck.read(opnAck);
104  soFsm_Signal.write(SIG_OPEN);
105  }
106  }
107  else
108  startupDelay--;
109  }
110 }
111 
112 
113 
126  stream<UdpWord> &siUDMX_Data,
127  stream<UdpMeta> &siUDMX_Meta,
128  stream<DhcpMetaRep> &soFsm_MetaRepFifo,
129  ap_uint<48> piMMIO_MacAddr)
130 {
131  //-- DIRECTIVES FOR THIS PROCESS ------------------------------------------
132  #pragma HLS PIPELINE II=1 enable_flush
133  #pragma HLS INLINE off
134 
135  //-- LOCAL STREAMS --------------------------------------------------------
136  static bool rcvMsgIsReply = false;
137  static bool rcvMsgHasMyMac = true;
138  static bool rcvMsgIsDhcp = false;
139  static ap_uint<6> rcvWordCount = 0;
140  static DhcpMetaRep metaReplyInfo;
141 
142  UdpWord currWord;
143 
144  if (!siUDMX_Data.empty()) {
145  siUDMX_Data.read(currWord);
146  //std::cout << std::hex << currWord.data << " " << currWord.last << std::endl;
147  switch (rcvWordCount) {
148 
149  case 0: // Type, HWTYPE, HWLEN, HOPS, ID
150  rcvMsgIsReply = currWord.tdata(7, 0) == 0x2;
151  metaReplyInfo.identifier = currWord.tdata(63, 32);
152  rcvMsgHasMyMac = true;
153  break;
154 
155  case 1: //SECS, FLAGS, ClientIp
156  // Do nothing
157  //currWord.data[32] == flag
158  break;
159 
160  case 2: //YourIP, NextServer IP
161  metaReplyInfo.assignedIpAddress = currWord.tdata(31, 0);
162  metaReplyInfo.serverAddress = currWord.tdata(63, 32); //TODO maybe not necessary
163  break;
164 
165  case 3: //Relay Agent, Client MAC part1
166  rcvMsgHasMyMac = (rcvMsgHasMyMac && (piMMIO_MacAddr(31, 0) == currWord.tdata(63, 32)));
167  break;
168 
169  case 4:
170  // Client Mac Part 2
171  rcvMsgHasMyMac = (rcvMsgHasMyMac && (piMMIO_MacAddr(47, 32) == currWord.tdata(15, 0)));
172  break;
173 
174  /*case 5: //client mac padding
175  case 7:
176  //legacy BOOTP
177  break;*/
178 
179  case 29:
180  // Assumption, no Option Overload and DHCP Message Type is first option
181  //MAGIC COOKIE
182  rcvMsgIsDhcp = (MAGIC_COOKIE == currWord.tdata(63, 32));
183  break;
184 
185  case 30:
186  //Option 53
187  if (currWord.tdata(15, 0) == 0x0135)
188  metaReplyInfo.type = currWord.tdata(23, 16);
189  break;
190 
191  default:
192  // 5-7 legacy BOOTP stuff
193  break;
194 
195  } // End: switch
196 
197  rcvWordCount++;
198  if (currWord.tlast) {
199  rcvWordCount = 0;
200  // Forward meta-reply information to FSM-ctrl process
201  if (rcvMsgIsReply && rcvMsgHasMyMac && rcvMsgIsDhcp)
202  soFsm_MetaRepFifo.write(metaReplyInfo);
203  }
204 
205  } // End: if not empty
206 
207  if (!siUDMX_Meta.empty())
208  siUDMX_Meta.read();
209 }
210 
211 
212 
226  stream<DhcpMetaReq> &siFsm_MetaReqFifo,
227  stream<UdpWord> &soUDMX_Data,
228  stream<UdpMeta> &soUDMX_Meta,
229  stream<UdpPLen> &soUDMX_PLen,
230  ap_uint<48> piMMIO_MacAddr)
231 {
232  //-- DIRECTIVES FOR THIS PROCESS ------------------------------------------
233  #pragma HLS PIPELINE II=1 enable_flush
234  #pragma HLS INLINE off
235 
236  //-- LOCAL VARIABLES ------------------------------------------------------
237  static ap_uint<6> sm_wordCount = 0;
238  static DhcpMetaReq meta;
239  UdpWord sendWord(0, 0xFF, 0);
240 
241  switch (sm_wordCount) {
242 
243  case 0:
244  if (!siFsm_MetaReqFifo.empty()) {
245  siFsm_MetaReqFifo.read(meta);
246  sendWord.tdata( 7, 0) = 0x01; //O
247  sendWord.tdata(15, 8) = 0x01; //HTYPE
248  sendWord.tdata(23, 16) = 0x06; //HLEN
249  sendWord.tdata(31, 24) = 0x00; //HOPS
250  // identifier
251  sendWord.tdata(63, 32) = meta.identifier;
252  soUDMX_Data.write(sendWord);
253  soUDMX_Meta.write(UdpMeta(SocketAddr(0x00000000, 68), SocketAddr(0xffffffff, 67)));
254  soUDMX_PLen.write(300); // 37*8 + 4
255  sm_wordCount++;
256  }
257  break;
258 
259  case 1: //secs, flags, CIADDR
260  sendWord.tdata(22, 0) = 0;
261  sendWord.tdata[23] = 0x1; // Broadcast flag
262  sendWord.tdata(63, 24) = 0;
263  soUDMX_Data.write(sendWord);
264  sm_wordCount++;
265  break;
266 
267  //case 2: //YIADDR, SIADDR
268  //case 5: //CHADDR padding + servername
269 
270  default: //BOOTP legacy
271  //case 5:
272  //case 6:
273  soUDMX_Data.write(sendWord);
274  sm_wordCount++;
275  break;
276 
277  case 3:
278  // GIADDR, CHADDR
279  sendWord.tdata(31, 0) = 0;
280  sendWord.tdata(63, 32) = piMMIO_MacAddr(31, 0);
281  soUDMX_Data.write(sendWord);
282  sm_wordCount++;
283  break;
284 
285  case 4:
286  sendWord.tdata(15, 0) = piMMIO_MacAddr(47, 32);
287  sendWord.tdata(63, 16) = 0;
288  soUDMX_Data.write(sendWord);
289  sm_wordCount++;
290  break;
291 
292  case 29:
293  sendWord.tdata(31, 0) = 0;
294  // Magic cookie
295  sendWord.tdata(63, 32) = MAGIC_COOKIE;
296  soUDMX_Data.write(sendWord);
297  sm_wordCount++;
298  break;
299 
300  case 30:
301  // DHCP option 53
302  sendWord.tdata(15, 0) = 0x0135;
303  sendWord.tdata(23, 16) = meta.type;
304  if (meta.type == DHCPDISCOVER) {
305  // We are done
306  sendWord.tdata(31, 24) = 0xff;
307  sendWord.tdata(63, 32) = 0;
308  }
309  else {
310  // Add DHCP Option 50, len 4, ip add
311  sendWord.tdata(31, 24) = 0x32; //50
312  sendWord.tdata(39, 32) = 0x04;
313  sendWord.tdata(63, 40) = meta.requestedIpAddress(23, 0);
314  }
315  sm_wordCount++;
316  soUDMX_Data.write(sendWord);
317  break;
318 
319  case 31:
320  // DHCP Option 50, len 4, ip add
321  if (meta.type == DHCPREQUEST)
322  sendWord.tdata(7, 0) = meta.requestedIpAddress(31, 24);
323  else
324  sendWord.tdata = 0;
325  sm_wordCount++;
326  soUDMX_Data.write(sendWord);
327  break;
328 
329  case 37:
330  // Last padding word, after 64bytes
331  sendWord.tkeep = 0x0f;
332  sendWord.tlast = 1;
333  soUDMX_Data.write(sendWord);
334  sm_wordCount = 0;
335  break;
336 
337  } // End of switch
338 }
339 
340 
341 
354 void pFsmCtrl(
355  stream<SigOpn> &siOpn_Signal,
356  ap_uint<1> &piMMIO_Enable,
357  stream<DhcpMetaRep> &siRcv_MsgFifo,
358  stream<DhcpMetaReq> &soSnd_MsgFifo,
359  ap_uint<32> &poNts_IpAddress)
360 
361 {
362  //-- DIRECTIVES FOR THIS PROCESS ------------------------------------------
363  #pragma HLS PIPELINE II=1 enable_flush
364  #pragma HLS INLINE off
365 
366  //-- LOCAL VARIABLES ------------------------------------------------------
367  static ap_uint<32> randomValue = 0x34aad34b;
368  static ap_uint<32> myIdentity = 0;
369  static ap_uint<32> myIpAddress = 0;
370  static ap_uint<32> IpAddressBuffer = 0;
371  static ap_uint<8> waitTime = 100;
372 
373  DhcpMetaRep rcvMsg;
374 
375  poNts_IpAddress = myIpAddress;
376 
377  static enum FsmState {PORT_WAIT=0, INIT, SELECTING, REQUESTING, BOUND} fsmState;
378 
379  switch (fsmState) {
380 
381  case PORT_WAIT:
382  if (!siOpn_Signal.empty()) {
383  SigOpn signal = siOpn_Signal.read();
384  if (signal == SIG_OPEN)
385  fsmState = INIT;
386  }
387  break;
388 
389  case INIT:
390  if (piMMIO_Enable == 1) {
391  if (waitTime == 0) {
392  myIdentity = randomValue;
393  soSnd_MsgFifo.write(DhcpMetaReq(randomValue, DHCPDISCOVER));
394  randomValue = (randomValue * 8) xor randomValue; // Update randomValue
395  waitTime = TIME_5S;
396  fsmState = SELECTING;
397  }
398  else
399  waitTime--;
400  }
401  break;
402 
403  case SELECTING:
404  if (!siRcv_MsgFifo.empty()) {
405  siRcv_MsgFifo.read(rcvMsg);
406  if (rcvMsg.identifier == myIdentity) {
407  if (rcvMsg.type == DHCPOFFER) {
408  IpAddressBuffer = rcvMsg.assignedIpAddress;
409  soSnd_MsgFifo.write(DhcpMetaReq(myIdentity, DHCPREQUEST, rcvMsg.assignedIpAddress));
410  waitTime = TIME_5S;
411  fsmState = REQUESTING;
412  }
413  else
414  fsmState = INIT;
415  }
416  }
417  else { //else we are waiting
418  if (waitTime == 0)
419  fsmState = INIT;
420  else // Decrease time-out value
421  waitTime--;
422  }
423  break;
424 
425  case REQUESTING:
426  if (!siRcv_MsgFifo.empty()) {
427  siRcv_MsgFifo.read(rcvMsg);
428  if (rcvMsg.identifier == myIdentity) {
429  if (rcvMsg.type == DHCPACK) { //TODO check if IP address correct
430  myIpAddress = IpAddressBuffer;
431  fsmState = BOUND;
432  }
433  else
434  fsmState = INIT;
435  }
436  //else omit
437  }
438  else {
439  if (waitTime == 0)
440  fsmState = INIT;
441  else // Decrease time-out value
442  waitTime--;
443  }
444  break;
445  case BOUND:
446  poNts_IpAddress = myIpAddress;
447  if (!siRcv_MsgFifo.empty())
448  siRcv_MsgFifo.read();
449  if (piMMIO_Enable == 0)
450  fsmState = INIT;
451  break;
452  }
453  randomValue++; //Make sure it doesn't get zero
454 }
455 
456 
457 
458 
475 
476  //------------------------------------------------------
477  //-- MMIO / This / Config Interfaces
478  //------------------------------------------------------
479  ap_uint<1> &piMMIO_This_Enable,
480  ap_uint<48> &piMMIO_This_MacAddress,
481 
482  //------------------------------------------------------
483  //-- THIS / Nts / IPv4 Interfaces
484  //------------------------------------------------------
485  ap_uint<32> &poTHIS_Nts_IpAddress,
486 
487  //------------------------------------------------------
488  //-- UDMX / This / Open-Port Interfaces
489  //------------------------------------------------------
490  stream<AxisAck> &siUDMX_This_OpnAck,
491  stream<UdpPort> &soTHIS_Udmx_OpnReq,
492 
493  //------------------------------------------------------
494  //-- UDMX / This / Data & MetaData Interfaces
495  //------------------------------------------------------
496  stream<UdpWord> &siUDMX_This_Data,
497  stream<UdpMeta> &siUDMX_This_Meta,
498  stream<UdpWord> &soTHIS_Udmx_Data,
499  stream<UdpMeta> &soTHIS_Udmx_Meta,
500  stream<UdpPort> &soTHIS_Udmx_PLen)
501 {
502 
503  //-- DIRECTIVES FOR THE INTERFACES ----------------------------------------
504  #pragma HLS INTERFACE ap_ctrl_none port=return
505 
506 
507 
508 
509 
511 #if defined(USE_DEPRECATED_DIRECTIVES)
512 
513  #pragma HLS INTERFACE ap_stable port=piMMIO_This_Enable
514  #pragma HLS INTERFACE ap_stable port=piMMIO_This_MacAddress
515 
516  #pragma HLS INTERFACE ap_none register port=poTHIS_Nts_IpAddress
517 
518  #pragma HLS resource core=AXI4Stream variable=siUDMX_This_OpnAck metadata="-bus_bundle siUDMX_This_OpnAck"
519  #pragma HLS resource core=AXI4Stream variable=soTHIS_Udmx_OpnReq metadata="-bus_bundle soTHIS_Udmx_OpnReq"
520 
521  #pragma HLS resource core=AXI4Stream variable=siUDMX_This_Data metadata="-bus_bundle siUDMX_This_Data"
522  #pragma HLS resource core=AXI4Stream variable=siUDMX_This_Meta metadata="-bus_bundle siUDMX_This_Meta"
523  #pragma HLS DATA_PACK variable=siUDMX_This_Meta
524 
525  #pragma HLS resource core=AXI4Stream variable=soTHIS_Udmx_Data metadata="-bus_bundle soTHIS_Udmx_Data"
526  #pragma HLS resource core=AXI4Stream variable=soTHIS_Udmx_Meta metadata="-bus_bundle soTHIS_Udmx_Meta"
527  #pragma HLS DATA_PACK variable=soTHIS_Udmx_Meta
528  #pragma HLS resource core=AXI4Stream variable=soTHIS_Udmx_PLen metadata="-bus_bundle soTHIS_Udmx_PLen"
529 
530 #else
531 
532  #pragma HLS INTERFACE ap_stable port=piMMIO_This_Enable
533  #pragma HLS INTERFACE ap_stable port=piMMIO_This_MacAddress
534 
535  #pragma HLS INTERFACE ap_none register port=poTHIS_Nts_IpAddress
536 
537  #pragma HLS INTERFACE axis register both port=siUDMX_This_OpnAck
538  #pragma HLS INTERFACE axis register both port=soTHIS_Udmx_OpnReq
539 
540  #pragma HLS INTERFACE axis register both port=siUDMX_This_Data
541  #pragma HLS INTERFACE axis register both port=siUDMX_This_Meta
542  #pragma HLS DATA_PACK variable=siUDMX_This_Meta instance=siUDMX_This_Meta
543 
544  #pragma HLS INTERFACE axis register both port=soTHIS_Udmx_Data
545  #pragma HLS INTERFACE axis register both port=soTHIS_Udmx_Meta
546  #pragma HLS DATA_PACK variable=soTHIS_Udmx_Meta instance=soTHIS_Udmx_Meta
547  #pragma HLS INTERFACE axis register both port=soTHIS_Udmx_PLen
548 
549 #endif
550 
551  //-- DIRECTIVES FOR THIS PROCESS ------------------------------------------
552  #pragma HLS DATAFLOW
553 
554  //-- LOCAL STREAMS --------------------------------------------------------
555  static stream<SigOpn> sOpnToFsm_Signal ("sOpnToFsm_Signal");
556 
557  static stream<DhcpMetaRep> sRcvToFsm_MetaRepFifo ("sRcvToFsm_MetaRepFifo");
558  #pragma HLS stream variable=sRcvToFsm_MetaRepFifo depth=4
559  #pragma HLS DATA_PACK variable=sRcvToFsm_MetaRepFifo
560 
561  static stream<DhcpMetaReq> sFsmToSnd_MetaReqFifo ("sFsmToSnd_MetaReqFifo");
562  #pragma HLS stream variable=sFsmToSnd_MetaReqFifo depth=4
563  #pragma HLS DATA_PACK variable=sFsmToSnd_MetaReqFifo
564 
565  //-- PROCESS FUNCTIONS ----------------------------------------------------
566 
567  pOpnComm(piMMIO_This_Enable,
568  soTHIS_Udmx_OpnReq, siUDMX_This_OpnAck,
569  sOpnToFsm_Signal);
570 
571  pRcvMessage(siUDMX_This_Data, siUDMX_This_Meta,
572  sRcvToFsm_MetaRepFifo, piMMIO_This_MacAddress);
573 
574  pFsmCtrl(sOpnToFsm_Signal, piMMIO_This_Enable,
575  sRcvToFsm_MetaRepFifo, sFsmToSnd_MetaReqFifo,
576  poTHIS_Nts_IpAddress);
577 
578  pSndMessage(sFsmToSnd_MetaReqFifo,
579  soTHIS_Udmx_Data, soTHIS_Udmx_Meta, soTHIS_Udmx_PLen,
580  piMMIO_This_MacAddress);
581 }
ap_uint< 8 > fsmState
void pFsmCtrl(stream< SigOpn > &siOpn_Signal, ap_uint< 1 > &piMMIO_Enable, stream< DhcpMetaRep > &siRcv_MsgFifo, stream< DhcpMetaReq > &soSnd_MsgFifo, ap_uint< 32 > &poNts_IpAddress)
Final state machine that controls the sending and reception of DHCP messages. to the.
void pSndMessage(stream< DhcpMetaReq > &siFsm_MetaReqFifo, stream< UdpWord > &soUDMX_Data, stream< UdpMeta > &soUDMX_Meta, stream< UdpPLen > &soUDMX_PLen, ap_uint< 48 > piMMIO_MacAddr)
Build a DHCP message from a meta-request information and send it out to the DHCP server.
void dhcp_client(ap_uint< 1 > &piMMIO_This_Enable, ap_uint< 48 > &piMMIO_This_MacAddress, ap_uint< 32 > &poTHIS_Nts_IpAddress, stream< AxisAck > &siUDMX_This_OpnAck, stream< UdpPort > &soTHIS_Udmx_OpnReq, stream< UdpWord > &siUDMX_This_Data, stream< UdpMeta > &siUDMX_This_Meta, stream< UdpWord > &soTHIS_Udmx_Data, stream< UdpMeta > &soTHIS_Udmx_Meta, stream< UdpPort > &soTHIS_Udmx_PLen)
Main process of the DHCP-client.
void pRcvMessage(stream< UdpWord > &siUDMX_Data, stream< UdpMeta > &siUDMX_Meta, stream< DhcpMetaRep > &soFsm_MetaRepFifo, ap_uint< 48 > piMMIO_MacAddr)
Receive a message from the DHCP server and generate a meta-reply information for the FSM control proc...
void pOpnComm(ap_uint< 1 > &piMMIO_Enable, stream< ap_uint< 16 > > &soUDMX_OpnReq, stream< bool > &siUDMX_OpnAck, stream< SigOpn > &soFsm_Signal)
Open a communication end point. This corresponds somehow to the creation of a UDP socket at the clien...
Definition: dhcp_client.cpp:77
: Dynamic Host Configuration Protocol (DHCP) client.
ap_uint< 1 > SigOpn
@ DHCPACK
Definition: dhcp_client.hpp:90
@ DHCPOFFER
Definition: dhcp_client.hpp:88
@ DHCPREQUEST
Definition: dhcp_client.hpp:89
@ DHCPDISCOVER
Definition: dhcp_client.hpp:87
ap_uint< 32 > myIpAddress
Definition: tb_nal.cpp:140
ap_uint< 32 > serverAddress
Definition: dhcp_client.hpp:65
ap_uint< 8 > type
Definition: dhcp_client.hpp:66
ap_uint< 32 > identifier
Definition: dhcp_client.hpp:63
ap_uint< 32 > assignedIpAddress
Definition: dhcp_client.hpp:64
ap_uint< 8 > type
Definition: dhcp_client.hpp:71
ap_uint< 32 > requestedIpAddress
Definition: dhcp_client.hpp:72
ap_uint< 32 > identifier
Definition: dhcp_client.hpp:70
ap_uint< 64 > tdata
ap_uint< 1 > tlast
ap_uint< 8 > tkeep