+ if (a[OVS_TUNNEL_ATTR_TOS]) {
+ mutable->tos = nla_get_u8(a[OVS_TUNNEL_ATTR_TOS]);
+ /* Reject ToS config with ECN bits set. */
+ if (mutable->tos & INET_ECN_MASK)
+ return -EINVAL;
+ }
+
+ if (a[OVS_TUNNEL_ATTR_TTL])
+ mutable->ttl = nla_get_u8(a[OVS_TUNNEL_ATTR_TTL]);
+
+ if (!a[OVS_TUNNEL_ATTR_IN_KEY]) {
+ mutable->key.tunnel_type |= TNL_T_KEY_MATCH;
+ mutable->flags |= TNL_F_IN_KEY_MATCH;
+ } else {
+ mutable->key.tunnel_type |= TNL_T_KEY_EXACT;
+ mutable->key.in_key = nla_get_be64(a[OVS_TUNNEL_ATTR_IN_KEY]);
+ }
+
+ if (!a[OVS_TUNNEL_ATTR_OUT_KEY])
+ mutable->flags |= TNL_F_OUT_KEY_ACTION;
+ else
+ mutable->out_key = nla_get_be64(a[OVS_TUNNEL_ATTR_OUT_KEY]);
+
+ mutable->mlink = 0;
+ if (ipv4_is_multicast(mutable->key.daddr)) {
+ struct net_device *dev;
+ struct rtable *rt;
+ __be32 saddr = mutable->key.saddr;
+
+ rt = find_route(port_key_get_net(&mutable->key),
+ &saddr, mutable->key.daddr,
+ tnl_ops->ipproto, mutable->tos);
+ if (IS_ERR(rt))
+ return -EADDRNOTAVAIL;
+ dev = rt_dst(rt).dev;
+ ip_rt_put(rt);
+ if (__in_dev_get_rtnl(dev) == NULL)
+ return -EADDRNOTAVAIL;
+ mutable->mlink = dev->ifindex;
+ ip_mc_inc_group(__in_dev_get_rtnl(dev), mutable->key.daddr);
+ }
+
+out:
+ old_vport = port_table_lookup(&mutable->key, &old_mutable);