32 #define KNXIP_HEADER_LEN 0x6
33 #define KNXIP_PROTOCOL_VERSION 0x10
35 #define MIN_LEN_CEMI 10
42 bool IpDataLinkLayer::sendFrame(
CemiFrame& frame)
47 if (isSendLimitReached())
50 bool success = sendBytes(packet.data(), packet.totalLength());
51 #ifdef KNX_ACTIVITYCALLBACK
54 _dllcb->
activity((
_netIndex << KNX_ACTIVITYCALLBACK_NET) | (KNX_ACTIVITYCALLBACK_DIR_SEND << KNX_ACTIVITYCALLBACK_DIR));
66 for (
int i = 0; i < KNX_TUNNELING; i++)
68 sendFrameToTunnel(&tunnels[i], frame);
76 for (
int i = 0; i < KNX_TUNNELING; i++)
90 for (
int i = 0; i < KNX_TUNNELING; i++)
92 if (tunnels[i].IsConfig)
94 #ifdef KNX_LOG_TUNNELING
95 println(
"Found config Channel");
105 #ifdef KNX_LOG_TUNNELING
106 print(
"Found no Tunnel for IA: ");
112 sendFrameToTunnel(tun, frame);
119 for (
int i = 0; i < KNX_TUNNELING; i++)
121 sendFrameToTunnel(&tunnels[i], frame);
129 for (
int i = 0; i < KNX_TUNNELING; i++)
143 for (
int i = 0; i < KNX_TUNNELING; i++)
145 if (tunnels[i].IsConfig)
147 #ifdef KNX_LOG_TUNNELING
148 println(
"Found config Channel");
158 #ifdef KNX_LOG_TUNNELING
159 print(
"Found no Tunnel for IA: ");
165 sendFrameToTunnel(tun, frame);
172 for (
int i = 0; i < KNX_TUNNELING; i++)
174 sendFrameToTunnel(&tunnels[i], frame);
181 for (
int i = 0; i < KNX_TUNNELING; i++)
195 for (
int i = 0; i < KNX_TUNNELING; i++)
197 if (tunnels[i].IsConfig)
199 #ifdef KNX_LOG_TUNNELING
200 println(
"Found config Channel");
210 #ifdef KNX_LOG_TUNNELING
211 print(
"Found no Tunnel for IA: ");
217 sendFrameToTunnel(tun, frame);
222 #ifdef KNX_LOG_TUNNELING
223 print(
"Send to Channel: ");
228 req.connectionHeader().length(LEN_CH);
229 req.connectionHeader().channelId(tunnel->
ChannelId);
242 for (
int i = 0; i < KNX_TUNNELING; i++)
253 for (
int i = 0; i < KNX_TUNNELING; i++)
254 if (tunnels[i].ChannelId != 0)
261 for (
int i = 0; i < KNX_TUNNELING; i++)
277 for (
int i = 0; i < KNX_TUNNELING; i++)
279 if (tunnels[i].ChannelId != 0)
281 if (
millis() - tunnels[i].lastHeartbeat > 120000)
283 #ifdef KNX_LOG_TUNNELING
284 print(
"Closed Tunnel 0x");
285 print(tunnels[i].ChannelId, 16);
286 println(
" due to no heartbeat in 2 minutes");
306 uint16_t remotePort = 0;
307 uint32_t remoteAddr = 0;
313 if (len < KNXIP_HEADER_LEN)
316 if (buffer[0] != KNXIP_HEADER_LEN
317 || buffer[1] != KNXIP_PROTOCOL_VERSION)
320 #ifdef KNX_ACTIVITYCALLBACK
323 _dllcb->
activity((
_netIndex << KNX_ACTIVITYCALLBACK_NET) | (KNX_ACTIVITYCALLBACK_DIR_RECV << KNX_ACTIVITYCALLBACK_DIR));
344 auto hpai = searchRequest.
hpai();
345 #ifdef KNX_ACTIVITYCALLBACK
348 _dllcb->
activity((
_netIndex << KNX_ACTIVITYCALLBACK_NET) | (KNX_ACTIVITYCALLBACK_DIR_SEND << KNX_ACTIVITYCALLBACK_DIR) | (KNX_ACTIVITYCALLBACK_IPUNICAST));
357 #if KNX_SERVICE_FAMILY_CORE >= 2
358 loopHandleSearchRequestExtended(buffer, len);
367 loopHandleConnectRequest(buffer, len, remoteAddr, remotePort);
373 loopHandleConnectionStateRequest(buffer, len);
379 loopHandleDisconnectRequest(buffer, len);
385 loopHandleDescriptionRequest(buffer, len);
391 loopHandleDeviceConfigurationRequest(buffer, len);
397 loopHandleTunnelingRequest(buffer, len);
418 print(
"Unhandled service identifier: ");
424 #if KNX_SERVICE_FAMILY_CORE >= 2
425 void IpDataLinkLayer::loopHandleSearchRequestExtended(uint8_t* buffer, uint16_t length)
429 if (searchRequest.srpByProgMode)
437 if (searchRequest.srpByMacAddr)
442 for (
int i = 0; i < 6; i++)
443 if (searchRequest.srpMacAddr[i] != x[i])
447 #define LEN_SERVICE_FAMILIES 2
448 #if MASK_VERSION == 0x091A
450 #define LEN_SERVICE_DIB (2 + 4 * LEN_SERVICE_FAMILIES)
452 #define LEN_SERVICE_DIB (2 + 3 * LEN_SERVICE_FAMILIES)
456 #define LEN_SERVICE_DIB (2 + 3 * LEN_SERVICE_FAMILIES)
458 #define LEN_SERVICE_DIB (2 + 2 * LEN_SERVICE_FAMILIES)
463 int dibLength = LEN_DEVICE_INFORMATION_DIB + LEN_SERVICE_DIB + LEN_EXTENDED_DEVICE_INFORMATION_DIB;
465 if (searchRequest.srpByService)
468 uint8_t length = searchRequest.srpServiceFamilies[0];
469 uint8_t* currentPos = searchRequest.srpServiceFamilies + 2;
471 for (
int i = 0; i < (length - 2) / 2; i++)
473 uint8_t serviceFamily = (currentPos + i * 2)[0];
474 uint8_t version = (currentPos + i * 2)[1];
476 switch (serviceFamily)
479 if (version > KNX_SERVICE_FAMILY_CORE)
485 if (version > KNX_SERVICE_FAMILY_DEVICE_MANAGEMENT)
491 if (version > KNX_SERVICE_FAMILY_TUNNELING)
497 if (version > KNX_SERVICE_FAMILY_ROUTING)
505 if (searchRequest.srpRequestDIBs)
508 if(searchRequest.requestedDIB(
IP_CONFIG))
509 dibLength += LEN_IP_CONFIG_DIB;
512 dibLength += LEN_IP_CURRENT_CONFIG_DIB;
518 dibLength += 4 + length * 2;
528 dibLength += 4 + length * 4;
534 searchResponse.setDeviceInfo(_ipParameters, _deviceObject);
535 searchResponse.setSupportedServices();
536 searchResponse.setExtendedDeviceInfo();
538 if (searchRequest.srpRequestDIBs)
540 if (searchRequest.requestedDIB(
IP_CONFIG))
541 searchResponse.setIpConfig(_ipParameters);
544 searchResponse.setIpCurrentConfig(_ipParameters);
547 searchResponse.setKnxAddresses(_ipParameters, _deviceObject);
555 searchResponse.setTunnelingInfo(_ipParameters, _deviceObject, tunnels);
558 if(searchResponse.totalLength() > 500)
560 printf(
"skipped response length > 500. Length: %d bytes\n", searchResponse.totalLength());
564 _platform.
sendBytesUniCast(searchRequest.hpai().ipAddress(), searchRequest.hpai().ipPortNumber(), searchResponse.data(), searchResponse.totalLength());
569 void IpDataLinkLayer::loopHandleConnectRequest(uint8_t* buffer, uint16_t length, uint32_t& src_addr, uint16_t& src_port)
572 #ifdef KNX_LOG_TUNNELING
573 println(
"Got Connect Request!");
575 switch (connRequest.cri().type())
578 println(
"Device Management Connection");
594 println(
"ObjectServer Connection");
598 print(
"Data Endpoint: ");
599 uint32_t ip = connRequest.hpaiData().ipAddress();
602 print((ip >> 16) & 0xFF);
604 print((ip >> 8) & 0xFF);
608 println(connRequest.hpaiData().ipPortNumber());
609 print(
"Ctrl Endpoint: ");
610 ip = connRequest.hpaiCtrl().ipAddress();
613 print((ip >> 16) & 0xFF);
615 print((ip >> 8) & 0xFF);
619 println(connRequest.hpaiCtrl().ipPortNumber());
625 #ifdef KNX_LOG_TUNNELING
626 println(
"Only Tunnel/DeviceMgmt Connection ist supported!");
629 _platform.
sendBytesUniCast(connRequest.hpaiCtrl().ipAddress(), connRequest.hpaiCtrl().ipPortNumber(), connRes.data(), connRes.totalLength());
633 if (connRequest.cri().type() ==
TUNNEL_CONNECTION && connRequest.cri().layer() != 0x02)
636 #ifdef KNX_LOG_TUNNELING
637 println(
"Only LinkLayer ist supported!");
640 _platform.
sendBytesUniCast(connRequest.hpaiCtrl().ipAddress(), connRequest.hpaiCtrl().ipPortNumber(), connRes.data(), connRes.totalLength());
646 uint32_t srcIP = connRequest.hpaiCtrl().ipAddress() ? connRequest.hpaiCtrl().ipAddress() : src_addr;
647 uint16_t srcPort = connRequest.hpaiCtrl().ipPortNumber() ? connRequest.hpaiCtrl().ipPortNumber() : src_port;
650 uint16_t propCount = 0;
652 const uint8_t* addresses;
654 if (propCount == KNX_TUNNELING)
660 uint8_t addrbuffer[KNX_TUNNELING * 2];
661 addresses = (uint8_t*)addrbuffer;
663 for (
int i = 0; i < KNX_TUNNELING; i++)
665 addrbuffer[i * 2 + 1] = i + 1;
669 uint8_t count = KNX_TUNNELING;
671 #ifdef KNX_LOG_TUNNELING
672 println(
"no Tunnel-PAs configured, using own subnet");
677 const uint8_t* tunCtrlBytes =
nullptr;
679 if (propCount == KNX_TUNNELING)
683 const uint8_t* tunCtrlIp =
nullptr;
685 if (propCount == KNX_TUNNELING)
688 bool resTunActive = (tunCtrlBytes && tunCtrlIp);
689 #ifdef KNX_LOG_TUNNELING
692 println(
"Reserved Tunnel Feature active");
695 printHex(
"tunCtrlBytes", tunCtrlBytes, KNX_TUNNELING);
698 printHex(
"tunCtrlIp", tunCtrlIp, KNX_TUNNELING * 4);
703 int firstFreeTunnel = -1;
704 int firstResAndFreeTunnel = -1;
705 int firstResAndOccTunnel = -1;
706 bool tunnelResActive[KNX_TUNNELING] = {0};
707 uint8_t tunnelResOptions[KNX_TUNNELING] = {0};
709 for (
int i = 0; i < KNX_TUNNELING; i++)
713 tunnelResActive[i] = *(tunCtrlBytes + i) & 0x80;
714 tunnelResOptions[i] = (*(tunCtrlBytes + i) & 0x60) >> 5;
717 if(resTunActive && tunnelResActive[i])
719 #ifdef KNX_LOG_TUNNELING
720 print(
"tunnel reserve feature active for this tunnel: ");
721 print(tunnelResActive[i]);
727 popInt(rIP, tunCtrlIp + 4 * i);
732 if (tunnels[i].ChannelId == 0)
734 if (firstResAndFreeTunnel < 0)
735 firstResAndFreeTunnel = i;
739 if (firstResAndOccTunnel < 0)
740 firstResAndOccTunnel = i;
746 if (tunnels[i].ChannelId == 0 && firstFreeTunnel < 0)
751 #ifdef KNX_LOG_TUNNELING
752 print(
"firstFreeTunnel: ");
753 print(firstFreeTunnel);
754 print(
" firstResAndFreeTunnel: ");
755 print(firstResAndFreeTunnel);
756 print(
" firstResAndOccTunnel: ");
761 uint8_t tunIdx = 0xff;
763 if (resTunActive & (firstResAndFreeTunnel >= 0 || firstResAndOccTunnel >= 0))
765 if (firstResAndFreeTunnel >= 0)
767 tunIdx = firstResAndFreeTunnel;
769 else if (firstResAndOccTunnel >= 0)
771 if (tunnelResOptions[firstResAndOccTunnel] == 1)
775 else if (tunnelResOptions[firstResAndOccTunnel] == 2)
778 discReq.
channelId(tunnels[firstResAndOccTunnel].ChannelId);
784 tunnels[firstResAndOccTunnel].
Reset();
787 tunIdx = firstResAndOccTunnel;
789 else if (tunnelResOptions[firstResAndOccTunnel] == 3)
791 if (firstFreeTunnel >= 0)
792 tunIdx = firstFreeTunnel;
808 if (firstFreeTunnel >= 0)
809 tunIdx = firstFreeTunnel;
819 tun = &tunnels[tunIdx];
822 popWord(tunPa, addresses + (tunIdx * 2));
825 for (
int x = 0; x < KNX_TUNNELING; x++)
828 #ifdef KNX_LOG_TUNNELING
829 println(
"cannot use tunnel because PA is already in use");
842 println(
"no free tunnel availible");
844 _platform.
sendBytesUniCast(connRequest.hpaiCtrl().ipAddress(), connRequest.hpaiCtrl().ipPortNumber(), connRes.data(), connRes.totalLength());
857 channelIdInUse =
false;
859 for (
int x = 0; x < KNX_TUNNELING; x++)
860 if (tunnels[x].ChannelId == _lastChannelId)
861 channelIdInUse =
true;
862 }
while (channelIdInUse);
867 if (_lastChannelId == 255)
871 tun->
PortData = connRequest.hpaiData().ipPortNumber()?connRequest.hpaiData().ipPortNumber():srcPort;
872 tun->
PortCtrl = connRequest.hpaiCtrl().ipPortNumber()?connRequest.hpaiCtrl().ipPortNumber():srcPort;
874 print(
"New Tunnel-Connection[");
876 print(
"], Channel: 0x");
898 print(
" (Ctrlport: ");
905 print(
" (Config-Channel)");
915 void IpDataLinkLayer::loopHandleConnectionStateRequest(uint8_t* buffer, uint16_t length)
921 for (
int i = 0; i < KNX_TUNNELING; i++)
923 if (tunnels[i].ChannelId == stateRequest.channelId())
932 #ifdef KNX_LOG_TUNNELING
933 print(
"Channel ID nicht gefunden: ");
934 println(stateRequest.channelId());
937 _platform.
sendBytesUniCast(stateRequest.hpaiCtrl().ipAddress(), stateRequest.hpaiCtrl().ipPortNumber(), stateRes.data(), stateRes.totalLength());
948 _platform.
sendBytesUniCast(stateRequest.hpaiCtrl().ipAddress(), stateRequest.hpaiCtrl().ipPortNumber(), stateRes.data(), stateRes.totalLength());
951 void IpDataLinkLayer::loopHandleDisconnectRequest(uint8_t* buffer, uint16_t length)
955 #ifdef KNX_LOG_TUNNELING
956 print(
">>> Disconnect Channel ID: ");
962 for (
int i = 0; i < KNX_TUNNELING; i++)
964 if (tunnels[i].ChannelId == discReq.
channelId())
973 #ifdef KNX_LOG_TUNNELING
974 print(
"Channel ID nicht gefunden: ");
988 void IpDataLinkLayer::loopHandleDescriptionRequest(uint8_t* buffer, uint16_t length)
992 _platform.
sendBytesUniCast(descReq.hpaiCtrl().ipAddress(), descReq.hpaiCtrl().ipPortNumber(), descRes.data(), descRes.totalLength());
995 void IpDataLinkLayer::loopHandleDeviceConfigurationRequest(uint8_t* buffer, uint16_t length)
1001 for (
int i = 0; i < KNX_TUNNELING; i++)
1003 if (tunnels[i].ChannelId == confReq.connectionHeader().channelId())
1012 print(
"Channel ID nicht gefunden: ");
1013 println(confReq.connectionHeader().channelId());
1031 void IpDataLinkLayer::loopHandleTunnelingRequest(uint8_t* buffer, uint16_t length)
1037 for (
int i = 0; i < KNX_TUNNELING; i++)
1039 if (tunnels[i].ChannelId == tunnReq.connectionHeader().channelId())
1048 #ifdef KNX_LOG_TUNNELING
1049 print(
"Channel ID nicht gefunden: ");
1050 println(tunnReq.connectionHeader().channelId());
1057 uint8_t sequence = tunnReq.connectionHeader().sequenceCounter();
1061 #ifdef KNX_LOG_TUNNELING
1062 print(
"Received SequenceCounter again: ");
1063 println(tunnReq.connectionHeader().sequenceCounter());
1077 #ifdef KNX_LOG_TUNNELING
1078 print(
"Wrong SequenceCounter: got ");
1079 print(tunnReq.connectionHeader().sequenceCounter());
1080 print(
" expected ");
1096 if (tunnReq.frame().sourceAddress() == 0)
1107 if (value && !_enabled)
1114 if (!value && _enabled)
1132 bool IpDataLinkLayer::sendBytes(uint8_t* bytes, uint16_t length)
1140 bool IpDataLinkLayer::isSendLimitReached()
1142 uint32_t curTime =
millis() / 100;
1145 if (_frameCountTimeBase >= curTime)
1147 uint32_t timeBaseDiff = _frameCountTimeBase - curTime;
1149 if (timeBaseDiff > 10)
1152 for (uint32_t i = 0; i < timeBaseDiff ; i++)
1155 _frameCountBase = _frameCountBase % 10;
1156 _frameCount[_frameCountBase] = 0;
1159 _frameCountTimeBase = curTime;
1163 for (
int i = 0; i < 10 ; i++)
1166 _frameCountBase = 0;
1167 _frameCountTimeBase = curTime;
1173 for (
int i = 0; i < 10 ; i++)
1174 sum += _frameCount[i];
1178 println(
"Dropping packet due to 50p/s limit");
1183 _frameCount[_frameCountBase]++;
void printHex(const char *suffix, const uint8_t *data, size_t length, bool newline)
const uint8_t * popInt(uint32_t &i, const uint8_t *data)
const uint8_t * popWord(uint16_t &w, const uint8_t *data)
uint16_t sourceAddress() const
uint16_t destinationAddress() const
MessageCode messageCode() const
AddressType addressType() const
void frameReceived(CemiFrame &frame)
virtual void activity(uint8_t info)
void frameReceived(CemiFrame &frame)
void dataConReceived(CemiFrame &frame, bool success)
uint16_t individualAddress()
const uint8_t * propertyData(PropertyID id)
virtual void writeProperty(PropertyID id, uint16_t start, uint8_t *data, uint8_t &count)
Write property of the interface object.
virtual void readPropertyLength(PropertyID id, uint16_t &length)
Read length of a property of the interface object.
T propertyValue(PropertyID id)
DptMedium mediumType() const override
IpDataLinkLayer(DeviceObject &devObj, IpParameterObject &ipParam, NetworkLayerEntity &netLayerEntity, Platform &platform, DataLinkLayerCallbacks *dllcb=nullptr)
bool isSentToTunnel(uint16_t address, bool isGrpAddr)
void dataIndicationToTunnel(CemiFrame &frame) override
void dataConfirmationToTunnel(CemiFrame &frame) override
void dataRequestToTunnel(CemiFrame &frame) override
bool isTunnelAddress(uint16_t addr) override
void status(uint8_t status)
void sequenceCounter(uint8_t sequenceCounter)
void channelId(uint8_t channelId)
void length(uint8_t value)
IpHostProtocolAddressInformation & hpaiCtrl()
uint16_t totalLength() const
uint16_t serviceTypeIdentifier() const
IpHostProtocolAddressInformation & hpai()
uint8_t SequenceCounter_R
unsigned long lastHeartbeat
uint8_t SequenceCounter_S
uint16_t IndividualAddress
KnxIpCH & connectionHeader()
KnxFacade< SamdPlatform, Bau07B0 > knx(buttonEvent)
@ DeviceConfigurationRequest
@ PID_ADDITIONAL_INDIVIDUAL_ADDRESSES
@ PID_CUSTOM_RESERVED_TUNNELS_IP
@ PID_CUSTOM_RESERVED_TUNNELS_CTRL
@ PID_ROUTING_MULTICAST_ADDRESS