add icmp (untested, will need fifo)

This commit is contained in:
Florent Kermarrec 2015-02-06 01:38:30 +01:00
parent c0814ac63f
commit b1e0a21f78
3 changed files with 162 additions and 0 deletions

View File

@ -75,6 +75,15 @@ udp_header = {
udp_protocol = 0x11 udp_protocol = 0x11
icmp_header_len = 8
icmp_header = {
"msgtype": HField( 0, 0, 8),
"code": HField( 1, 0, 8),
"checksum": HField( 2, 0, 16),
"quench": HField( 4, 0, 32)
}
icmp_protocol = 0x01
def reverse_bytes(v): def reverse_bytes(v):
n = math.ceil(flen(v)/8) n = math.ceil(flen(v)/8)
r = [] r = []
@ -163,6 +172,22 @@ def eth_udp_user_description(dw):
] ]
return EndpointDescription(layout, packetized=True) return EndpointDescription(layout, packetized=True)
def eth_icmp_description(dw):
layout = _layout_from_header(icmp_header) + [
("data", dw),
("error", dw//8)
]
return EndpointDescription(layout, packetized=True)
def eth_icmp_user_description(dw):
layout = _layout_from_header(icmp_header) + [
("ip_address", 32),
("length", 16),
("data", dw),
("error", dw//8)
]
return EndpointDescription(layout, packetized=True)
# Generic modules # Generic modules
@DecorateModule(InsertReset) @DecorateModule(InsertReset)
@DecorateModule(InsertCE) @DecorateModule(InsertCE)

View File

@ -3,12 +3,14 @@ from liteeth.mac import LiteEthMAC
from liteeth.core.arp import LiteEthARP from liteeth.core.arp import LiteEthARP
from liteeth.core.ip import LiteEthIP from liteeth.core.ip import LiteEthIP
from liteeth.core.udp import LiteEthUDP from liteeth.core.udp import LiteEthUDP
from liteeth.core.icmp import LiteEthICMP
class LiteEthIPCore(Module, AutoCSR): class LiteEthIPCore(Module, AutoCSR):
def __init__(self, phy, mac_address, ip_address, clk_freq): def __init__(self, phy, mac_address, ip_address, clk_freq):
self.submodules.mac = LiteEthMAC(phy, 8, interface="crossbar", with_hw_preamble_crc=True) self.submodules.mac = LiteEthMAC(phy, 8, interface="crossbar", with_hw_preamble_crc=True)
self.submodules.arp = LiteEthARP(self.mac, mac_address, ip_address, clk_freq) self.submodules.arp = LiteEthARP(self.mac, mac_address, ip_address, clk_freq)
self.submodules.ip = LiteEthIP(self.mac, mac_address, ip_address, self.arp.table) self.submodules.ip = LiteEthIP(self.mac, mac_address, ip_address, self.arp.table)
self.submodules.icmp = LiteEthICMP(self.ip, ip_address)
class LiteEthUDPIPCore(LiteEthIPCore): class LiteEthUDPIPCore(LiteEthIPCore):
def __init__(self, phy, mac_address, ip_address, clk_freq): def __init__(self, phy, mac_address, ip_address, clk_freq):

View File

@ -0,0 +1,135 @@
from liteeth.common import *
from liteeth.generic.depacketizer import LiteEthDepacketizer
from liteeth.generic.packetizer import LiteEthPacketizer
class LiteEthICMPDepacketizer(LiteEthDepacketizer):
def __init__(self):
LiteEthDepacketizer.__init__(self,
eth_ipv4_user_description(8),
eth_icmp_description(8),
icmp_header,
icmp_header_len)
class LiteEthICMPPacketizer(LiteEthPacketizer):
def __init__(self):
LiteEthPacketizer.__init__(self,
eth_icmp_description(8),
eth_ipv4_user_description(8),
icmp_header,
icmp_header_len)
class LiteEthICMPTX(Module):
def __init__(self, ip_address):
self.sink = Sink(eth_icmp_user_description(8))
self.source = Source(eth_ipv4_user_description(8))
###
packetizer = LiteEthICMPPacketizer()
self.submodules += packetizer
self.comb += [
packetizer.sink.stb.eq(self.sink.stb),
packetizer.sink.sop.eq(self.sink.sop),
packetizer.sink.eop.eq(self.sink.eop),
self.sink.ack.eq(packetizer.sink.ack),
packetizer.sink.msgtype.eq(self.sink.msgtype),
packetizer.sink.code.eq(self.sink.code),
packetizer.sink.checksum.eq(self.sink.checksum),
packetizer.sink.quench.eq(self.sink.quench),
packetizer.sink.data.eq(self.sink.data)
]
sink = packetizer.source
self.submodules.fsm = fsm = FSM(reset_state="IDLE")
fsm.act("IDLE",
sink.ack.eq(1),
If(sink.stb & sink.sop,
sink.ack.eq(0),
NextState("SEND")
)
)
fsm.act("SEND",
Record.connect(packetizer.source, self.source),
self.source.length.eq(self.sink.length + icmp_header_len),
self.source.protocol.eq(icmp_protocol),
self.source.ip_address.eq(self.sink.ip_address),
If(self.source.stb & self.source.eop & self.source.ack,
NextState("IDLE")
)
)
class LiteEthICMPRX(Module):
def __init__(self, ip_address):
self.sink = Sink(eth_ipv4_user_description(8))
self.source = source = Source(eth_icmp_user_description(8))
###
depacketizer = LiteEthICMPDepacketizer()
self.submodules += depacketizer
self.comb += Record.connect(self.sink, depacketizer.sink)
sink = depacketizer.source
self.submodules.fsm = fsm = FSM(reset_state="IDLE")
fsm.act("IDLE",
sink.ack.eq(1),
If(sink.stb & sink.sop,
sink.ack.eq(0),
NextState("CHECK")
)
)
valid = Signal()
self.comb += valid.eq(
sink.stb &
(self.sink.protocol == icmp_protocol) &
(self.sink.ip_address == ip_address)
)
fsm.act("CHECK",
If(valid,
NextState("PRESENT")
).Else(
NextState("DROP")
)
)
self.comb += [
source.sop.eq(sink.sop),
source.eop.eq(sink.eop),
source.msgtype.eq(sink.msgtype),
source.code.eq(sink.code),
source.checksum.eq(sink.checksum),
source.quench.eq(sink.quench),
source.ip_address.eq(self.sink.ip_address),
source.length.eq(self.sink.length - icmp_header_len),
source.data.eq(sink.data),
source.error.eq(sink.error)
]
fsm.act("PRESENT",
source.stb.eq(sink.stb),
sink.ack.eq(source.ack),
If(source.stb & source.eop & source.ack,
NextState("IDLE")
)
)
fsm.act("DROP",
sink.ack.eq(1),
If(source.stb & source.eop & source.ack,
NextState("IDLE")
)
)
class LiteEthICMPEcho(Module):
def __init__(self):
self.sink = Sink(eth_icmp_user_description(8))
self.source = Source(eth_icmp_user_description(8))
###
self.comb += [
Record.connect(self.sink, self.source),
self.source.msgtype.eq(0x0),
self.source.checksum.eq(~((~self.sink.checksum)-0x0800))
]
class LiteEthICMP(Module):
def __init__(self, ip, ip_address):
self.submodules.tx = LiteEthICMPTX(ip_address)
self.submodules.rx = LiteEthICMPRX(ip_address)
ip_port = ip.crossbar.get_port(icmp_protocol)
self.comb += [
Record.connect(self.tx.source, ip_port.sink),
Record.connect(ip_port.source, self.rx.sink)
]