X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=datapath%2Fvport-gre.c;h=2bddc871093205c6442a24e4954c5bd538b47693;hb=882c2399908b0f33f73651ccfc3aaf76a7858ce4;hp=c71cc34d91b1c40fcef201c58d944b04ae2d3a8d;hpb=b28c72ba7c992bcd2f5b65be0799a2d9422df21f;p=openvswitch diff --git a/datapath/vport-gre.c b/datapath/vport-gre.c index c71cc34d..2bddc871 100644 --- a/datapath/vport-gre.c +++ b/datapath/vport-gre.c @@ -44,6 +44,11 @@ * number of options. */ #define GRE_HEADER_SECTION 4 +struct gre_base_hdr { + __be16 flags; + __be16 protocol; +}; + struct mutable_config { struct rcu_head rcu; @@ -55,6 +60,7 @@ struct mutable_config { }; struct gre_vport { + struct rcu_head rcu; struct tbl_node tbl_node; char name[IFNAMSIZ]; @@ -74,34 +80,30 @@ static unsigned int key_remote_ports; static unsigned int local_remote_ports; static unsigned int remote_ports; -static inline struct gre_vport * -gre_vport_priv(const struct vport *vport) +static inline struct gre_vport *gre_vport_priv(const struct vport *vport) { return vport_priv(vport); } -static inline struct vport * -gre_vport_to_vport(const struct gre_vport *gre_vport) +static inline struct vport *gre_vport_to_vport(const struct gre_vport *gre_vport) { return vport_from_priv(gre_vport); } -static inline struct gre_vport * -gre_vport_table_cast(const struct tbl_node *node) +static inline struct gre_vport *gre_vport_table_cast(const struct tbl_node *node) { return container_of(node, struct gre_vport, tbl_node); } /* RCU callback. */ -static void -free_config(struct rcu_head *rcu) +static void free_config(struct rcu_head *rcu) { struct mutable_config *c = container_of(rcu, struct mutable_config, rcu); kfree(c); } -static void -assign_config_rcu(struct vport *vport, struct mutable_config *new_config) +static void assign_config_rcu(struct vport *vport, + struct mutable_config *new_config) { struct gre_vport *gre_vport = gre_vport_priv(vport); struct mutable_config *old_config; @@ -111,8 +113,7 @@ assign_config_rcu(struct vport *vport, struct mutable_config *new_config) call_rcu(&old_config->rcu, free_config); } -static unsigned int * -find_port_pool(const struct mutable_config *mutable) +static unsigned int *find_port_pool(const struct mutable_config *mutable) { if (mutable->port_config.flags & GRE_F_IN_KEY_MATCH) { if (mutable->port_config.saddr) @@ -141,8 +142,7 @@ struct port_lookup_key { /* Modifies 'target' to store the rcu_dereferenced pointer that was used to do * the comparision. */ -static int -port_cmp(const struct tbl_node *node, void *target) +static int port_cmp(const struct tbl_node *node, void *target) { const struct gre_vport *gre_vport = gre_vport_table_cast(node); struct port_lookup_key *lookup = target; @@ -156,14 +156,12 @@ port_cmp(const struct tbl_node *node, void *target) lookup->mutable->port_config.saddr == lookup->vals[LOOKUP_SADDR]; } -static u32 -port_hash(struct port_lookup_key *lookup) +static u32 port_hash(struct port_lookup_key *lookup) { return jhash2(lookup->vals, ARRAY_SIZE(lookup->vals), 0); } -static int -add_port(struct vport *vport) +static int add_port(struct vport *vport) { struct gre_vport *gre_vport = gre_vport_priv(vport); struct port_lookup_key lookup; @@ -204,8 +202,7 @@ add_port(struct vport *vport) return 0; } -static int -del_port(struct vport *vport) +static int del_port(struct vport *vport) { struct gre_vport *gre_vport = gre_vport_priv(vport); int err; @@ -223,9 +220,9 @@ del_port(struct vport *vport) #define FIND_PORT_MATCH (1 << 1) #define FIND_PORT_ANY (FIND_PORT_KEY | FIND_PORT_MATCH) -static struct vport * -find_port(__be32 saddr, __be32 daddr, __be32 key, int port_type, - const struct mutable_config **mutable) +static struct vport *find_port(__be32 saddr, __be32 daddr, __be32 key, + int port_type, + const struct mutable_config **mutable) { struct port_lookup_key lookup; struct tbl *table = rcu_dereference(port_table); @@ -284,8 +281,7 @@ found: return gre_vport_to_vport(gre_vport_table_cast(tbl_node)); } -static bool -check_ipv4_address(__be32 addr) +static bool check_ipv4_address(__be32 addr) { if (ipv4_is_multicast(addr) || ipv4_is_lbcast(addr) || ipv4_is_loopback(addr) || ipv4_is_zeronet(addr)) @@ -294,8 +290,7 @@ check_ipv4_address(__be32 addr) return true; } -static bool -ipv4_should_icmp(struct sk_buff *skb) +static bool ipv4_should_icmp(struct sk_buff *skb) { struct iphdr *old_iph = ip_hdr(skb); @@ -335,9 +330,8 @@ ipv4_should_icmp(struct sk_buff *skb) return true; } -static void -ipv4_build_icmp(struct sk_buff *skb, struct sk_buff *nskb, - unsigned int mtu, unsigned int payload_length) +static void ipv4_build_icmp(struct sk_buff *skb, struct sk_buff *nskb, + unsigned int mtu, unsigned int payload_length) { struct iphdr *iph, *old_iph = ip_hdr(skb); struct icmphdr *icmph; @@ -378,8 +372,7 @@ ipv4_build_icmp(struct sk_buff *skb, struct sk_buff *nskb, } #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) -static bool -ipv6_should_icmp(struct sk_buff *skb) +static bool ipv6_should_icmp(struct sk_buff *skb) { struct ipv6hdr *old_ipv6h = ipv6_hdr(skb); int addr_type; @@ -415,9 +408,8 @@ ipv6_should_icmp(struct sk_buff *skb) return true; } -static void -ipv6_build_icmp(struct sk_buff *skb, struct sk_buff *nskb, unsigned int mtu, - unsigned int payload_length) +static void ipv6_build_icmp(struct sk_buff *skb, struct sk_buff *nskb, + unsigned int mtu, unsigned int payload_length) { struct ipv6hdr *ipv6h, *old_ipv6h = ipv6_hdr(skb); struct icmp6hdr *icmp6h; @@ -455,9 +447,10 @@ ipv6_build_icmp(struct sk_buff *skb, struct sk_buff *nskb, unsigned int mtu, } #endif /* IPv6 */ -static bool -send_frag_needed(struct vport *vport, const struct mutable_config *mutable, - struct sk_buff *skb, unsigned int mtu, __be32 flow_key) +static bool send_frag_needed(struct vport *vport, + const struct mutable_config *mutable, + struct sk_buff *skb, unsigned int mtu, + __be32 flow_key) { unsigned int eth_hdr_len = ETH_HLEN; unsigned int total_length = 0, header_length = 0, payload_length; @@ -554,11 +547,10 @@ send_frag_needed(struct vport *vport, const struct mutable_config *mutable, return true; } -static struct sk_buff * -check_headroom(struct sk_buff *skb, int headroom) +static struct sk_buff *check_headroom(struct sk_buff *skb, int headroom) { if (skb_headroom(skb) < headroom || skb_header_cloned(skb)) { - struct sk_buff *nskb = skb_realloc_headroom(skb, max(headroom, 64)); + struct sk_buff *nskb = skb_realloc_headroom(skb, headroom + 16); if (!nskb) { kfree_skb(skb); return ERR_PTR(-ENOMEM); @@ -576,22 +568,21 @@ check_headroom(struct sk_buff *skb, int headroom) return skb; } -static void -create_gre_header(struct sk_buff *skb, const struct mutable_config *mutable) +static void create_gre_header(struct sk_buff *skb, + const struct mutable_config *mutable) { struct iphdr *iph = ip_hdr(skb); - __be16 *flags = (__be16 *)(iph + 1); - __be16 *protocol = flags + 1; + struct gre_base_hdr *greh = (struct gre_base_hdr *)(iph + 1); __be32 *options = (__be32 *)((u8 *)iph + mutable->tunnel_hlen - GRE_HEADER_SECTION); - *protocol = htons(ETH_P_TEB); - *flags = 0; + greh->protocol = htons(ETH_P_TEB); + greh->flags = 0; /* Work backwards over the options so the checksum is last. */ if (mutable->port_config.out_key || mutable->port_config.flags & GRE_F_OUT_KEY_ACTION) { - *flags |= GRE_KEY; + greh->flags |= GRE_KEY; if (mutable->port_config.flags & GRE_F_OUT_KEY_ACTION) *options = OVS_CB(skb)->tun_id; @@ -602,7 +593,7 @@ create_gre_header(struct sk_buff *skb, const struct mutable_config *mutable) } if (mutable->port_config.flags & GRE_F_OUT_CSUM) { - *flags |= GRE_CSUM; + greh->flags |= GRE_CSUM; *options = 0; *(__sum16 *)options = csum_fold(skb_checksum(skb, @@ -612,8 +603,7 @@ create_gre_header(struct sk_buff *skb, const struct mutable_config *mutable) } } -static int -check_checksum(struct sk_buff *skb) +static int check_checksum(struct sk_buff *skb) { struct iphdr *iph = ip_hdr(skb); __be16 flags = *(__be16 *)(iph + 1); @@ -639,31 +629,29 @@ check_checksum(struct sk_buff *skb) return (csum == 0); } -static int -parse_gre_header(struct iphdr *iph, __be16 *flags, __be32 *key) +static int parse_gre_header(struct iphdr *iph, __be16 *flags, __be32 *key) { /* IP and ICMP protocol handlers check that the IHL is valid. */ - __be16 *flagsp = (__be16 *)((u8 *)iph + (iph->ihl << 2)); - __be16 *protocol = flagsp + 1; - __be32 *options = (__be32 *)(protocol + 1); + struct gre_base_hdr *greh = (struct gre_base_hdr *)((u8 *)iph + (iph->ihl << 2)); + __be32 *options = (__be32 *)(greh + 1); int hdr_len; - *flags = *flagsp; + *flags = greh->flags; - if (*flags & (GRE_VERSION | GRE_ROUTING)) + if (greh->flags & (GRE_VERSION | GRE_ROUTING)) return -EINVAL; - if (*protocol != htons(ETH_P_TEB)) + if (greh->protocol != htons(ETH_P_TEB)) return -EINVAL; hdr_len = GRE_HEADER_SECTION; - if (*flags & GRE_CSUM) { + if (greh->flags & GRE_CSUM) { hdr_len += GRE_HEADER_SECTION; options++; } - if (*flags & GRE_KEY) { + if (greh->flags & GRE_KEY) { hdr_len += GRE_HEADER_SECTION; *key = *options; @@ -671,14 +659,13 @@ parse_gre_header(struct iphdr *iph, __be16 *flags, __be32 *key) } else *key = 0; - if (*flags & GRE_SEQ) + if (greh->flags & GRE_SEQ) hdr_len += GRE_HEADER_SECTION; return hdr_len; } -static inline u8 -ecn_encapsulate(u8 tos, struct sk_buff *skb) +static inline u8 ecn_encapsulate(u8 tos, struct sk_buff *skb) { u8 inner; @@ -694,8 +681,7 @@ ecn_encapsulate(u8 tos, struct sk_buff *skb) return INET_ECN_encapsulate(tos, inner); } -static inline void -ecn_decapsulate(u8 tos, struct sk_buff *skb) +static inline void ecn_decapsulate(u8 tos, struct sk_buff *skb) { if (INET_ECN_is_ce(tos)) { __be16 protocol = skb->protocol; @@ -729,11 +715,10 @@ ecn_decapsulate(u8 tos, struct sk_buff *skb) } } -static struct sk_buff * -handle_gso(struct sk_buff *skb) +static struct sk_buff *handle_gso(struct sk_buff *skb) { if (skb_is_gso(skb)) { - struct sk_buff *nskb = skb_gso_segment(skb, NETIF_F_SG); + struct sk_buff *nskb = skb_gso_segment(skb, 0); dev_kfree_skb(skb); return nskb; @@ -742,8 +727,7 @@ handle_gso(struct sk_buff *skb) return skb; } -static int -handle_csum_offload(struct sk_buff *skb) +static int handle_csum_offload(struct sk_buff *skb) { if (skb->ip_summed == CHECKSUM_PARTIAL) return skb_checksum_help(skb); @@ -754,8 +738,7 @@ handle_csum_offload(struct sk_buff *skb) } /* Called with rcu_read_lock. */ -static void -gre_err(struct sk_buff *skb, u32 info) +static void gre_err(struct sk_buff *skb, u32 info) { struct vport *vport; const struct mutable_config *mutable; @@ -871,8 +854,7 @@ out: } /* Called with rcu_read_lock. */ -static int -gre_rcv(struct sk_buff *skb) +static int gre_rcv(struct sk_buff *skb) { struct vport *vport; const struct mutable_config *mutable; @@ -937,10 +919,9 @@ error: return 0; } -static int -build_packet(struct vport *vport, const struct mutable_config *mutable, - struct iphdr *iph, struct rtable *rt, int max_headroom, int mtu, - struct sk_buff *skb) +static int build_packet(struct vport *vport, const struct mutable_config *mutable, + struct iphdr *iph, struct rtable *rt, int max_headroom, + int mtu, struct sk_buff *skb) { int err; struct iphdr *new_iph; @@ -1014,8 +995,7 @@ error: return 0; } -static int -gre_send(struct vport *vport, struct sk_buff *skb) +static int gre_send(struct vport *vport, struct sk_buff *skb) { struct gre_vport *gre_vport = gre_vport_priv(vport); const struct mutable_config *mutable = rcu_dereference(gre_vport->mutable); @@ -1167,8 +1147,7 @@ static struct net_protocol gre_protocol_handlers = { .err_handler = gre_err, }; -static int -gre_init(void) +static int gre_init(void) { int err; @@ -1179,16 +1158,14 @@ gre_init(void) return err; } -static void -gre_exit(void) +static void gre_exit(void) { tbl_destroy(port_table, NULL); inet_del_protocol(&gre_protocol_handlers, IPPROTO_GRE); } -static int -set_config(const struct vport *cur_vport, struct mutable_config *mutable, - const void __user *uconfig) +static int set_config(const struct vport *cur_vport, + struct mutable_config *mutable, const void __user *uconfig) { const struct vport *old_vport; const struct mutable_config *old_mutable; @@ -1229,8 +1206,7 @@ set_config(const struct vport *cur_vport, struct mutable_config *mutable, return 0; } -static struct vport * -gre_create(const char *name, const void __user *config) +static struct vport *gre_create(const char *name, const void __user *config) { struct vport *vport; struct gre_vport *gre_vport; @@ -1273,8 +1249,7 @@ error: return ERR_PTR(err); } -static int -gre_modify(struct vport *vport, const void __user *config) +static int gre_modify(struct vport *vport, const void __user *config) { struct gre_vport *gre_vport = gre_vport_priv(vport); struct mutable_config *mutable; @@ -1325,8 +1300,15 @@ error: return err; } -static int -gre_destroy(struct vport *vport) +static void free_port(struct rcu_head *rcu) +{ + struct gre_vport *gre_vport = container_of(rcu, struct gre_vport, rcu); + + kfree(gre_vport->mutable); + vport_free(gre_vport_to_vport(gre_vport)); +} + +static int gre_destroy(struct vport *vport) { struct gre_vport *gre_vport = gre_vport_priv(vport); int port_type; @@ -1344,14 +1326,12 @@ gre_destroy(struct vport *vport) gre_vport->mutable->port_config.in_key, port_type, &old_mutable)) del_port(vport); - kfree(gre_vport->mutable); - vport_free(vport); + call_rcu(&gre_vport->rcu, free_port); return 0; } -static int -gre_set_mtu(struct vport *vport, int mtu) +static int gre_set_mtu(struct vport *vport, int mtu) { struct gre_vport *gre_vport = gre_vport_priv(vport); struct mutable_config *mutable; @@ -1366,8 +1346,7 @@ gre_set_mtu(struct vport *vport, int mtu) return 0; } -static int -gre_set_addr(struct vport *vport, const unsigned char *addr) +static int gre_set_addr(struct vport *vport, const unsigned char *addr) { struct gre_vport *gre_vport = gre_vport_priv(vport); struct mutable_config *mutable; @@ -1383,22 +1362,19 @@ gre_set_addr(struct vport *vport, const unsigned char *addr) } -static const char * -gre_get_name(const struct vport *vport) +static const char *gre_get_name(const struct vport *vport) { const struct gre_vport *gre_vport = gre_vport_priv(vport); return gre_vport->name; } -static const unsigned char * -gre_get_addr(const struct vport *vport) +static const unsigned char *gre_get_addr(const struct vport *vport) { const struct gre_vport *gre_vport = gre_vport_priv(vport); return rcu_dereference(gre_vport->mutable)->eth_addr; } -static int -gre_get_mtu(const struct vport *vport) +static int gre_get_mtu(const struct vport *vport) { const struct gre_vport *gre_vport = gre_vport_priv(vport); return rcu_dereference(gre_vport->mutable)->mtu;