Lines 195-200
Link Here
|
195 |
static void ng_fec_tick(void *arg); |
195 |
static void ng_fec_tick(void *arg); |
196 |
static int ng_fec_addport(struct ng_fec_private *priv, char *iface); |
196 |
static int ng_fec_addport(struct ng_fec_private *priv, char *iface); |
197 |
static int ng_fec_delport(struct ng_fec_private *priv, char *iface); |
197 |
static int ng_fec_delport(struct ng_fec_private *priv, char *iface); |
|
|
198 |
static void ng_fec_update_opts(struct ng_fec_bundle *b, |
199 |
struct ifnet *ifp); |
198 |
|
200 |
|
199 |
#ifdef DEBUG |
201 |
#ifdef DEBUG |
200 |
static void ng_fec_print_ioctl(struct ifnet *ifp, int cmd, caddr_t data); |
202 |
static void ng_fec_print_ioctl(struct ifnet *ifp, int cmd, caddr_t data); |
Lines 439-447
Link Here
|
439 |
new->fec_ifstat = -1; |
441 |
new->fec_ifstat = -1; |
440 |
TAILQ_INSERT_TAIL(&b->ng_fec_ports, new, fec_list); |
442 |
TAILQ_INSERT_TAIL(&b->ng_fec_ports, new, fec_list); |
441 |
|
443 |
|
|
|
444 |
ng_fec_update_opts(b, ifp); |
445 |
|
442 |
return(0); |
446 |
return(0); |
443 |
} |
447 |
} |
444 |
|
448 |
|
|
|
449 |
/* Update interfaces capabilities in bundle */ |
450 |
static void |
451 |
ng_fec_update_opts(struct ng_fec_bundle *b, struct ifnet *ifp) |
452 |
{ |
453 |
struct ng_fec_portlist *p; |
454 |
int with_hwtag = 0, with_mtu = 0; |
455 |
/* See if the interface is already in the bundle */ |
456 |
TAILQ_FOREACH(p, &b->ng_fec_ports, fec_list) { |
457 |
struct ifnet *bifp = p->fec_if; |
458 |
if(bifp->if_capenable & IFCAP_VLAN_MTU) |
459 |
with_mtu++; |
460 |
if(bifp->if_capenable & IFCAP_VLAN_HWTAGGING) |
461 |
with_hwtag++; |
462 |
} |
463 |
if(b->fec_ifcnt == 0) |
464 |
return; |
465 |
|
466 |
if(b->fec_ifcnt > with_hwtag) |
467 |
ifp->if_capenable &= ~IFCAP_VLAN_HWTAGGING; |
468 |
else |
469 |
ifp->if_capenable |= IFCAP_VLAN_HWTAGGING; |
470 |
|
471 |
if(b->fec_ifcnt > with_mtu) |
472 |
ifp->if_capenable &= ~IFCAP_VLAN_MTU; |
473 |
else |
474 |
ifp->if_capenable |= IFCAP_VLAN_MTU; |
475 |
|
476 |
return; |
477 |
} |
478 |
|
445 |
static int |
479 |
static int |
446 |
ng_fec_delport(struct ng_fec_private *priv, char *iface) |
480 |
ng_fec_delport(struct ng_fec_private *priv, char *iface) |
447 |
{ |
481 |
{ |
Lines 504-509
Link Here
|
504 |
if (b->fec_ifcnt == 0) |
538 |
if (b->fec_ifcnt == 0) |
505 |
b->fec_if_output = NULL; |
539 |
b->fec_if_output = NULL; |
506 |
|
540 |
|
|
|
541 |
ng_fec_update_opts(b, ifp); |
542 |
|
507 |
return(0); |
543 |
return(0); |
508 |
} |
544 |
} |
509 |
|
545 |
|
Lines 678-684
Link Here
|
678 |
ng_fec_ioctl(struct ifnet *ifp, u_long command, caddr_t data) |
714 |
ng_fec_ioctl(struct ifnet *ifp, u_long command, caddr_t data) |
679 |
{ |
715 |
{ |
680 |
struct ifreq *const ifr = (struct ifreq *) data; |
716 |
struct ifreq *const ifr = (struct ifreq *) data; |
681 |
int s, error = 0; |
717 |
int error = 0; |
|
|
718 |
int ifcap; |
682 |
struct ng_fec_private *priv; |
719 |
struct ng_fec_private *priv; |
683 |
struct ng_fec_bundle *b; |
720 |
struct ng_fec_bundle *b; |
684 |
|
721 |
|
Lines 688-694
Link Here
|
688 |
#ifdef DEBUG |
725 |
#ifdef DEBUG |
689 |
ng_fec_print_ioctl(ifp, command, data); |
726 |
ng_fec_print_ioctl(ifp, command, data); |
690 |
#endif |
727 |
#endif |
691 |
s = splimp(); |
728 |
mtx_lock(&ng_fec_mtx); |
692 |
switch (command) { |
729 |
switch (command) { |
693 |
|
730 |
|
694 |
/* These two are mostly handled at a higher layer */ |
731 |
/* These two are mostly handled at a higher layer */ |
Lines 745-756
Link Here
|
745 |
case SIOCSIFPHYS: |
782 |
case SIOCSIFPHYS: |
746 |
error = EOPNOTSUPP; |
783 |
error = EOPNOTSUPP; |
747 |
break; |
784 |
break; |
748 |
|
785 |
case SIOCSIFCAP: |
|
|
786 |
ifcap = ifp->if_capenable; |
787 |
ng_fec_update_opts(b, ifp); |
788 |
if(ifcap != ifp->if_capenable) |
789 |
ng_fec_init(priv); |
790 |
break; |
749 |
default: |
791 |
default: |
750 |
error = EINVAL; |
792 |
error = EINVAL; |
751 |
break; |
793 |
break; |
752 |
} |
794 |
} |
753 |
(void) splx(s); |
795 |
mtx_unlock(&ng_fec_mtx); |
754 |
return (error); |
796 |
return (error); |
755 |
} |
797 |
} |
756 |
|
798 |
|
Lines 840-879
Link Here
|
840 |
} |
882 |
} |
841 |
|
883 |
|
842 |
b = &priv->fec_bundle; |
884 |
b = &priv->fec_bundle; |
843 |
|
|
|
844 |
switch (b->fec_btype) { |
885 |
switch (b->fec_btype) { |
845 |
case FEC_BTYPE_MAC: |
886 |
case FEC_BTYPE_MAC: |
846 |
m->m_flags |= M_FEC_MAC; |
|
|
847 |
break; |
848 |
#ifdef INET |
887 |
#ifdef INET |
849 |
case FEC_BTYPE_INET: |
888 |
case FEC_BTYPE_INET: |
850 |
/* |
|
|
851 |
* We can't use the INET address port selection |
852 |
* scheme if this isn't an INET packet. |
853 |
*/ |
854 |
if (dst->sa_family == AF_INET) |
855 |
m->m_flags |= M_FEC_INET; |
856 |
#ifdef INET6 |
889 |
#ifdef INET6 |
857 |
else if (dst->sa_family == AF_INET6) |
890 |
case FEC_BTYPE_INET6: |
858 |
m->m_flags |= M_FEC_INET6; |
|
|
859 |
#endif |
891 |
#endif |
860 |
else { |
|
|
861 |
#ifdef DEBUG |
862 |
if_printf(ifp, "can't do inet aggregation of non " |
863 |
"inet packet\n"); |
864 |
#endif |
892 |
#endif |
865 |
m->m_flags |= M_FEC_MAC; |
|
|
866 |
} |
867 |
break; |
893 |
break; |
868 |
#endif |
|
|
869 |
default: |
894 |
default: |
870 |
if_printf(ifp, "bogus hash type: %d\n", |
895 |
if_printf(ifp, "bogus hash type: %d\n", b->fec_btype); |
871 |
b->fec_btype); |
|
|
872 |
m_freem(m); |
896 |
m_freem(m); |
873 |
return(EINVAL); |
897 |
return(EINVAL); |
874 |
break; |
898 |
break; |
875 |
} |
899 |
} |
876 |
|
|
|
877 |
/* |
900 |
/* |
878 |
* Pass the frame to the output vector for all the protocol |
901 |
* Pass the frame to the output vector for all the protocol |
879 |
* handling. This will put the ethernet header on the packet |
902 |
* handling. This will put the ethernet header on the packet |
Lines 898-904
Link Here
|
898 |
struct mbuf *m, struct ifnet **ifp) |
921 |
struct mbuf *m, struct ifnet **ifp) |
899 |
{ |
922 |
{ |
900 |
struct ether_header *eh; |
923 |
struct ether_header *eh; |
901 |
struct mbuf *m0; |
|
|
902 |
#ifdef INET |
924 |
#ifdef INET |
903 |
struct ip *ip; |
925 |
struct ip *ip; |
904 |
#ifdef INET6 |
926 |
#ifdef INET6 |
Lines 907-913
Link Here
|
907 |
#endif |
929 |
#endif |
908 |
|
930 |
|
909 |
struct ng_fec_portlist *p; |
931 |
struct ng_fec_portlist *p; |
910 |
int port = 0, mask; |
932 |
int port = -1, mask; |
911 |
|
933 |
|
912 |
/* |
934 |
/* |
913 |
* If there are only two ports, mask off all but the |
935 |
* If there are only two ports, mask off all but the |
Lines 925-967
Link Here
|
925 |
#endif |
947 |
#endif |
926 |
#endif |
948 |
#endif |
927 |
|
949 |
|
928 |
/* |
|
|
929 |
* The fg_fec_output() routine is supposed to leave a |
930 |
* flag for us in the mbuf that tells us what hash to |
931 |
* use, but sometimes a new mbuf is prepended to the |
932 |
* chain, so we have to search every mbuf in the chain |
933 |
* to find the flags. |
934 |
*/ |
935 |
m0 = m; |
936 |
while (m0) { |
937 |
if (m0->m_flags & (M_FEC_MAC|M_FEC_INET|M_FEC_INET6)) |
938 |
break; |
939 |
m0 = m0->m_next; |
940 |
} |
941 |
if (m0 == NULL) |
942 |
return(EINVAL); |
943 |
|
944 |
switch (m0->m_flags & (M_FEC_MAC|M_FEC_INET|M_FEC_INET6)) { |
945 |
case M_FEC_MAC: |
946 |
port = (eh->ether_dhost[5] ^ |
947 |
eh->ether_shost[5]) & mask; |
948 |
break; |
949 |
#ifdef INET |
950 |
#ifdef INET |
950 |
case M_FEC_INET: |
951 |
if(b->fec_btype == FEC_BTYPE_INET) { |
|
|
952 |
if(eh->ether_type == ETHERTYPE_IP) { |
953 |
switch(ip->ip_v) { |
954 |
case 4: |
951 |
port = (ntohl(ip->ip_dst.s_addr) ^ |
955 |
port = (ntohl(ip->ip_dst.s_addr) ^ |
952 |
ntohl(ip->ip_src.s_addr)) & mask; |
956 |
ntohl(ip->ip_src.s_addr)) & mask; |
953 |
break; |
957 |
break; |
954 |
#ifdef INET6 |
958 |
#ifdef INET6 |
955 |
case M_FEC_INET6: |
959 |
case 6: |
956 |
port = (ip6->ip6_dst.s6_addr[15] ^ |
960 |
port = (ip6->ip6_dst.s6_addr[15] ^ |
957 |
ip6->ip6_dst.s6_addr[15]) & mask; |
961 |
ip6->ip6_dst.s6_addr[15]) & mask; |
958 |
break; |
962 |
break; |
959 |
#endif |
963 |
#endif |
960 |
#endif |
|
|
961 |
default: |
964 |
default: |
962 |
return(EINVAL); |
965 |
#ifdef DEBUG |
|
|
966 |
printf("%s: can't do inet aggregation of " |
967 |
"inet packet with unknown ip version\n", |
968 |
__func__); |
969 |
#endif |
963 |
break; |
970 |
break; |
964 |
} |
971 |
} |
|
|
972 |
} else { |
973 |
#ifdef DEBUG |
974 |
printf("%s: can't do inet aggregation of non " |
975 |
"inet packet\n", __func__); |
976 |
#endif |
977 |
} |
978 |
#endif |
979 |
} |
980 |
if(port < 0) |
981 |
port = (eh->ether_dhost[5] ^ |
982 |
eh->ether_shost[5]) & mask; |
965 |
|
983 |
|
966 |
TAILQ_FOREACH(p, &b->ng_fec_ports, fec_list) { |
984 |
TAILQ_FOREACH(p, &b->ng_fec_ports, fec_list) { |
967 |
if (port == p->fec_idx) |
985 |
if (port == p->fec_idx) |
Lines 1134-1139
Link Here
|
1134 |
ifp->if_addrlen = 0; /* XXX */ |
1152 |
ifp->if_addrlen = 0; /* XXX */ |
1135 |
ifp->if_hdrlen = 0; /* XXX */ |
1153 |
ifp->if_hdrlen = 0; /* XXX */ |
1136 |
ifp->if_baudrate = 100000000; /* XXX */ |
1154 |
ifp->if_baudrate = 100000000; /* XXX */ |
|
|
1155 |
ifp->if_capabilities = IFCAP_VLAN_MTU | IFCAP_VLAN_HWTAGGING; |
1137 |
TAILQ_INIT(&ifp->if_addrhead); /* XXX useless - done in if_attach */ |
1156 |
TAILQ_INIT(&ifp->if_addrhead); /* XXX useless - done in if_attach */ |
1138 |
|
1157 |
|
1139 |
/* Give this node the same name as the interface (if possible) */ |
1158 |
/* Give this node the same name as the interface (if possible) */ |
Lines 1253-1259
Link Here
|
1253 |
|
1272 |
|
1254 |
switch (event) { |
1273 |
switch (event) { |
1255 |
case MOD_LOAD: |
1274 |
case MOD_LOAD: |
1256 |
mtx_init(&ng_fec_mtx, "ng_fec", NULL, MTX_DEF); |
1275 |
mtx_init(&ng_fec_mtx, "ng_fec", MTX_NETWORK_LOCK, MTX_DEF); |
1257 |
break; |
1276 |
break; |
1258 |
case MOD_UNLOAD: |
1277 |
case MOD_UNLOAD: |
1259 |
mtx_destroy(&ng_fec_mtx); |
1278 |
mtx_destroy(&ng_fec_mtx); |