| 149 | } |
| 150 | |
| 151 | int |
| 152 | tcp_lro_init_args(struct lro_ctrl *lc, struct ifnet *ifp, |
| 153 | unsigned lro_entries, unsigned lro_mbufs) |
| 154 | { |
| 155 | struct lro_entry *le; |
| 156 | size_t size; |
| 157 | unsigned i, elements; |
| 158 | |
| 159 | lc->lro_bad_csum = 0; |
| 160 | lc->lro_queued = 0; |
| 161 | lc->lro_flushed = 0; |
| 162 | lc->lro_mbuf_count = 0; |
| 163 | lc->lro_mbuf_max = lro_mbufs; |
| 164 | lc->lro_cnt = lro_entries; |
| 165 | lc->lro_ackcnt_lim = TCP_LRO_ACKCNT_MAX; |
| 166 | lc->lro_length_lim = TCP_LRO_LENGTH_MAX; |
| 167 | lc->ifp = ifp; |
| 168 | LIST_INIT(&lc->lro_free); |
| 169 | LIST_INIT(&lc->lro_active); |
| 170 | |
| 171 | /* create hash table to accelerate entry lookup */ |
| 172 | if (lro_entries > lro_mbufs) |
| 173 | elements = lro_entries; |
| 174 | else |
| 175 | elements = lro_mbufs; |
| 176 | lc->lro_hash = phashinit_flags(elements, M_LRO, &lc->lro_hashsz, |
| 177 | HASH_NOWAIT); |
| 178 | if (lc->lro_hash == NULL) { |
| 179 | memset(lc, 0, sizeof(*lc)); |
| 180 | return (ENOMEM); |
| 181 | } |
| 182 | |
| 183 | /* compute size to allocate */ |
| 184 | size = (lro_mbufs * sizeof(struct lro_mbuf_sort)) + |
| 185 | (lro_entries * sizeof(*le)); |
| 186 | lc->lro_mbuf_data = (struct lro_mbuf_sort *) |
| 187 | malloc(size, M_LRO, M_NOWAIT | M_ZERO); |
| 188 | |
| 189 | /* check for out of memory */ |
| 190 | if (lc->lro_mbuf_data == NULL) { |
| 191 | free(lc->lro_hash, M_LRO); |
| 192 | memset(lc, 0, sizeof(*lc)); |
| 193 | return (ENOMEM); |
| 194 | } |
| 195 | /* compute offset for LRO entries */ |
| 196 | le = (struct lro_entry *) |
| 197 | (lc->lro_mbuf_data + lro_mbufs); |
| 198 | |
| 199 | /* setup linked list */ |
| 200 | for (i = 0; i != lro_entries; i++) |
| 201 | LIST_INSERT_HEAD(&lc->lro_free, le + i, next); |
| 202 | |
| 203 | return (0); |
| 204 | } |
| 205 | |
| 206 | static struct tcphdr * |
| 207 | tcp_lro_get_th(struct lro_entry *le, struct mbuf *m) |
no test coverage detected