From 22127a2ceab6d3ad12ecea67176f7a7a3b26f567 Mon Sep 17 00:00:00 2001 From: Pawel Dziepak Date: Fri, 10 Jul 2009 00:41:46 +0200 Subject: [PATCH] net: data reception system, fixed bugs in rtl8139 TODO: - overload of rtl8139 receive buffer - arp_table lose entries --- libs/buffer.h | 7 +++++++ manes/start.cpp | 8 +++++--- resources/net/arp.cpp | 2 +- resources/net/arp_table.cpp | 6 ++++-- resources/net/icmp.cpp | 31 +++++++++++++++++++++++++++++++ resources/net/icmp.h | 7 +++++++ resources/net/internet_layer.h | 9 +++++++++ resources/net/ipv4.cpp | 11 ++++++++++- resources/net/ipv4.h | 4 +++- resources/net/udp.cpp | 20 ++++++++++++++++++++ resources/net/udp.h | 13 +++++++++++-- resources/rtl8139.cpp | 8 ++++---- resources/rtl8139.h | 1 + 13 files changed, 113 insertions(+), 14 deletions(-) diff --git a/libs/buffer.h b/libs/buffer.h index 840f3dc..7f8f12d 100644 --- a/libs/buffer.h +++ b/libs/buffer.h @@ -88,6 +88,13 @@ public: return address; } + buffer cut_first(unsigned int cut_size) const { + if (cut_size >= size) + throw cut_size; + + return buffer(address + cut_size, size - cut_size); + } + template static buffer to_mem(p addr) { return buffer((void*)addr, sizeof(T)); diff --git a/manes/start.cpp b/manes/start.cpp index f2f563b..30f1352 100644 --- a/manes/start.cpp +++ b/manes/start.cpp @@ -182,11 +182,13 @@ extern "C" void _start() { icmp ping; ping.set_internet_layer(&ip); - ping.ping(ipv4_addr::from_le(192 << 24 | 168 << 16 | 1 << 8 | 1)); + ping.ping(ipv4_addr::from_le(192 << 24 | 168 << 16 | 1 << 8 | 2)); - ping.ping(ipv4_addr::from_le(192 << 24 | 168 << 16 | 1 << 8 | 3)); + ping.ping(ipv4_addr::from_le(192 << 24 | 168 << 16 | 1 << 8 | 2)); + + while (true) asm("hlt"); } - while (true) asm("cli\nhlt"); + p floppy = main->get("/fdc"); p fs_floppy = main->get("/fat"); diff --git a/resources/net/arp.cpp b/resources/net/arp.cpp index 70f5fc2..334a63d 100644 --- a/resources/net/arp.cpp +++ b/resources/net/arp.cpp @@ -4,7 +4,7 @@ using namespace net; void poll(volatile bool *value) { - while (!*value) asm volatile("hlt"); + while (!*value) asm volatile("nop"); } mac_addr arp::get_haddr(const ipv4_addr &ipaddr) { diff --git a/resources/net/arp_table.cpp b/resources/net/arp_table.cpp index c0afefc..088685c 100644 --- a/resources/net/arp_table.cpp +++ b/resources/net/arp_table.cpp @@ -3,9 +3,11 @@ using namespace net; void arp_table::add(p x) { - for (int i = 0; i < table.get_count(); i++) + for (int i = 0; i < table.get_count();) if (table[i]->paddr == x->paddr) table.remove(i); + else + i++; table.add(x); } @@ -15,5 +17,5 @@ p arp_table::get(const ipv4_addr &x) { if (table[i]->paddr == x) return table[i]; - return 0;//p::invalid; + return p::invalid; } diff --git a/resources/net/icmp.cpp b/resources/net/icmp.cpp index b921622..6489888 100644 --- a/resources/net/icmp.cpp +++ b/resources/net/icmp.cpp @@ -33,3 +33,34 @@ void icmp::ping(const ipv4_addr &addr) { pkg.dispose(); } + +void icmp::receive(const ipv4_addr &addr, const buffer &data) { + p request = data.cast(); + + if (request->type != 8 || request->code != 0) + return; + + p pkg = new icmp_packet; + pkg->type = 0; + pkg->code = 0; + pkg->checksum = 0; + pkg->id = request->id; + pkg->sequence = request->sequence; + + buffer buf = buffer::to_mem(pkg); + buf += data.cut_first(sizeof(icmp_packet)); + + array words = array::from_buffer(buf); + u32 sum = 0; + for (int i = 0; i < 18; i++) + sum += words[i]; + + sum = (sum & 0xffff) + (sum >> 16); + sum += (sum >> 16); + + buf.cast()->checksum = to_le16(~sum); + + down->send_data(addr, ipv4::icmp, buf); + + pkg.dispose(); +} diff --git a/resources/net/icmp.h b/resources/net/icmp.h index b4efde9..5de7d42 100644 --- a/resources/net/icmp.h +++ b/resources/net/icmp.h @@ -14,7 +14,14 @@ namespace net { u16 id; u16 sequence; }; + + void receive(const ipv4_addr&, const buffer&); public: + void set_internet_layer(p x) { + down = x; + down->listen(1, delegate::method(this, &icmp::receive)); + } + void ping(const ipv4_addr &addr); }; } diff --git a/resources/net/internet_layer.h b/resources/net/internet_layer.h index 83b7b5e..878ea4a 100644 --- a/resources/net/internet_layer.h +++ b/resources/net/internet_layer.h @@ -5,18 +5,27 @@ #include "link_layer.h" #include "ipv4_addr.h" +#include "libs/list.h" +#include "libs/delegate.h" namespace net { class internet_layer : public osi_layer { protected: p down; + list protocols; + list > listeners; public: virtual void set_link_layer(p x) { down = x; } virtual void send_data(const ipv4_addr &, int, const buffer &) = 0; + + virtual void listen(int prot, delegate listener) { + protocols.add(prot); + listeners.add(listener); + } }; } diff --git a/resources/net/ipv4.cpp b/resources/net/ipv4.cpp index 27f1025..e718f89 100644 --- a/resources/net/ipv4.cpp +++ b/resources/net/ipv4.cpp @@ -9,7 +9,7 @@ void ipv4::set_link_layer(p x) { arp_prot.set_link_layer(x); down = x; - my_ip = ipv4_addr::from_le(192 << 24 | 168 << 16 | 1 << 8 | 50); + x->add_handler(0x800, delegate::method(this, &ipv4::receive_data)); } void ipv4::send_data(const ipv4_addr &addr, int prot, const buffer &x) { @@ -52,3 +52,12 @@ void ipv4::send_data(const ipv4_addr &addr, int prot, const buffer &x) { pkg.dispose(); } + +void ipv4::receive_data(const buffer &data) { + p pkg = data.cast(); + + for (int i = 0; i < protocols.get_count(); i++) + if (protocols[i] == pkg->prot) + listeners[i](ipv4_addr::from_be(pkg->src), data.cut_first(sizeof(ipv4_packet))); + +} diff --git a/resources/net/ipv4.h b/resources/net/ipv4.h index 1386e48..d267773 100644 --- a/resources/net/ipv4.h +++ b/resources/net/ipv4.h @@ -37,6 +37,8 @@ namespace net { udp = 17 }; + void set_link_layer(p x); + void configure_ipv4(const ipv4_addr &ip, const ipv4_addr &netmask, const ipv4_addr &gate) { my_ip = ip; mask = netmask; @@ -47,8 +49,8 @@ namespace net { return my_ip; } - void set_link_layer(p x); void send_data(const ipv4_addr &addr, int prot, const buffer &x); + void receive_data(const buffer&); }; } diff --git a/resources/net/udp.cpp b/resources/net/udp.cpp index 5bae27c..22cdb70 100644 --- a/resources/net/udp.cpp +++ b/resources/net/udp.cpp @@ -50,3 +50,23 @@ void udp::send(ipv4_addr addr, u16 dst_port, u16 src_port, const buffer &data) { // pkg.dispose(); } +void udp::receive(const ipv4_addr &sender, const buffer &data) { + p pkg = data.cast(); + + for (int i = 0; i < ports.get_count(); i++) + if (ports[i] == from_be16(pkg->receiver_port)) + listeners[i](sender, from_be16(pkg->sender_port), data.cut_first(sizeof(udp_packet))); +} + +void udp::listen(u16 port, delegate listener) { + for (int i = 0; i < ports.get_count();) { + if (ports[i] == port) { + ports.remove(i); + listeners.remove(i); + } else + i++; + } + + ports.add(port); + listeners.add(listener); +} diff --git a/resources/net/udp.h b/resources/net/udp.h index b41e066..dd89f20 100644 --- a/resources/net/udp.h +++ b/resources/net/udp.h @@ -2,6 +2,7 @@ #define _UDP_H_ #include "transport_layer.h" +#include "ipv4_addr.h" namespace net { class udp : public transport_layer { @@ -21,10 +22,18 @@ namespace net { u16 checksum; } __attribute__((packed)); - void receive(const buffer&); + list ports; + list > listeners; + + void receive(const ipv4_addr &, const buffer&); public: + void set_internet_layer(p x) { + down = x; + // down->listen(17, delegate::method(this, &udp::receive)); + } + void send(ipv4_addr, u16, u16, const buffer &); - void listen(u16, delegate); + void listen(u16, delegate); }; } diff --git a/resources/rtl8139.cpp b/resources/rtl8139.cpp index 6d6aaf7..77ef21e 100644 --- a/resources/rtl8139.cpp +++ b/resources/rtl8139.cpp @@ -127,19 +127,19 @@ void rtl8139::send_packet(const buffer &x) { /* Set TSD */ id.outl(tsd0 + send_index * 4, x.get_size()); - send_index++; + send_index = (send_index + 1) % 4; } - void rtl8139::receive_packet() { wait_loop(); - packet *pkg = (packet*)((u32)rec_buffer + id.inl(capr)); + packet *pkg = (packet*)((u32)rec_buffer + received_index); u32 size = pkg->size; u8* buf = new u8[size + 4]; memcpy(buf, pkg, size + 4); + received_index += size + 4; pkg = (packet*)buf; - id.outl(capr, pkg->size); + id.outl(capr, received_index); id.outw(isr,0xffff); id.inw(isr); diff --git a/resources/rtl8139.h b/resources/rtl8139.h index 6e4ffdd..5180287 100644 --- a/resources/rtl8139.h +++ b/resources/rtl8139.h @@ -55,6 +55,7 @@ namespace resources { pci_did id; int send_index; + int received_index; volatile char *rec_buffer; -- 2.11.4.GIT