Neighbor subsystem of linux protocol stack (related process 4)

  

int neigh_resolve_output(struct sk_buff *skb){struct dst_entry *dst = skb->dst;struct neighbour *neigh;int rc = 0;//validity Judge if (!dst | |  (neigh = dst->neighbour))goto discard;__skb_pull(skb, skb->nh.raw - skb->data);//determine whether the neighbor item is available, if available, then packet Send out if (!neigh_event_send(neigh, skb)) {int err;struct net_device *dev = neigh->dev;if (dev->hard_header_cache && !dst->hh) {write_lock_bh(& Neigh->lock);if (!dst->hh)neigh_hh_init(neigh, dst, dst->ops->protocol);err = dev->hard_header(skb, dev, ntohs(skb-> ;protocol),neigh->ha, NULL, skb->len);write_unlock_bh(&neigh->lock);} else {read_lock_bh(&neigh->lock);err = dev-> Hard_header(skb, dev, ntohs(skb->protocol),neigh->ha, NULL, skb->len);read_unlock_bh(&neigh->lock);}if (err >= 0) Rc = neigh->ops->queue_xmit(skb);elsegoto out_kfree_skb;}out:return rc;discard:NEIGH_PRINTK1("neigh_resolve_output: dst=%p neigh=%p\ ",dst, dst ? dst- >neighbour : NULL);out_kfree_skb:rc = -EINVAL;kfree_skb(skb);goto out;}turn to neigh_event_send();stat Ic inline int neigh_event_send(struct neighbour *neigh, struct sk_buff *skb){neigh->used = jiffies;//The NUD_STALE state is removed here because, when there is a message in this state, it will be delayed. State, and set the timer, which can be seen in __neigh_event_send() if (!(neigh->nud_state&(NUD_CONNECTED| NUD_DELAY| NUD_PROBE)))return __neigh_event_send(neigh, skb);return 0;} We assume that the corresponding neighbor is a new item, the initial conditions are not met, and go to __neigh_event_send()int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb) {int rc;unsigned long now;write_lock_bh(&neigh->lock);rc = 0;//entry parameter detection if (neigh->nud_state & (NUD_CONNECTED |  NUD_DELAY |  NUD_PROBE)) goto out_unlock_bh;now = jiffies;//if the status is not NUD_STALE and NUD_INCOMPLETEif (!(neigh->nud_state & (NUD_STALE |  NUD_INCOMPLETE))) {if (neigh->parms->mcast_probes + neigh->parms->app_probes) {//Set the state to NUD_INCOMPLETE and set the timer atomic_set(&neigh->probes, neigh ->parms->ucast_probes);neigh->nud_state = NUD_INCOMPLETE;neigh_hold(neigh);neigh->timer.expires = now + 1;add_timer(&neigh->timer);} else {//If the delay parameter is set at the end, set this neighbor to be unavailable neigh->nud_state = NUD_FAILED; write_unlock_bh(&neigh->lock);if (skb)kfree_skb(skb);return 1;}} else if (neigh ->nud_state & NUD_STALE) {//If the status is NUD_STALE, change the status to NUD_DELAY, and set the timer //to return to zero. In neigh_resolve_output, send the packet to NEIGH_PRINTK2 ("neigh %p is delayed.\\ n", neigh);neigh_hold(neigh);neigh->nud_state = NUD_DELAY;neigh->timer.expires = jiffies + neigh->parms->delay_probe_time;add_timer(&neigh->timer); }if (neigh->nud_state == NUD_INCOMPLETE) {//Add the package to neigh, arp_queue, skb tail if (skb) {//If the queue is too long, then The first packet of arp_queue discards if (skb_queue_len(&neigh->arp_queue) >=neigh->parms->queue_len) {struct sk_buff *buff;buff = neigh->arp_queue.next;__skb_unlink( Buff, &neigh->arp_queue);kfree_skb(buff);}//Add the package to the end of the queue __skb_queue_tail(&neigh->arp_queue, skb);}rc = 1;}out_unlock_bh:write_unlock_bh(& ;neigh->lock);return rc;} The above process mainly determines the state of the neighbor item corresponding to dst, and if the status is available, the packet is directly sent. If not available, set the status to NUD_INCOMPLETE and set the timer. The processing function corresponding to the timer is:zh-CN"],null,[0.86750525],zh-CN"]]]

Copyright © Windows knowledge All Rights Reserved