aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/include/ipxe/tcpip.h3
-rw-r--r--src/net/ipv4.c1
-rw-r--r--src/net/ipv6.c1
-rw-r--r--src/net/tcpip.c29
4 files changed, 34 insertions, 0 deletions
diff --git a/src/include/ipxe/tcpip.h b/src/include/ipxe/tcpip.h
index d28689a1..200630d6 100644
--- a/src/include/ipxe/tcpip.h
+++ b/src/include/ipxe/tcpip.h
@@ -97,6 +97,8 @@ struct tcpip_net_protocol {
const char *name;
/** Network address family */
sa_family_t sa_family;
+ /** Fixed header length */
+ size_t header_len;
/**
* Transmit packet
*
@@ -148,6 +150,7 @@ extern int tcpip_tx ( struct io_buffer *iobuf, struct tcpip_protocol *tcpip,
struct net_device *netdev,
uint16_t *trans_csum );
extern struct net_device * tcpip_netdev ( struct sockaddr_tcpip *st_dest );
+extern size_t tcpip_mtu ( struct sockaddr_tcpip *st_dest );
extern uint16_t generic_tcpip_continue_chksum ( uint16_t partial,
const void *data, size_t len );
extern uint16_t tcpip_chksum ( const void *data, size_t len );
diff --git a/src/net/ipv4.c b/src/net/ipv4.c
index 8bda5c86..c5cfd134 100644
--- a/src/net/ipv4.c
+++ b/src/net/ipv4.c
@@ -621,6 +621,7 @@ struct net_protocol ipv4_protocol __net_protocol = {
struct tcpip_net_protocol ipv4_tcpip_protocol __tcpip_net_protocol = {
.name = "IPv4",
.sa_family = AF_INET,
+ .header_len = sizeof ( struct iphdr ),
.tx = ipv4_tx,
.netdev = ipv4_netdev,
};
diff --git a/src/net/ipv6.c b/src/net/ipv6.c
index 6f2e9477..f753751d 100644
--- a/src/net/ipv6.c
+++ b/src/net/ipv6.c
@@ -988,6 +988,7 @@ struct net_protocol ipv6_protocol __net_protocol = {
struct tcpip_net_protocol ipv6_tcpip_protocol __tcpip_net_protocol = {
.name = "IPv6",
.sa_family = AF_INET6,
+ .header_len = sizeof ( struct ipv6_header ),
.tx = ipv6_tx,
.netdev = ipv6_netdev,
};
diff --git a/src/net/tcpip.c b/src/net/tcpip.c
index 6fac8c52..4bcbe64b 100644
--- a/src/net/tcpip.c
+++ b/src/net/tcpip.c
@@ -6,6 +6,7 @@
#include <ipxe/iobuf.h>
#include <ipxe/tables.h>
#include <ipxe/ipstat.h>
+#include <ipxe/netdevice.h>
#include <ipxe/tcpip.h>
/** @file
@@ -123,6 +124,34 @@ struct net_device * tcpip_netdev ( struct sockaddr_tcpip *st_dest ) {
}
/**
+ * Determine maximum transmission unit
+ *
+ * @v st_dest Destination address
+ * @ret mtu Maximum transmission unit
+ */
+size_t tcpip_mtu ( struct sockaddr_tcpip *st_dest ) {
+ struct tcpip_net_protocol *tcpip_net;
+ struct net_device *netdev;
+ size_t mtu;
+
+ /* Find appropriate network-layer protocol */
+ tcpip_net = tcpip_net_protocol ( st_dest );
+ if ( ! tcpip_net )
+ return 0;
+
+ /* Find transmitting network device */
+ netdev = tcpip_net->netdev ( st_dest );
+ if ( ! netdev )
+ return 0;
+
+ /* Calculate MTU */
+ mtu = ( netdev->max_pkt_len - netdev->ll_protocol->ll_header_len -
+ tcpip_net->header_len );
+
+ return mtu;
+}
+
+/**
* Calculate continued TCP/IP checkum
*
* @v partial Checksum of already-summed data, in network byte order