Namespace changed:
------------------

Let us consider

  fec     : Forward Equivalence Class
  ftn     : FEC-to-NHLFE Map
  ilm     : incoming label map
  nh      : next-hop or gateway address
  nhlfe   : Next Hop Label Forwarding Entry
  op      : MPLS operation
  rd      : MPLS Route Distinguisher or reserved label value
  segment : denotes particular Label Switch Path (LSP)
  seg_in  : defines in-segment, incoming label
  seg_out : defines out-segment, outgoing label
  x       : destination, key in fec

 then

  fec = < x, nh >
  gw = < nh, seg_out, rd, op >
  ftn = < x, gw >
  nhlfe = < seg_in, ftn >
  ilm = < seg_in, gw >

finally former struct mpls_ftn{} changed in

    struct mpls_xc {
        struct rtentry    *xc_ilm;        /* ilm */
        struct llentry    *xc_lle;        /* shortcut */
        struct ifaddr    *xc_ifa;        /* nhlfe */
        int    xc_flags;
        struct sockaddr_ftn    xc_gw;    /* storage, destination */

        struct sockaddr_mpls    xc_iseg;    /* storage, seg_in */
        struct sockaddr_mpls    xc_oseg;    /* stoage, seg_out */

        struct sockaddr    *xc_fec;    /* key x in fec */
        struct sockaddr    *xc_nh;       /* nh */
        struct sockaddr    *xc_dst;    /* gateway */
        struct rtentry    *xc_rt;    /* fec */
        struct ifnet    *xc_ifp;    /* interface, tx */
    };
    #define rotoxc(ro)        ((struct mpls_xc)(ro))
    #define xctoro(xc)        ((struct route)(xc))

because it was wrong terminology and fibnum moved
from mpls_nhlfe{} to

    struct sockaddr_ftn {
        uint8_t    sftn_len;
        sa_family_t sftn_family;    /* address family, gateway address (nh) */
        uint16_t    sftn_pad0[13];    /* stores nh */
        uint32_t     sftn_label;    /* stores seg_out */
        uint32_t     sftn_vprd;    /* route distinguisher */
        uint32_t     sftn_op;    /* MPLS operation */
        uint32_t     sftn_fib;    /* forwarding information base */
    };
    #define satosftn(sa)        ((struct sockaddr_ftn *)(sa))
    #define sftntosa(sftn)    ((struct sockaddr *)(sftn))

Misc. bugfixes and major cleanup:
---------------------------------

Several fixes in route(8), ifconfig(8) relying MPLS extensions.

Handling of gateway in rt_addrinfo{} by route(8) and netmpls/mpls_rmx.c
changed. Segements for x-connect are encoded by sockaddr_mpls{} maps to
sockaddr_ftn{}, where in-seg is stored by

 (a) satosmpls(gateway)->smpls_label = ...

and out-seg by

 (b) satosftn(gateway)->sftn_label = ...

Misc. bugfixes in netmpls/mpls_arp.c, optimized shortcut:

    static __inline void
    mpls_rtalloc_fib(struct mpls_ftnftn, u_int fibnum)
    {

        rtalloc_fib((struct route)ftn, fibnum);
        if (ftn->ftn_ilm != NULL) {
            ftn->ftn_lle = ftn->ftn_lle = /* XXX: <= maps llentry{} */
                NHLFE_SHORTCUT(ftn->ftn_ilm->rt_ifa);
            ftn->ftn_ifa = ftn->ftn_ilm->rt_ifa;
            ftn->ftn_flags = ftn->ftn_ilm->rt_flags;
        }
    }

on LSR llentry{} maps to route{} avoids call of mpls_arpresolve
during i.e. ether_output, if tx host rx ARP_INVREPLY succesfully.

OID

 net.link.ether.mpls.proxy_arp= [01]

introduced. Let us assume:

 1. Alice performs x-connect such that corrosponding
     llentry{} is allocated by mpls_arp_ifinit().
 2. By mpls_output tx Protocol Data Unit (PDU) will
    be cached by mpls_arpresolve() selected llentry{}
    and mpls_arprequest() tx PDU containing ARPOP_INVREQUEST
    Service Primitive (SPI).
 3. Bob rx ARPOP_INVREQUEST by mpls_arpinput().
 4. If Bob is label peer, then Bob replies by
    tx ARPOP_INVREPLY containing linklayer
    address (lla) maps to for tx used network
    interface.
 5. Alice rx ARPOP_INVREPLY, maps lla to corrosponding
    llentry{} and tx by 2. cached PDU.

If proxy_arp OID remains in enabled state (default setup),
Bob tx during 4. an ARPOP_INVREQUEST downstream before tx
ARPOP_INVREPLY against Alice takes place.

  +------+       < seg_i >                    < seg_j >
  |       \
  | Alice  +---[req, bcast]--->+------+
  |       /                    |       \
  +------+                     | Bob    +---[req, bcast]--->
          \                    |       /
           +<--[repl, ucast]---+------+
                                       \
                                        +<---[repl, ucast]--

 (upstream)                                       (downstream)

This cascade causes by mpls_output tx PDU is cached only by
LSR_in during mpls_arpresolve() and not by any intermediary
LSR until LSR_out in LSP.
    Maybe, proxy_arp could be used as a starting point for an
implementation for a traceroute mechanism or for a MPLS_ARP
piggybacked label distribution engine.