diff options
| -rw-r--r-- | include/linux/if_link.h | 23 | ||||
| -rw-r--r-- | include/net/tcp.h | 21 | ||||
| -rw-r--r-- | net/core/rtnetlink.c | 159 | ||||
| -rw-r--r-- | net/ipv4/tcp.c | 34 | ||||
| -rw-r--r-- | net/sctp/transport.c | 4 |
5 files changed, 160 insertions, 81 deletions
diff --git a/include/linux/if_link.h b/include/linux/if_link.h index c9bf92cd7653..d94963b379d9 100644 --- a/include/linux/if_link.h +++ b/include/linux/if_link.h | |||
| @@ -79,10 +79,7 @@ enum { | |||
| 79 | IFLA_NET_NS_PID, | 79 | IFLA_NET_NS_PID, |
| 80 | IFLA_IFALIAS, | 80 | IFLA_IFALIAS, |
| 81 | IFLA_NUM_VF, /* Number of VFs if device is SR-IOV PF */ | 81 | IFLA_NUM_VF, /* Number of VFs if device is SR-IOV PF */ |
| 82 | IFLA_VF_MAC, /* Hardware queue specific attributes */ | 82 | IFLA_VFINFO_LIST, |
| 83 | IFLA_VF_VLAN, | ||
| 84 | IFLA_VF_TX_RATE, /* TX Bandwidth Allocation */ | ||
| 85 | IFLA_VFINFO, | ||
| 86 | __IFLA_MAX | 83 | __IFLA_MAX |
| 87 | }; | 84 | }; |
| 88 | 85 | ||
| @@ -203,6 +200,24 @@ enum macvlan_mode { | |||
| 203 | 200 | ||
| 204 | /* SR-IOV virtual function managment section */ | 201 | /* SR-IOV virtual function managment section */ |
| 205 | 202 | ||
| 203 | enum { | ||
| 204 | IFLA_VF_INFO_UNSPEC, | ||
| 205 | IFLA_VF_INFO, | ||
| 206 | __IFLA_VF_INFO_MAX, | ||
| 207 | }; | ||
| 208 | |||
| 209 | #define IFLA_VF_INFO_MAX (__IFLA_VF_INFO_MAX - 1) | ||
| 210 | |||
| 211 | enum { | ||
| 212 | IFLA_VF_UNSPEC, | ||
| 213 | IFLA_VF_MAC, /* Hardware queue specific attributes */ | ||
| 214 | IFLA_VF_VLAN, | ||
| 215 | IFLA_VF_TX_RATE, /* TX Bandwidth Allocation */ | ||
| 216 | __IFLA_VF_MAX, | ||
| 217 | }; | ||
| 218 | |||
| 219 | #define IFLA_VF_MAX (__IFLA_VF_MAX - 1) | ||
| 220 | |||
| 206 | struct ifla_vf_mac { | 221 | struct ifla_vf_mac { |
| 207 | __u32 vf; | 222 | __u32 vf; |
| 208 | __u8 mac[32]; /* MAX_ADDR_LEN */ | 223 | __u8 mac[32]; /* MAX_ADDR_LEN */ |
diff --git a/include/net/tcp.h b/include/net/tcp.h index 75be5a28815d..aa04b9a5093b 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h | |||
| @@ -1197,30 +1197,15 @@ extern int tcp_v4_md5_do_del(struct sock *sk, | |||
| 1197 | extern struct tcp_md5sig_pool * __percpu *tcp_alloc_md5sig_pool(struct sock *); | 1197 | extern struct tcp_md5sig_pool * __percpu *tcp_alloc_md5sig_pool(struct sock *); |
| 1198 | extern void tcp_free_md5sig_pool(void); | 1198 | extern void tcp_free_md5sig_pool(void); |
| 1199 | 1199 | ||
| 1200 | extern struct tcp_md5sig_pool *__tcp_get_md5sig_pool(int cpu); | 1200 | extern struct tcp_md5sig_pool *tcp_get_md5sig_pool(void); |
| 1201 | extern void __tcp_put_md5sig_pool(void); | 1201 | extern void tcp_put_md5sig_pool(void); |
| 1202 | |||
| 1202 | extern int tcp_md5_hash_header(struct tcp_md5sig_pool *, struct tcphdr *); | 1203 | extern int tcp_md5_hash_header(struct tcp_md5sig_pool *, struct tcphdr *); |
| 1203 | extern int tcp_md5_hash_skb_data(struct tcp_md5sig_pool *, struct sk_buff *, | 1204 | extern int tcp_md5_hash_skb_data(struct tcp_md5sig_pool *, struct sk_buff *, |
| 1204 | unsigned header_len); | 1205 | unsigned header_len); |
| 1205 | extern int tcp_md5_hash_key(struct tcp_md5sig_pool *hp, | 1206 | extern int tcp_md5_hash_key(struct tcp_md5sig_pool *hp, |
| 1206 | struct tcp_md5sig_key *key); | 1207 | struct tcp_md5sig_key *key); |
| 1207 | 1208 | ||
| 1208 | static inline | ||
| 1209 | struct tcp_md5sig_pool *tcp_get_md5sig_pool(void) | ||
| 1210 | { | ||
| 1211 | int cpu = get_cpu(); | ||
| 1212 | struct tcp_md5sig_pool *ret = __tcp_get_md5sig_pool(cpu); | ||
| 1213 | if (!ret) | ||
| 1214 | put_cpu(); | ||
| 1215 | return ret; | ||
| 1216 | } | ||
| 1217 | |||
| 1218 | static inline void tcp_put_md5sig_pool(void) | ||
| 1219 | { | ||
| 1220 | __tcp_put_md5sig_pool(); | ||
| 1221 | put_cpu(); | ||
| 1222 | } | ||
| 1223 | |||
| 1224 | /* write queue abstraction */ | 1209 | /* write queue abstraction */ |
| 1225 | static inline void tcp_write_queue_purge(struct sock *sk) | 1210 | static inline void tcp_write_queue_purge(struct sock *sk) |
| 1226 | { | 1211 | { |
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index fe776c9ddeca..31e85d327aa2 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
| @@ -602,12 +602,19 @@ static void copy_rtnl_link_stats(struct rtnl_link_stats *a, | |||
| 602 | a->tx_compressed = b->tx_compressed; | 602 | a->tx_compressed = b->tx_compressed; |
| 603 | }; | 603 | }; |
| 604 | 604 | ||
| 605 | /* All VF info */ | ||
| 605 | static inline int rtnl_vfinfo_size(const struct net_device *dev) | 606 | static inline int rtnl_vfinfo_size(const struct net_device *dev) |
| 606 | { | 607 | { |
| 607 | if (dev->dev.parent && dev_is_pci(dev->dev.parent)) | 608 | if (dev->dev.parent && dev_is_pci(dev->dev.parent)) { |
| 608 | return dev_num_vf(dev->dev.parent) * | 609 | |
| 609 | sizeof(struct ifla_vf_info); | 610 | int num_vfs = dev_num_vf(dev->dev.parent); |
| 610 | else | 611 | size_t size = nlmsg_total_size(sizeof(struct nlattr)); |
| 612 | size += nlmsg_total_size(num_vfs * sizeof(struct nlattr)); | ||
| 613 | size += num_vfs * (sizeof(struct ifla_vf_mac) + | ||
| 614 | sizeof(struct ifla_vf_vlan) + | ||
| 615 | sizeof(struct ifla_vf_tx_rate)); | ||
| 616 | return size; | ||
| 617 | } else | ||
| 611 | return 0; | 618 | return 0; |
| 612 | } | 619 | } |
| 613 | 620 | ||
| @@ -629,7 +636,7 @@ static inline size_t if_nlmsg_size(const struct net_device *dev) | |||
| 629 | + nla_total_size(1) /* IFLA_OPERSTATE */ | 636 | + nla_total_size(1) /* IFLA_OPERSTATE */ |
| 630 | + nla_total_size(1) /* IFLA_LINKMODE */ | 637 | + nla_total_size(1) /* IFLA_LINKMODE */ |
| 631 | + nla_total_size(4) /* IFLA_NUM_VF */ | 638 | + nla_total_size(4) /* IFLA_NUM_VF */ |
| 632 | + nla_total_size(rtnl_vfinfo_size(dev)) /* IFLA_VFINFO */ | 639 | + rtnl_vfinfo_size(dev) /* IFLA_VFINFO_LIST */ |
| 633 | + rtnl_link_get_size(dev); /* IFLA_LINKINFO */ | 640 | + rtnl_link_get_size(dev); /* IFLA_LINKINFO */ |
| 634 | } | 641 | } |
| 635 | 642 | ||
| @@ -700,14 +707,37 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, | |||
| 700 | 707 | ||
| 701 | if (dev->netdev_ops->ndo_get_vf_config && dev->dev.parent) { | 708 | if (dev->netdev_ops->ndo_get_vf_config && dev->dev.parent) { |
| 702 | int i; | 709 | int i; |
| 703 | struct ifla_vf_info ivi; | ||
| 704 | 710 | ||
| 705 | NLA_PUT_U32(skb, IFLA_NUM_VF, dev_num_vf(dev->dev.parent)); | 711 | struct nlattr *vfinfo, *vf; |
| 706 | for (i = 0; i < dev_num_vf(dev->dev.parent); i++) { | 712 | int num_vfs = dev_num_vf(dev->dev.parent); |
| 713 | |||
| 714 | NLA_PUT_U32(skb, IFLA_NUM_VF, num_vfs); | ||
| 715 | vfinfo = nla_nest_start(skb, IFLA_VFINFO_LIST); | ||
| 716 | if (!vfinfo) | ||
| 717 | goto nla_put_failure; | ||
| 718 | for (i = 0; i < num_vfs; i++) { | ||
| 719 | struct ifla_vf_info ivi; | ||
| 720 | struct ifla_vf_mac vf_mac; | ||
| 721 | struct ifla_vf_vlan vf_vlan; | ||
| 722 | struct ifla_vf_tx_rate vf_tx_rate; | ||
| 707 | if (dev->netdev_ops->ndo_get_vf_config(dev, i, &ivi)) | 723 | if (dev->netdev_ops->ndo_get_vf_config(dev, i, &ivi)) |
| 708 | break; | 724 | break; |
| 709 | NLA_PUT(skb, IFLA_VFINFO, sizeof(ivi), &ivi); | 725 | vf_mac.vf = vf_vlan.vf = vf_tx_rate.vf = ivi.vf; |
| 726 | memcpy(vf_mac.mac, ivi.mac, sizeof(ivi.mac)); | ||
| 727 | vf_vlan.vlan = ivi.vlan; | ||
| 728 | vf_vlan.qos = ivi.qos; | ||
| 729 | vf_tx_rate.rate = ivi.tx_rate; | ||
| 730 | vf = nla_nest_start(skb, IFLA_VF_INFO); | ||
| 731 | if (!vf) { | ||
| 732 | nla_nest_cancel(skb, vfinfo); | ||
| 733 | goto nla_put_failure; | ||
| 734 | } | ||
| 735 | NLA_PUT(skb, IFLA_VF_MAC, sizeof(vf_mac), &vf_mac); | ||
| 736 | NLA_PUT(skb, IFLA_VF_VLAN, sizeof(vf_vlan), &vf_vlan); | ||
| 737 | NLA_PUT(skb, IFLA_VF_TX_RATE, sizeof(vf_tx_rate), &vf_tx_rate); | ||
| 738 | nla_nest_end(skb, vf); | ||
| 710 | } | 739 | } |
| 740 | nla_nest_end(skb, vfinfo); | ||
| 711 | } | 741 | } |
| 712 | if (dev->rtnl_link_ops) { | 742 | if (dev->rtnl_link_ops) { |
| 713 | if (rtnl_link_fill(skb, dev) < 0) | 743 | if (rtnl_link_fill(skb, dev) < 0) |
| @@ -769,12 +799,7 @@ const struct nla_policy ifla_policy[IFLA_MAX+1] = { | |||
| 769 | [IFLA_LINKINFO] = { .type = NLA_NESTED }, | 799 | [IFLA_LINKINFO] = { .type = NLA_NESTED }, |
| 770 | [IFLA_NET_NS_PID] = { .type = NLA_U32 }, | 800 | [IFLA_NET_NS_PID] = { .type = NLA_U32 }, |
| 771 | [IFLA_IFALIAS] = { .type = NLA_STRING, .len = IFALIASZ-1 }, | 801 | [IFLA_IFALIAS] = { .type = NLA_STRING, .len = IFALIASZ-1 }, |
| 772 | [IFLA_VF_MAC] = { .type = NLA_BINARY, | 802 | [IFLA_VFINFO_LIST] = {. type = NLA_NESTED }, |
| 773 | .len = sizeof(struct ifla_vf_mac) }, | ||
| 774 | [IFLA_VF_VLAN] = { .type = NLA_BINARY, | ||
| 775 | .len = sizeof(struct ifla_vf_vlan) }, | ||
| 776 | [IFLA_VF_TX_RATE] = { .type = NLA_BINARY, | ||
| 777 | .len = sizeof(struct ifla_vf_tx_rate) }, | ||
| 778 | }; | 803 | }; |
| 779 | EXPORT_SYMBOL(ifla_policy); | 804 | EXPORT_SYMBOL(ifla_policy); |
| 780 | 805 | ||
| @@ -783,6 +808,19 @@ static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = { | |||
| 783 | [IFLA_INFO_DATA] = { .type = NLA_NESTED }, | 808 | [IFLA_INFO_DATA] = { .type = NLA_NESTED }, |
| 784 | }; | 809 | }; |
| 785 | 810 | ||
| 811 | static const struct nla_policy ifla_vfinfo_policy[IFLA_VF_INFO_MAX+1] = { | ||
| 812 | [IFLA_VF_INFO] = { .type = NLA_NESTED }, | ||
| 813 | }; | ||
| 814 | |||
| 815 | static const struct nla_policy ifla_vf_policy[IFLA_VF_MAX+1] = { | ||
| 816 | [IFLA_VF_MAC] = { .type = NLA_BINARY, | ||
| 817 | .len = sizeof(struct ifla_vf_mac) }, | ||
| 818 | [IFLA_VF_VLAN] = { .type = NLA_BINARY, | ||
| 819 | .len = sizeof(struct ifla_vf_vlan) }, | ||
| 820 | [IFLA_VF_TX_RATE] = { .type = NLA_BINARY, | ||
| 821 | .len = sizeof(struct ifla_vf_tx_rate) }, | ||
| 822 | }; | ||
| 823 | |||
| 786 | struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[]) | 824 | struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[]) |
| 787 | { | 825 | { |
| 788 | struct net *net; | 826 | struct net *net; |
| @@ -812,6 +850,52 @@ static int validate_linkmsg(struct net_device *dev, struct nlattr *tb[]) | |||
| 812 | return 0; | 850 | return 0; |
| 813 | } | 851 | } |
| 814 | 852 | ||
| 853 | static int do_setvfinfo(struct net_device *dev, struct nlattr *attr) | ||
| 854 | { | ||
| 855 | int rem, err = -EINVAL; | ||
| 856 | struct nlattr *vf; | ||
| 857 | const struct net_device_ops *ops = dev->netdev_ops; | ||
| 858 | |||
| 859 | nla_for_each_nested(vf, attr, rem) { | ||
| 860 | switch (nla_type(vf)) { | ||
| 861 | case IFLA_VF_MAC: { | ||
| 862 | struct ifla_vf_mac *ivm; | ||
| 863 | ivm = nla_data(vf); | ||
| 864 | err = -EOPNOTSUPP; | ||
| 865 | if (ops->ndo_set_vf_mac) | ||
| 866 | err = ops->ndo_set_vf_mac(dev, ivm->vf, | ||
| 867 | ivm->mac); | ||
| 868 | break; | ||
| 869 | } | ||
| 870 | case IFLA_VF_VLAN: { | ||
| 871 | struct ifla_vf_vlan *ivv; | ||
| 872 | ivv = nla_data(vf); | ||
| 873 | err = -EOPNOTSUPP; | ||
| 874 | if (ops->ndo_set_vf_vlan) | ||
| 875 | err = ops->ndo_set_vf_vlan(dev, ivv->vf, | ||
| 876 | ivv->vlan, | ||
| 877 | ivv->qos); | ||
| 878 | break; | ||
| 879 | } | ||
| 880 | case IFLA_VF_TX_RATE: { | ||
| 881 | struct ifla_vf_tx_rate *ivt; | ||
| 882 | ivt = nla_data(vf); | ||
| 883 | err = -EOPNOTSUPP; | ||
| 884 | if (ops->ndo_set_vf_tx_rate) | ||
| 885 | err = ops->ndo_set_vf_tx_rate(dev, ivt->vf, | ||
| 886 | ivt->rate); | ||
| 887 | break; | ||
| 888 | } | ||
| 889 | default: | ||
| 890 | err = -EINVAL; | ||
| 891 | break; | ||
| 892 | } | ||
| 893 | if (err) | ||
| 894 | break; | ||
| 895 | } | ||
| 896 | return err; | ||
| 897 | } | ||
| 898 | |||
| 815 | static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, | 899 | static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, |
| 816 | struct nlattr **tb, char *ifname, int modified) | 900 | struct nlattr **tb, char *ifname, int modified) |
| 817 | { | 901 | { |
| @@ -942,40 +1026,17 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, | |||
| 942 | write_unlock_bh(&dev_base_lock); | 1026 | write_unlock_bh(&dev_base_lock); |
| 943 | } | 1027 | } |
| 944 | 1028 | ||
| 945 | if (tb[IFLA_VF_MAC]) { | 1029 | if (tb[IFLA_VFINFO_LIST]) { |
| 946 | struct ifla_vf_mac *ivm; | 1030 | struct nlattr *attr; |
| 947 | ivm = nla_data(tb[IFLA_VF_MAC]); | 1031 | int rem; |
| 948 | err = -EOPNOTSUPP; | 1032 | nla_for_each_nested(attr, tb[IFLA_VFINFO_LIST], rem) { |
| 949 | if (ops->ndo_set_vf_mac) | 1033 | if (nla_type(attr) != IFLA_VF_INFO) |
| 950 | err = ops->ndo_set_vf_mac(dev, ivm->vf, ivm->mac); | 1034 | goto errout; |
| 951 | if (err < 0) | 1035 | err = do_setvfinfo(dev, attr); |
| 952 | goto errout; | 1036 | if (err < 0) |
| 953 | modified = 1; | 1037 | goto errout; |
| 954 | } | 1038 | modified = 1; |
| 955 | 1039 | } | |
| 956 | if (tb[IFLA_VF_VLAN]) { | ||
| 957 | struct ifla_vf_vlan *ivv; | ||
| 958 | ivv = nla_data(tb[IFLA_VF_VLAN]); | ||
| 959 | err = -EOPNOTSUPP; | ||
| 960 | if (ops->ndo_set_vf_vlan) | ||
| 961 | err = ops->ndo_set_vf_vlan(dev, ivv->vf, | ||
| 962 | ivv->vlan, | ||
| 963 | ivv->qos); | ||
| 964 | if (err < 0) | ||
| 965 | goto errout; | ||
| 966 | modified = 1; | ||
| 967 | } | ||
| 968 | err = 0; | ||
| 969 | |||
| 970 | if (tb[IFLA_VF_TX_RATE]) { | ||
| 971 | struct ifla_vf_tx_rate *ivt; | ||
| 972 | ivt = nla_data(tb[IFLA_VF_TX_RATE]); | ||
| 973 | err = -EOPNOTSUPP; | ||
| 974 | if (ops->ndo_set_vf_tx_rate) | ||
| 975 | err = ops->ndo_set_vf_tx_rate(dev, ivt->vf, ivt->rate); | ||
| 976 | if (err < 0) | ||
| 977 | goto errout; | ||
| 978 | modified = 1; | ||
| 979 | } | 1040 | } |
| 980 | err = 0; | 1041 | err = 0; |
| 981 | 1042 | ||
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 0f8caf64caa3..296150b2a62f 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
| @@ -2839,7 +2839,6 @@ static void __tcp_free_md5sig_pool(struct tcp_md5sig_pool * __percpu *pool) | |||
| 2839 | if (p->md5_desc.tfm) | 2839 | if (p->md5_desc.tfm) |
| 2840 | crypto_free_hash(p->md5_desc.tfm); | 2840 | crypto_free_hash(p->md5_desc.tfm); |
| 2841 | kfree(p); | 2841 | kfree(p); |
| 2842 | p = NULL; | ||
| 2843 | } | 2842 | } |
| 2844 | } | 2843 | } |
| 2845 | free_percpu(pool); | 2844 | free_percpu(pool); |
| @@ -2937,25 +2936,40 @@ retry: | |||
| 2937 | 2936 | ||
| 2938 | EXPORT_SYMBOL(tcp_alloc_md5sig_pool); | 2937 | EXPORT_SYMBOL(tcp_alloc_md5sig_pool); |
| 2939 | 2938 | ||
| 2940 | struct tcp_md5sig_pool *__tcp_get_md5sig_pool(int cpu) | 2939 | |
| 2940 | /** | ||
| 2941 | * tcp_get_md5sig_pool - get md5sig_pool for this user | ||
| 2942 | * | ||
| 2943 | * We use percpu structure, so if we succeed, we exit with preemption | ||
| 2944 | * and BH disabled, to make sure another thread or softirq handling | ||
| 2945 | * wont try to get same context. | ||
| 2946 | */ | ||
| 2947 | struct tcp_md5sig_pool *tcp_get_md5sig_pool(void) | ||
| 2941 | { | 2948 | { |
| 2942 | struct tcp_md5sig_pool * __percpu *p; | 2949 | struct tcp_md5sig_pool * __percpu *p; |
| 2943 | spin_lock_bh(&tcp_md5sig_pool_lock); | 2950 | |
| 2951 | local_bh_disable(); | ||
| 2952 | |||
| 2953 | spin_lock(&tcp_md5sig_pool_lock); | ||
| 2944 | p = tcp_md5sig_pool; | 2954 | p = tcp_md5sig_pool; |
| 2945 | if (p) | 2955 | if (p) |
| 2946 | tcp_md5sig_users++; | 2956 | tcp_md5sig_users++; |
| 2947 | spin_unlock_bh(&tcp_md5sig_pool_lock); | 2957 | spin_unlock(&tcp_md5sig_pool_lock); |
| 2948 | return (p ? *per_cpu_ptr(p, cpu) : NULL); | 2958 | |
| 2949 | } | 2959 | if (p) |
| 2960 | return *per_cpu_ptr(p, smp_processor_id()); | ||
| 2950 | 2961 | ||
| 2951 | EXPORT_SYMBOL(__tcp_get_md5sig_pool); | 2962 | local_bh_enable(); |
| 2963 | return NULL; | ||
| 2964 | } | ||
| 2965 | EXPORT_SYMBOL(tcp_get_md5sig_pool); | ||
| 2952 | 2966 | ||
| 2953 | void __tcp_put_md5sig_pool(void) | 2967 | void tcp_put_md5sig_pool(void) |
| 2954 | { | 2968 | { |
| 2969 | local_bh_enable(); | ||
| 2955 | tcp_free_md5sig_pool(); | 2970 | tcp_free_md5sig_pool(); |
| 2956 | } | 2971 | } |
| 2957 | 2972 | EXPORT_SYMBOL(tcp_put_md5sig_pool); | |
| 2958 | EXPORT_SYMBOL(__tcp_put_md5sig_pool); | ||
| 2959 | 2973 | ||
| 2960 | int tcp_md5_hash_header(struct tcp_md5sig_pool *hp, | 2974 | int tcp_md5_hash_header(struct tcp_md5sig_pool *hp, |
| 2961 | struct tcphdr *th) | 2975 | struct tcphdr *th) |
diff --git a/net/sctp/transport.c b/net/sctp/transport.c index 4a368038d46f..165d54e07fcd 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c | |||
| @@ -173,6 +173,10 @@ void sctp_transport_free(struct sctp_transport *transport) | |||
| 173 | del_timer(&transport->T3_rtx_timer)) | 173 | del_timer(&transport->T3_rtx_timer)) |
| 174 | sctp_transport_put(transport); | 174 | sctp_transport_put(transport); |
| 175 | 175 | ||
| 176 | /* Delete the ICMP proto unreachable timer if it's active. */ | ||
| 177 | if (timer_pending(&transport->proto_unreach_timer) && | ||
| 178 | del_timer(&transport->proto_unreach_timer)) | ||
| 179 | sctp_association_put(transport->asoc); | ||
| 176 | 180 | ||
| 177 | sctp_transport_put(transport); | 181 | sctp_transport_put(transport); |
| 178 | } | 182 | } |
