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 #include #include +#include #include /** @file @@ -122,6 +123,34 @@ struct net_device * tcpip_netdev ( struct sockaddr_tcpip *st_dest ) { return NULL; } +/** + * 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 *