diff --git a/ChangeLog b/ChangeLog index ad1da08cb..0d03c0932 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,25 @@ +2012-06-09 Vladimir Serbinenko + + Stop polling as soon as we have the packet we were waiting for. + + * include/grub/net.h (grub_net_poll_cards): New argument stop_condition. + All users updated. + * grub-core/net/arp.c (have_pending): New var. + (pending_req): Likewise. + (grub_net_arp_send_request): Fill pending_req and use have_pending as + stop indicator. + (grub_net_arp_receive): Set have_pending. + * grub-core/net/dns.c (recv_data): New field stop. + (recv_hook): Set stop. + (grub_net_dns_lookup): Init stop and use as stop condition. + * grub-core/net/http.c (http_establish): Use headers_recv as stop + condition. + * grub-core/net/net.c (grub_net_poll_cards): New argument + stop_condition. Stop when it goes true. + * grub-core/net/tcp.c (grub_net_tcp_open): Use `established' as stop + indicator. + * grub-core/net/tftp.c (tftp_open): Use `have_oack' as stop indicator. + 2012-06-09 Vladimir Serbinenko Keep TX and RX buffers on EFI rather than always allocate new ones. diff --git a/grub-core/net/arp.c b/grub-core/net/arp.c index 3db852e74..a34aecd0a 100644 --- a/grub-core/net/arp.c +++ b/grub-core/net/arp.c @@ -45,6 +45,8 @@ struct arphdr { grub_uint16_t op; } __attribute__ ((packed)); +static int have_pending; +static grub_uint32_t pending_req; grub_err_t grub_net_arp_send_request (struct grub_net_network_level_interface *inf, @@ -106,7 +108,9 @@ grub_net_arp_send_request (struct grub_net_network_level_interface *inf, { if (grub_net_link_layer_resolve_check (inf, proto_addr)) return GRUB_ERR_NONE; - grub_net_poll_cards (GRUB_NET_INTERVAL); + pending_req = proto_addr->ipv4; + have_pending = 0; + grub_net_poll_cards (GRUB_NET_INTERVAL, &have_pending); if (grub_net_link_layer_resolve_check (inf, proto_addr)) return GRUB_ERR_NONE; nb.data = nbd; @@ -140,6 +144,8 @@ grub_net_arp_receive (struct grub_net_buff *nb, target_addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; grub_memcpy (&sender_addr.ipv4, sender_protocol_address, 4); grub_memcpy (&target_addr.ipv4, target_protocol_address, 4); + if (grub_memcmp (sender_protocol_address, &pending_req, 4) == 0) + have_pending = 1; } else return GRUB_ERR_NONE; diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c index d11fdb20d..a303bb19c 100644 --- a/grub-core/net/bootp.c +++ b/grub-core/net/bootp.c @@ -541,7 +541,7 @@ grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)), } if (!done) break; - grub_net_poll_cards (interval); + grub_net_poll_cards (interval, 0); } err = GRUB_ERR_NONE; diff --git a/grub-core/net/dns.c b/grub-core/net/dns.c index ee3029e0b..acf855771 100644 --- a/grub-core/net/dns.c +++ b/grub-core/net/dns.c @@ -108,6 +108,7 @@ struct recv_data int dns_err; char *name; const char *oname; + int stop; }; static inline int @@ -339,6 +340,7 @@ recv_hook (grub_net_udp_socket_t sock __attribute__ ((unused)), grub_memcpy (&(*data->addresses)[*data->naddresses].ipv4, ptr, 4); (*data->naddresses)++; + data->stop = 1; break; case DNS_CLASS_AAAA: if (length != 16) @@ -348,6 +350,7 @@ recv_hook (grub_net_udp_socket_t sock __attribute__ ((unused)), grub_memcpy (&(*data->addresses)[*data->naddresses].ipv6, ptr, 16); (*data->naddresses)++; + data->stop = 1; break; case DNS_CLASS_CNAME: if (!(redirect_cnt & (redirect_cnt - 1))) @@ -425,7 +428,7 @@ grub_net_dns_lookup (const char *name, static grub_uint16_t id = 1; grub_err_t err = GRUB_ERR_NONE; struct recv_data data = {naddresses, addresses, cache, - grub_cpu_to_be16 (id++), 0, 0, name}; + grub_cpu_to_be16 (id++), 0, 0, name, 0}; grub_uint8_t *nbd; int have_server = 0; @@ -573,7 +576,7 @@ grub_net_dns_lookup (const char *name, if (*data.naddresses) goto out; } - grub_net_poll_cards (200); + grub_net_poll_cards (200, &data.stop); } out: grub_free (data.name); diff --git a/grub-core/net/http.c b/grub-core/net/http.c index 48b2ccf34..be9dafacd 100644 --- a/grub-core/net/http.c +++ b/grub-core/net/http.c @@ -390,7 +390,7 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial) for (i = 0; !data->headers_recv && i < 100; i++) { grub_net_tcp_retransmit (); - grub_net_poll_cards (300); + grub_net_poll_cards (300, &data->headers_recv); } if (!data->headers_recv) diff --git a/grub-core/net/icmp6.c b/grub-core/net/icmp6.c index 9a5f3cafe..4fc343d72 100644 --- a/grub-core/net/icmp6.c +++ b/grub-core/net/icmp6.c @@ -513,7 +513,7 @@ grub_net_icmp6_send_request (struct grub_net_network_level_interface *inf, { if (grub_net_link_layer_resolve_check (inf, proto_addr)) break; - grub_net_poll_cards (GRUB_NET_INTERVAL); + grub_net_poll_cards (GRUB_NET_INTERVAL, 0); if (grub_net_link_layer_resolve_check (inf, proto_addr)) break; nb->data = nbd; diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 7e3ad7795..9f1afd1e7 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -339,7 +339,7 @@ grub_cmd_ipv6_autoconf (struct grub_command *cmd __attribute__ ((unused)), } if (done) break; - grub_net_poll_cards (interval); + grub_net_poll_cards (interval, 0); } err = GRUB_ERR_NONE; @@ -1336,16 +1336,15 @@ receive_packets (struct grub_net_card *card) } void -grub_net_poll_cards (unsigned time) +grub_net_poll_cards (unsigned time, int *stop_condition) { struct grub_net_card *card; grub_uint64_t start_time; - FOR_NET_CARDS (card) - { - start_time = grub_get_time_ms (); - while ((grub_get_time_ms () - start_time) < time) - receive_packets (card); - } + start_time = grub_get_time_ms (); + while ((grub_get_time_ms () - start_time) < time + && (!stop_condition || !*stop_condition)) + FOR_NET_CARDS (card) + receive_packets (card); grub_net_tcp_retransmit (); } @@ -1405,7 +1404,7 @@ grub_net_fs_read_real (grub_file_t file, char *buf, grub_size_t len) if (!net->eof) { try++; - grub_net_poll_cards (GRUB_NET_INTERVAL); + grub_net_poll_cards (GRUB_NET_INTERVAL, &net->eof); } else return total; diff --git a/grub-core/net/tcp.c b/grub-core/net/tcp.c index ae86d2b86..57fdba979 100644 --- a/grub-core/net/tcp.c +++ b/grub-core/net/tcp.c @@ -649,7 +649,7 @@ grub_net_tcp_open (char *server, } for (j = 0; (j < TCP_SYN_RETRANSMISSION_TIMEOUT / 50 && !socket->established); j++) - grub_net_poll_cards (50); + grub_net_poll_cards (50, &socket->established); if (socket->established) break; } diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c index 7cc89390d..abd5395d6 100644 --- a/grub-core/net/tftp.c +++ b/grub-core/net/tftp.c @@ -376,7 +376,7 @@ tftp_open (struct grub_file *file, const char *filename) destroy_pq (data); return err; } - grub_net_poll_cards (GRUB_NET_INTERVAL); + grub_net_poll_cards (GRUB_NET_INTERVAL, &data->have_oack); if (data->have_oack) break; } diff --git a/include/grub/net.h b/include/grub/net.h index bd6d87ae9..d854ed2de 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -458,7 +458,7 @@ void grub_net_hwaddr_to_str (const grub_net_link_level_address_t *addr, char *str); void -grub_net_poll_cards (unsigned time); +grub_net_poll_cards (unsigned time, int *stop_condition); void grub_bootp_init (void); void grub_bootp_fini (void);